Repository: spyder-ide/spyder

Issue:
Calltip has unbound local error
## Description

### What steps will reproduce the problem?

<!--- You can use Markdown here --->

I was writing in the console:
`a[sorted(a.keys(|)]` where `|` is the cursor. The crash happened just after typing `(`.

### Traceback
```python-traceback
  File "/Users/quentinpeter/pyscripts/qtconsole/qtconsole/base_frontend_mixin.py", line 138, in _dispatch
    handler(msg)
  File "/Users/quentinpeter/pyscripts/spyder/spyder/plugins/ipythonconsole/widgets/help.py", line 176, in _handle_inspect_reply
    text_new_line=new_line
  File "/Users/quentinpeter/pyscripts/spyder/spyder/widgets/mixins.py", line 573, in show_calltip
    inspect_word=inspect_word,
UnboundLocalError: local variable 'inspect_word' referenced before assignment
```

## Versions

* Spyder version: 4.0.0.dev0 cd9e760fa
* Python version: 3.7.5
* Qt version: 5.12.6
* PyQt5 version: 5.12.3
* Operating System: Darwin 19.0.0

### Dependencies

```
cloudpickle >=0.5.0          :  1.2.2 (OK)
pygments >=2.0               :  2.4.2 (OK)
qtconsole >=4.6.0            :  4.7.0.dev0 (OK)
nbconvert >=4.0              :  5.6.1 (OK)
sphinx >=0.6.6               :  2.2.1 (OK)
pylint >=0.25                :  2.4.4 (OK)
psutil >=0.3                 :  5.6.5 (OK)
qtawesome >=0.5.7            :  0.6.0 (OK)
qtpy >=1.5.0                 :  1.9.0 (OK)
pickleshare >=0.4            :  0.7.5 (OK)
zmq >=17                     :  18.1.1 (OK)
chardet >=2.0.0              :  3.0.4 (OK)
numpydoc >=0.6.0             :  0.9.1 (OK)
spyder_kernels >=1.8.0;<2.0.0:  1.9.0.dev0 (OK)
qdarkstyle >=2.7             :  2.7 (OK)
atomicwrites >=1.2.0         :  1.3.0 (OK)
diff_match_patch >=20181111  :  20181111 (OK)
intervaltree                 :  None (OK)
watchdog                     :  None (OK)
keyring                      :  None (OK)
pexpect >=4.4.0              :  4.7.0 (OK)
pympler                      :  None (OK)
sympy >=0.7.3                :  None (NOK)
cython >=0.21                :  None (NOK)
IPython >=4.0                :  7.9.0 (OK)
matplotlib >=2.0.0           :  3.1.2 (OK)
pandas >=0.13.1              :  0.25.3 (OK)
numpy >=1.7                  :  1.17.4 (OK)
scipy >=0.17.0               :  1.3.3 (OK)
pyls >=0.31.1;<0.32.0        :  0.31.1 (OK)
applaunchservices >=0.1.7    :  0.2.1 (OK)
```



Discussion:

Resolving patch:
diff --git a/spyder/widgets/mixins.py b/spyder/widgets/mixins.py
--- a/spyder/widgets/mixins.py
+++ b/spyder/widgets/mixins.py
@@ -548,7 +548,7 @@ def show_calltip(self, signature, parameter=None, documentation=None,
         # Find position of calltip
         point = self._calculate_position()
         signature = signature.strip()
-
+        inspect_word = None
         language = getattr(self, 'language', language).lower()
         if language == 'python' and signature:
             inspect_word = signature.split('(')[0]


Test patch:
diff --git a/spyder/plugins/ipythonconsole/tests/test_ipythonconsole.py b/spyder/plugins/ipythonconsole/tests/test_ipythonconsole.py
--- a/spyder/plugins/ipythonconsole/tests/test_ipythonconsole.py
+++ b/spyder/plugins/ipythonconsole/tests/test_ipythonconsole.py
@@ -180,6 +180,7 @@ def __getattr__(self, attr):
     # Close
     console.closing_plugin()
     console.close()
+    window.close()
 
 
 # =============================================================================
@@ -1539,5 +1540,27 @@ def test_pdb_ignore_lib(ipyconsole, qtbot):
     assert 'iostream.py' not in control.toPlainText()
 
 
+@flaky(max_runs=3)
+@pytest.mark.skipif(sys.platform == 'darwin', reason="Times out on macOS")
+def test_calltip(ipyconsole, qtbot):
+    """
+    Test Calltip.
+
+    See spyder-ide/spyder#10842
+    """
+    shell = ipyconsole.get_current_shellwidget()
+    qtbot.waitUntil(lambda: shell._prompt_html is not None,
+                    timeout=SHELL_TIMEOUT)
+
+    # Give focus to the widget that's going to receive clicks
+    control = ipyconsole.get_focus_widget()
+    control.setFocus()
+    with qtbot.waitSignal(shell.executed):
+        shell.execute('a = {"a": 1}')
+    qtbot.keyClicks(control, 'a.keys(', delay=100)
+    qtbot.wait(1000)
+    assert control.calltip_widget.isVisible()
+
+
 if __name__ == "__main__":
     pytest.main()