Repository: spyder-ide/spyder

Issue:
Error for calltip with empty signature
## Description

### What steps will reproduce the problem?

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

import os

os.getcwd( -> triggers calltip but an error raises


### Traceback
```python-traceback
  File "C:\Users\Daniel\Anaconda3\envs\spyder4\lib\site-packages\qtconsole\base_frontend_mixin.py", line 138, in _dispatch
    handler(msg)
  File "C:\Users\Daniel\Desktop\Spyder\spyder\spyder\plugins\ipythonconsole\widgets\help.py", line 141, in _handle_inspect_reply
    documentation = self.get_documentation(content)
  File "C:\Users\Daniel\Desktop\Spyder\spyder\spyder\plugins\ipythonconsole\widgets\help.py", line 46, in get_documentation
    documentation = text.split(signature)
ValueError: empty separator
```

## Versions

* Spyder version: 4.0.0.dev0 eb70e6b6d
* Python version: 3.7.3
* Qt version: 5.9.6
* PyQt5 version: 5.9.2
* Operating System: Windows 8.1

### Dependencies

```
pygments >=2.0     :  2.4.0 (OK)
qdarkstyle >=2.6.4 :  2.6.8 (OK)
sphinx >=0.6.6     :  2.0.1 (OK)
pyls >=0.19.0;<0.25:  0.24.0 (OK)
nbconvert >=4.0    :  5.5.0 (OK)
pandas >=0.13.1    :  0.24.2 (OK)
numpy >=1.7        :  1.16.3 (OK)
sympy >=0.7.3      :  1.4 (OK)
cython >=0.21      :  0.29.7 (OK)
qtconsole >=4.2.0  :  4.5.1 (OK)
IPython >=4.0      :  7.5.0 (OK)
matplotlib >=2.0.0 :  3.0.3 (OK)
pylint >=0.25      :  2.3.1 (OK)
```



Discussion:
Thanks for reporting @dalthviz will fix it now
Hi @dalthviz sorry, I thought this was related to the code editor. I think you have more xp with the ipython console :-p. Could you fix it?

---
Also if I try doing on the ipython console

```python
import subprocess
subprocess.Popen(
```

I am getting

```python-traceback
  File "/Users/gpena-castellanos/anaconda2/envs/spyder/lib/python2.7/site-packages/qtconsole/base_frontend_mixin.py", line 138, in _dispatch
    handler(msg)
  File "/Users/gpena-castellanos/Dropbox (Personal)/develop/quansight/spyder/spyder/plugins/ipythonconsole/widgets/help.py", line 146, in _handle_inspect_reply
    language=self.language_name,
AttributeError: 'ShellWidget' object has no attribute 'language_name'
```

@goanpeca, you need to update qtconsole to fix that error.
Right I forgot
@goanpeca no worries, actually I think the error is part of the changes I made to show documentation in the calltips of the IPython Console, so I will work on it :+1: 
Thanks!

Resolving patch:
diff --git a/spyder/plugins/ipythonconsole/plugin.py b/spyder/plugins/ipythonconsole/plugin.py
--- a/spyder/plugins/ipythonconsole/plugin.py
+++ b/spyder/plugins/ipythonconsole/plugin.py
@@ -66,7 +66,7 @@
 dependencies.add("cython", _("Run Cython files in the IPython Console"),
                  required_version=CYTHON_REQVER, optional=True)
 
-QTCONSOLE_REQVER = ">=4.2.0"
+QTCONSOLE_REQVER = ">=4.5.0"
 dependencies.add("qtconsole", _("Integrate the IPython console"),
                  required_version=QTCONSOLE_REQVER)
 
diff --git a/spyder/plugins/ipythonconsole/widgets/help.py b/spyder/plugins/ipythonconsole/widgets/help.py
--- a/spyder/plugins/ipythonconsole/widgets/help.py
+++ b/spyder/plugins/ipythonconsole/widgets/help.py
@@ -13,7 +13,7 @@
 
 import re
 
-from qtconsole.ansi_code_processor import ANSI_OR_SPECIAL_PATTERN
+from qtconsole.ansi_code_processor import ANSI_OR_SPECIAL_PATTERN, ANSI_PATTERN
 from qtconsole.rich_jupyter_widget import RichJupyterWidget
 from qtpy.QtCore import QEventLoop
 from spyder_kernels.utils.dochelpers import (getargspecfromtext,
@@ -38,14 +38,20 @@ def clean_invalid_var_chars(self, var):
         return re.sub(r'\W|^(?=\d)', '_', var)
 
     def get_documentation(self, content):
-        """Get documentation fron inspect reply content."""
+        """Get documentation from inspect reply content."""
         data = content.get('data', {})
         text = data.get('text/plain', '')
-        signature = self.get_signature(content).split('(')[-1]
         if text:
-            documentation = text.split(signature)
-            if len(documentation) > 1:
-                return documentation[-1]
+            text = re.compile(ANSI_PATTERN).sub('', text)
+            signature = self.get_signature(content).split('(')[-1]
+            if signature:
+                documentation = text.split(signature)
+                if len(documentation) > 1:
+                    return documentation[-1].split('Type:')[0]
+            else:
+                return text.split('Docstring:')[-1].split('Type:')[0]
+        else:
+            return ''
 
     def get_signature(self, content):
         """Get signature from inspect reply content"""
@@ -62,15 +68,17 @@ def get_signature(self, content):
                 name = self.clean_invalid_var_chars(name)
             except:
                 pass
-            text = text.split('Docstring:')[-1]
-            argspec = getargspecfromtext(text)
+
+            docstring_text = text.split('Docstring:')[-1]
+            argspec = getargspecfromtext(docstring_text)
             if argspec:
                 # This covers cases like np.abs, whose docstring is
                 # the same as np.absolute and because of that a proper
                 # signature can't be obtained correctly
                 signature = name + argspec
             else:
-                signature = getsignaturefromtext(text, name)
+                signature = getsignaturefromtext(docstring_text, name)
+
             # Remove docstring for uniformity with editor
             signature = signature.split('Docstring:')[0]
 
@@ -139,10 +147,9 @@ def _handle_inspect_reply(self, rep):
             if content.get('status') == 'ok' and content.get('found', False):
                 signature = self.get_signature(content)
                 documentation = self.get_documentation(content)
-                if signature:
-                    self._control.show_calltip(
-                        signature,
-                        documentation=documentation,
-                        language=self.language_name,
-                        max_lines=5
-                    )
+                self._control.show_calltip(
+                    signature,
+                    documentation=documentation,
+                    language=self.language_name,
+                    max_lines=7
+                )


Test patch: