Repository: spyder-ide/spyder

Issue:
Help is not displaying single-line docstrings



Discussion:
Kite hover was implemented successfully on 605422f78145f42df24c2283501c37e1588d75a8, and it is working since Spyder 4.0.
But is it connected to the Help pane?
Yes, because the connection is done on a higher level
Please tests that this is effectively working!
I think the integration with our Help pane isn't working (when using the shortcut `Ctrl+I`):

![help](https://user-images.githubusercontent.com/16781833/75368417-b6e12f00-588f-11ea-9edd-d0a92e48de0f.gif)

Kite version: `1.2020.211.0`
Installed a recent version of Kite (`1.2020.221.0`), the same behavior persists.
![imagen](https://user-images.githubusercontent.com/1878982/75389852-40efbe80-58b5-11ea-89f6-cb6a8e5b7528.png)

For me, it is working on PyTorch
~~Maybe it's something with Windows then?~~ Just in case the `tensorflow` code I tried is this one:

```python
import tensorflow as tf
mnist = tf.keras.datasets.mnist

(x_train, y_train), (x_test, y_test) = mnist.load_data()
x_train, x_test = x_train / 255.0, x_test / 255.0

model = tf.keras.models.Sequential([
  tf.keras.layers.Flatten(input_shape=(28, 28)),
  tf.keras.layers.Dense(128, activation='relu'),
  tf.keras.layers.Dropout(0.2),
  tf.keras.layers.Dense(10)
])
```

### Setup
Spyder: a44ae79d1
OS: Windows 10
Python: 3.6.10
Package list:
<details>

```

# Name                    Version                   Build  Channel
_tflow_select             2.2.0                     eigen
absl-py                   0.9.0                    py36_0
alabaster                 0.7.12                   py36_0
applaunchservices         0.2.1                      py_0
argh                      0.26.2                   py36_0
asn1crypto                1.3.0                    py36_0
astor                     0.8.0                    py36_0
astroid                   2.3.3                    py36_0
atomicwrites              1.3.0                    py36_1
attrs                     19.3.0                     py_0
autopep8                  1.4.4                      py_0
babel                     2.8.0                      py_0
backcall                  0.1.0                    py36_0
bcrypt                    3.1.7            py36he774522_0
blas                      1.0                         mkl
bleach                    3.1.0                    py36_0
blinker                   1.4                      py36_0
ca-certificates           2020.1.1                      0
cachetools                3.1.1                      py_0
certifi                   2019.11.28               py36_0
cffi                      1.14.0           py36h7a1dbc1_0
chardet                   3.0.4                 py36_1003
click                     7.0                      py36_0
cloudpickle               1.3.0                      py_0
colorama                  0.4.3                      py_0
coverage                  4.5.4            py36he774522_0
cryptography              2.8              py36h7a1dbc1_0
cycler                    0.10.0           py36h009560c_0
cython                    0.29.15          py36ha925a31_0
decorator                 4.4.1                      py_0
defusedxml                0.6.0                      py_0
diff-match-patch          20181111                   py_0
docutils                  0.16                     py36_0
entrypoints               0.3                      py36_0
fastcache                 1.1.0            py36he774522_0
flake8                    3.7.9                    py36_0
flaky                     3.6.1                      py_0
freetype                  2.9.1                ha9979f8_1
future                    0.18.2                   py36_0
gast                      0.2.2                    py36_0
google-auth               1.11.2                     py_0
google-auth-oauthlib      0.4.1                      py_2
google-pasta              0.1.8                      py_0
grpcio                    1.27.2           py36h351948d_0
h5py                      2.10.0           py36h5e291fa_0
hdf5                      1.10.4               h7ebc959_0
icc_rt                    2019.0.0             h0cc432a_1
icu                       58.2                 ha66f8fd_1
idna                      2.8                      py36_0
imagesize                 1.2.0                      py_0
importlib_metadata        1.5.0                    py36_0
intel-openmp              2020.0                      166
intervaltree              3.0.2                      py_0
ipykernel                 5.1.4            py36h39e3cac_0
ipython                   7.12.0           py36h5ca1d4c_0
ipython_genutils          0.2.0                    py36_0
isort                     4.3.21                   py36_0
jedi                      0.14.1                   py36_0
jinja2                    2.11.1                     py_0
jpeg                      9b                   hb83a4c4_2
jsonschema                3.2.0                    py36_0
jupyter_client            5.3.4                    py36_0
jupyter_core              4.6.1                    py36_0
keras-applications        1.0.8                      py_0
keras-preprocessing       1.1.0                      py_1
keyring                   21.1.0                   py36_0
kiwisolver                1.1.0            py36ha925a31_0
lazy-object-proxy         1.4.3            py36he774522_0
libpng                    1.6.37               h2a8f88b_0
libprotobuf               3.11.4               h7bd577a_0
libsodium                 1.0.16               h9d3ae62_0
libtiff                   4.1.0                h56a325e_0
markdown                  3.1.1                    py36_0
markupsafe                1.1.1            py36he774522_0
matplotlib                3.1.3                    py36_0
matplotlib-base           3.1.3            py36h64f37c6_0
mccabe                    0.6.1                    py36_1
mistune                   0.8.4            py36he774522_0
mkl                       2020.0                      166
mkl-service               2.3.0            py36hb782905_0
mkl_fft                   1.0.15           py36h14836fe_0
mkl_random                1.1.0            py36h675688f_0
mock                      4.0.1                      py_0
more-itertools            8.2.0                      py_0
mpmath                    1.1.0                    py36_0
nbconvert                 5.6.1                    py36_0
nbformat                  5.0.4                      py_0
numpy                     1.18.1           py36h93ca92e_0
numpy-base                1.18.1           py36hc3f5095_1
numpydoc                  0.9.2                      py_0
oauthlib                  3.1.0                      py_0
olefile                   0.46                     py36_0
openssl                   1.1.1d               he774522_4
opt_einsum                3.1.0                      py_0
packaging                 20.1                       py_0
pandas                    1.0.1            py36h47e9c7a_0
pandoc                    2.2.3.2                       0
pandocfilters             1.4.2                    py36_1
paramiko                  2.7.1                      py_0
parso                     0.5.2                      py_0
pathtools                 0.1.2                      py_1
pexpect                   4.8.0                    py36_0
pickleshare               0.7.5                    py36_0
pillow                    7.0.0            py36hcc1f983_0
pip                       20.0.2                   py36_1
pluggy                    0.13.1                   py36_0
prompt_toolkit            3.0.3                      py_0
protobuf                  3.11.4           py36h33f27b4_0
psutil                    5.6.7            py36he774522_0
py                        1.8.1                      py_0
pyasn1                    0.4.8                      py_0
pyasn1-modules            0.2.7                      py_0
pycodestyle               2.5.0                    py36_0
pycparser                 2.19                     py36_0
pydocstyle                4.0.1                      py_0
pyflakes                  2.1.1                    py36_0
pygments                  2.5.2                      py_0
pyjwt                     1.7.1                    py36_0
pylint                    2.4.4                    py36_0
pynacl                    1.3.0            py36h62dcd97_0
pyopenssl                 19.1.0                   py36_0
pyparsing                 2.4.6                      py_0
pyqt                      5.9.2            py36h6538335_2
pyreadline                2.1                      py36_1
pyrsistent                0.15.7           py36he774522_0
pysocks                   1.7.1                    py36_0
pytest                    4.6.2                    py36_0
pytest-cov                2.8.1                      py_0
pytest-faulthandler       1.6.0                    py36_0    spyder-ide
pytest-lazy-fixture       0.5.2                      py_0    spyder-ide
pytest-mock               1.13.0                     py_1
pytest-ordering           0.6                        py_0    spyder-ide
pytest-qt                 3.2.1                      py_0    spyder-ide
python                    3.6.10               h9f7ef89_0
python-dateutil           2.8.1                      py_0
python-jsonrpc-server     0.3.4                      py_0
python-language-server    0.31.7                   py36_0
pytz                      2019.3                     py_0
pywin32                   227              py36he774522_1
pywin32-ctypes            0.2.0                 py36_1000
pyxdg                     0.26                       py_0
pyyaml                    5.3              py36he774522_0
pyzmq                     18.1.1           py36ha925a31_0
qdarkstyle                2.8                        py_0
qt                        5.9.7            vc14h73c81de_0
qtawesome                 0.6.1                      py_0
qtconsole                 4.6.0                      py_1
qtpy                      1.9.0                      py_0
requests                  2.22.0                   py36_1
requests-oauthlib         1.3.0                      py_0
rope                      0.16.0                     py_0
rsa                       4.0                        py_0
scipy                     1.4.1            py36h9439919_0
setuptools                45.2.0                   py36_0
sip                       4.19.8           py36h6538335_0
six                       1.14.0                   py36_0
snowballstemmer           2.0.0                      py_0
sortedcontainers          2.1.0                    py36_0
sphinx                    2.4.0                      py_0
sphinxcontrib-applehelp   1.0.1                      py_0
sphinxcontrib-devhelp     1.0.1                      py_0
sphinxcontrib-htmlhelp    1.0.2                      py_0
sphinxcontrib-jsmath      1.0.1                      py_0
sphinxcontrib-qthelp      1.0.2                      py_0
sphinxcontrib-serializinghtml 1.1.3                      py_0
spyder-kernels            1.8.1                    py36_0
sqlite                    3.31.1               he774522_0
sympy                     1.5.1                    py36_0
tensorboard               2.1.0                     py3_0
tensorflow                2.1.0           eigen_py36hdbbabfe_0
tensorflow-base           2.1.0           eigen_py36h49b2757_0
tensorflow-estimator      2.1.0              pyhd54b08b_0
termcolor                 1.1.0                    py36_1
testpath                  0.4.4                      py_0
tk                        8.6.8                hfa6e2cd_0
tornado                   6.0.3            py36he774522_3
traitlets                 4.3.3                    py36_0
typed-ast                 1.4.1            py36he774522_0
ujson                     1.35             py36hfa6e2cd_0
urllib3                   1.25.8                   py36_0
vc                        14.1                 h0510ff6_4
vs2015_runtime            14.16.27012          hf0eaf9b_1
watchdog                  0.10.2                   py36_0
wcwidth                   0.1.8                      py_0
webencodings              0.5.1                    py36_1
werkzeug                  0.14.1                   py36_0
wheel                     0.34.2                   py36_0
win_inet_pton             1.1.0                    py36_0
wincertstore              0.2              py36h7fe50ca_0
wrapt                     1.11.2           py36he774522_0
xz                        5.2.4                h2fa13f4_4
yaml                      0.1.7                hc54c509_2
yapf                      0.28.0                     py_0
zeromq                    4.3.1                h33f27b4_3
zipp                      2.2.0                      py_0
zlib                      1.2.11               h62dcd97_3
zstd                      1.3.7                h508b16e_0

```

</details>

Edit: Testing a little bit, seems that the documentation and completion for `nn.Linear` is available even if you have Kite disabled (I can get the documentation of `nn.Linear` using just the LSP)
> Edit: Testing a little bit, seems that the documentation and completion for nn.Linear is available even if you have Kite disabled (I can get the documentation of nn.Linear using just the LSP)

I thought that was the case. Thanks @dalthviz for confirming it.

@andfoy, I think you need to add an additional request our Kite client to ask it for documentation. That was not implemented before but it should be now in its latest version.
![imagen](https://user-images.githubusercontent.com/1878982/75400528-8ae49e80-58cd-11ea-9248-ad21827733d8.png)


It seems like we're implementing the hover call as it should:

![imagen](https://user-images.githubusercontent.com/1878982/75400567-a51e7c80-58cd-11ea-8ddc-b7d4cadf872b.png)

> I thought that was the case. Thanks @dalthviz for confirming it.

With respect to the ``nn.Linear`` example, it seems that the docstrings were improved in PyTorch due to the inclusion of ``.pyi`` files. For instance, here's another example with OpenCV:

![imagen](https://user-images.githubusercontent.com/1878982/75400766-2f66e080-58ce-11ea-8fad-9daf141439cc.png)
 
As @andfoy says seems that we already have the implementation for the hover endpoint and we are getting some docstring from `report.description_text`:

![image](https://user-images.githubusercontent.com/16781833/75400785-3ee62980-58ce-11ea-89ee-95e8a97b1315.png)

But seems like sometimes the docstring isn't being rendered in the Help pane (the docstring that should be rendered is the same that is shown in the tooltip while hovering something) maybe a validation of length to render something exists?: 

![hover](https://user-images.githubusercontent.com/16781833/75400986-cd5aab00-58ce-11ea-8d62-a4bf7616aa8b.png)

> But seems like sometimes the docstring isn't being rendered in the Help pane (the docstring that should be rendered is the same that is shown in the tooltip while hovering something) maybe a validation of length to render something exists?:

It seems that it happens with docstrings of a single line:

![imagen](https://user-images.githubusercontent.com/1878982/75401414-195a1f80-58d0-11ea-9abe-8c7c845dfed8.png)

And also, it seems that it is also ignoring the first line whenever a function declaration is not included as part of the docstring:

![imagen](https://user-images.githubusercontent.com/1878982/75401474-44dd0a00-58d0-11ea-959d-855369a2a2a1.png)


Resolving patch:
diff --git a/spyder/plugins/completion/kite/providers/document.py b/spyder/plugins/completion/kite/providers/document.py
--- a/spyder/plugins/completion/kite/providers/document.py
+++ b/spyder/plugins/completion/kite/providers/document.py
@@ -198,7 +198,7 @@ def request_hover(self, params):
         logger.debug(path)
         if os.name == 'nt':
             path = path.replace('::', ':')
-            path = 'windows:' + path
+            path = ':windows:' + path
         request = {
             'filename': path,
             'hash': md5,
diff --git a/spyder/plugins/editor/widgets/editor.py b/spyder/plugins/editor/widgets/editor.py
--- a/spyder/plugins/editor/widgets/editor.py
+++ b/spyder/plugins/editor/widgets/editor.py
@@ -2623,20 +2623,23 @@ def send_to_help(self, name, signature, force=False):
             return
         if self.help is not None \
           and (force or self.help.dockwidget.isVisible()):
+            editor = self.get_current_editor()
+            language = editor.language.lower()
             signature = to_text_string(signature)
             signature = unicodedata.normalize("NFKD", signature)
             parts = signature.split('\n\n')
             definition = parts[0]
             documentation = '\n\n'.join(parts[1:])
             args = ''
-            if '(' in definition:
+            if '(' in definition and language == 'python':
                 args = definition[definition.find('('):]
+            else:
+                documentation = signature
 
             doc = {'obj_text': '', 'name': name,
                    'argspec': args, 'note': '',
                    'docstring': documentation}
             self.help.set_editor_doc(doc, force_refresh=force)
-            editor = self.get_current_editor()
             editor.setFocus()
 
     def new(self, filename, encoding, text, default_content=False,


Test patch:
diff --git a/spyder/app/tests/test_mainwindow.py b/spyder/app/tests/test_mainwindow.py
--- a/spyder/app/tests/test_mainwindow.py
+++ b/spyder/app/tests/test_mainwindow.py
@@ -504,7 +504,12 @@ def test_get_help_ipython_console(main_window, qtbot):
 @pytest.mark.skipif(not sys.platform.startswith('linux'),
                     reason="Only works on Linux")
 @pytest.mark.use_introspection
-def test_get_help_editor(main_window, qtbot):
+@pytest.mark.parametrize(
+    "object_info",
+    [("range", "range"),
+     ("import matplotlib.pyplot as plt",
+      "The object-oriented API is recommended for more complex plots.")])
+def test_get_help_editor(main_window, qtbot, object_info):
     """Test that Help works when called from the Editor."""
     help_plugin = main_window.help
     webview = help_plugin.rich_text.webview._webview
@@ -517,8 +522,9 @@ def test_get_help_editor(main_window, qtbot):
         code_editor.document_did_open()
 
     # Write some object in the editor
-    code_editor.set_text('range')
-    code_editor.move_cursor(len('range'))
+    object_name, expected_text = object_info
+    code_editor.set_text(object_name)
+    code_editor.move_cursor(len(object_name))
     with qtbot.waitSignal(code_editor.lsp_response_signal, timeout=30000):
         code_editor.document_did_change()
 
@@ -527,7 +533,7 @@ def test_get_help_editor(main_window, qtbot):
         editorstack.inspect_current_object()
 
     # Check that a expected text is part of the page
-    qtbot.waitUntil(lambda: check_text(webpage, "range"), timeout=30000)
+    qtbot.waitUntil(lambda: check_text(webpage, expected_text), timeout=30000)
 
 
 @pytest.mark.slow
diff --git a/spyder/plugins/completion/kite/utils/tests/test_install.py b/spyder/plugins/completion/kite/utils/tests/test_install.py
--- a/spyder/plugins/completion/kite/utils/tests/test_install.py
+++ b/spyder/plugins/completion/kite/utils/tests/test_install.py
@@ -27,6 +27,7 @@
 
 
 @pytest.mark.slow
+@pytest.mark.first
 @pytest.mark.skipif((not sys.platform.startswith('linux')
                      or os.environ.get('CI', None) is None),
                     reason=("Only works reliably on Linux and "