Repository: spyder-ide/spyder

Issue:
Go to definition not working on local packages
<!--- **PLEASE READ:** When submitting here, please ensure you've completed the following checklist and checked the boxes to confirm. Issue reports without it may be closed. Thanks! --->

### Issue Report Checklist
* [X ] Searched the [issues page](https://github.com/spyder-ide/spyder/issues?q=is%3Aissue) for similar reports
* [X] Read the relevant sections of the [Spyder Troubleshooting Guide](https://github.com/spyder-ide/spyder/wiki/Troubleshooting-Guide-and-FAQ) and followed its advice
* [X] Reproduced the issue after updating with ``conda update spyder`` (or ``pip``, if not using Anaconda)
* [X] Could not reproduce inside ``jupyter qtconsole`` (if console-related)
* [X] Tried basic troubleshooting (if a bug/error)
    * [X] Restarted Spyder
    * [X] Reset preferences with ``spyder --reset``
    * [X] Reinstalled the latest version of [Anaconda](https://www.anaconda.com/download/)
    * [X] Tried the other applicable steps from the Troubleshooting Guide
* [X] Completed the **Problem Description**, **Steps to Reproduce** and **Version** sections below

## Problem Description
Go to definition not working on local packages

### What steps reproduce the problem?

1. Assuming a main file: ./main.py
from v24.funcs import reset_logger
reset_logger()


2. And a ./v24/funcs.py file:
def reset_logger():
    print('Hello')

3. Go to definition in main.py reset_logger() doesn't do anything.
Used to work fine in versions prior to 4.1.4.
It still works for definitions in the same file (main.py) or external Python packages (numpy etc)

### What is the expected output? What do you see instead?
Open ./v24/funcs.py in the editor and place the cursor on the function definition



### Paste Traceback/Error Below (if applicable)
<!--- Copy from error dialog or View > Panes > Internal Console --->

```python-traceback

PASTE TRACEBACK HERE

```

## Versions
<!--- You can get this information from Help > About Spyder...
or (if Spyder won't launch) the "conda list" command
from the Anaconda Prompt/Terminal/command line. --->

* Spyder version:  4.1.4
* Python version: 3.6.10 
* Qt version: 5.9.7
* PyQt version: 5.9.2
* Operating System name/version: Linus 3.10.0

### Dependencies
<!--- Please go to the menu entry Help > Dependencies,
press the Copy to clipboard button and paste below --->

```

# Mandatory:
atomicwrites >=1.2.0           :  1.4.0 (OK)
chardet >=2.0.0                :  3.0.4 (OK)
cloudpickle >=0.5.0            :  1.5.0 (OK)
diff_match_patch >=20181111    :  20200713 (OK)
intervaltree                   :  None (OK)
IPython >=4.0                  :  7.13.0 (OK)
jedi =0.17.1                   :  0.17.1 (OK)
keyring                        :  None (OK)
nbconvert >=4.0                :  5.6.1 (OK)
numpydoc >=0.6.0               :  1.1.0 (OK)
parso =0.7.0                   :  0.7.0 (OK)
pexpect >=4.4.0                :  4.8.0 (OK)
pickleshare >=0.4              :  0.7.5 (OK)
psutil >=5.3                   :  5.7.0 (OK)
pygments >=2.0                 :  2.6.1 (OK)
pylint >=1.0                   :  2.5.3 (OK)
pyls >=0.34.0;<1.0.0           :  0.34.1 (OK)
qdarkstyle >=2.8               :  2.8.1 (OK)
qtawesome >=0.5.7              :  0.7.2 (OK)
qtconsole >=4.6.0              :  4.7.5 (OK)
qtpy >=1.5.0                   :  1.9.0 (OK)
rtree >=0.8.3                  :  0.9.4 (OK)
sphinx >=0.6.6                 :  3.1.2 (OK)
spyder_kernels >=1.9.2;<1.10.0 :  1.9.2 (OK)
watchdog                       :  None (OK)
xdg >=0.26                     :  0.26 (OK)
zmq >=17                       :  19.0.1 (OK)

# Optional:
cython >=0.21                  :  None (OK)
matplotlib >=2.0.0             :  3.1.0 (OK)
numpy >=1.7                    :  1.18.5 (OK)
pandas >=0.13.1                :  None (OK)
scipy >=0.17.0                 :  1.4.1 (OK)
sympy >=0.7.3                  :  None (OK)
```



Discussion:
Hi @liavassif thanks for the feedback. I was unable to reproduce this using Python 3.7. As a workaround, if you want to use Spyder 4.1.4, could you try to install Spyder in an env with Python 3.7?

I think that this could be caused do to the update to jedi 0.17 in our dependencies (I think it doesn't totally support python 3.6 well). What do you think @ccordoba12 ?
> Hi @liavassif thanks for the feedback. I was unable to reproduce this using Python 3.7. As a workaround, if you want to use Spyder 4.1.4, could you try to install Spyder in an env with Python 3.7?
> 
> I think that this could be caused do to the update to jedi 0.17 in our dependencies (I think it doesn't totally support python 3.6 well). What do you think @ccordoba12 ?

I've tried a new env with Python 3.7.7. Still does not work.
I'm not using any project in Spyder. Could this be relevant?

## Versions
<!--- You can get this information from Help > About Spyder...
or (if Spyder won't launch) the "conda list" command
from the Anaconda Prompt/Terminal/command line. --->

* Spyder version:  4.1.4
* Python version: 3.7.7
* Qt version: 5.9.7
* PyQt version: 5.9.2
* Operating System name/version: Linux 3.10.0

### Dependencies
```
# Mandatory:
atomicwrites >=1.2.0           :  1.4.0 (OK)
chardet >=2.0.0                :  3.0.4 (OK)
cloudpickle >=0.5.0            :  1.5.0 (OK)
diff_match_patch >=20181111    :  20200713 (OK)
intervaltree                   :  None (OK)
IPython >=4.0                  :  7.16.1 (OK)
jedi =0.17.1                   :  0.17.1 (OK)
keyring                        :  None (OK)
nbconvert >=4.0                :  5.6.1 (OK)
numpydoc >=0.6.0               :  1.1.0 (OK)
parso =0.7.0                   :  0.7.0 (OK)
pexpect >=4.4.0                :  4.8.0 (OK)
pickleshare >=0.4              :  0.7.5 (OK)
psutil >=5.3                   :  5.7.0 (OK)
pygments >=2.0                 :  2.6.1 (OK)
pylint >=1.0                   :  2.4.4 (OK)
pyls >=0.34.0;<1.0.0           :  0.34.1 (OK)
qdarkstyle >=2.8               :  2.8.1 (OK)
qtawesome >=0.5.7              :  0.7.2 (OK)
qtconsole >=4.6.0              :  4.7.5 (OK)
qtpy >=1.5.0                   :  1.9.0 (OK)
rtree >=0.8.3                  :  0.9.4 (OK)
sphinx >=0.6.6                 :  3.1.2 (OK)
spyder_kernels >=1.9.2;<1.10.0 :  1.9.2 (OK)
watchdog                       :  None (OK)
xdg >=0.26                     :  0.26 (OK)
zmq >=17                       :  19.0.1 (OK)

# Optional:
cython >=0.21                  :  None (OK)
matplotlib >=2.0.0             :  None (OK)
numpy >=1.7                    :  None (OK)
pandas >=0.13.1                :  None (OK)
scipy >=0.17.0                 :  None (OK)
sympy >=0.7.3                  :  None (OK)
```
Thanks for the response @liavassif actually checking again I'm being able to reproduce this. We will be checking this for a future release :+1:
Note: @liavassif as a workaround you will need to wrap your code base as a project (using the `New Project... > Existing directory`)
> Note: @liavassif as a workaround you will need to wrap your code base as a project (using the `New Project... > Existing directory`)

This works. Thanks!
Same experience for python 3.8.5. Does the latest release (spyder  4.1.5) possibly address this issue? 

Updated to it and still can't show local packages in the editor when i "go to definition". To be fair in the changelog there is no referrence to the current issue # but was wondering whether there is a change in settings that is necessary.
Hi @tryfonch there is not a fix for this yet, sorry :/ when someone submits a fix this issue will get referenced in the respective PR and closed after the merge of the fix.

However, now that I think in this maybe what is happening is that the path where you are doing your local package needs to be added to the `PYTHONPATH`. For that, you can go to `Tools > PYTHONPATH manager` and there you can add the root path of your package (that's part of what [opening a project](https://docs.spyder-ide.org/current/projects.html?highlight=pythonpath) does inside Spyder and probably is why opening the package as a project enables the go to definition). If you can try this approach let us know if works @tryfonch :)
@dalthviz when i go to `Tools > PYTHONPATH manager` what i get is an empty box:

![Capture](https://user-images.githubusercontent.com/29928641/92023238-7ecd1400-ed2a-11ea-9ff5-24435024ebb5.PNG)

However my local paths are already added to PYTHONPATH and whenever i import files that exist in those paths they run fine in the spyder console.

![Capture](https://user-images.githubusercontent.com/29928641/92027616-cd7dac80-ed30-11ea-8ae3-a42607758e10.PNG)


This is on a fresh conda installation (version 4.8.4).
Thanks @tryfonch for the feedback! Surely this new info will help us to implement a fix for this :+1:

Edit: pinged the incorrect user 😅 
Note: To make this work, we probably need to add the current document path to `sys.path` here:

https://github.com/palantir/python-language-server/blob/464663300754708e4a557c036c753ee8aea7def4/pyls/workspace.py#L242

Resolving patch:
diff --git a/external-deps/python-lsp-server/pylsp/plugins/definition.py b/external-deps/python-lsp-server/pylsp/plugins/definition.py
--- a/external-deps/python-lsp-server/pylsp/plugins/definition.py
+++ b/external-deps/python-lsp-server/pylsp/plugins/definition.py
@@ -11,7 +11,7 @@
 def pylsp_definitions(config, document, position):
     settings = config.plugin_settings('jedi_definition')
     code_position = _utils.position_to_jedi_linecolumn(document, position)
-    definitions = document.jedi_script().goto(
+    definitions = document.jedi_script(use_document_path=True).goto(
         follow_imports=settings.get('follow_imports', True),
         follow_builtin_imports=settings.get('follow_builtin_imports', True),
         **code_position)
diff --git a/external-deps/python-lsp-server/pylsp/plugins/hover.py b/external-deps/python-lsp-server/pylsp/plugins/hover.py
--- a/external-deps/python-lsp-server/pylsp/plugins/hover.py
+++ b/external-deps/python-lsp-server/pylsp/plugins/hover.py
@@ -11,7 +11,7 @@
 @hookimpl
 def pylsp_hover(document, position):
     code_position = _utils.position_to_jedi_linecolumn(document, position)
-    definitions = document.jedi_script().infer(**code_position)
+    definitions = document.jedi_script(use_document_path=True).infer(**code_position)
     word = document.word_at_position(position)
 
     # Find first exact matching definition


Test patch:
diff --git a/external-deps/python-lsp-server/test/plugins/test_definitions.py b/external-deps/python-lsp-server/test/plugins/test_definitions.py
--- a/external-deps/python-lsp-server/test/plugins/test_definitions.py
+++ b/external-deps/python-lsp-server/test/plugins/test_definitions.py
@@ -1,6 +1,8 @@
 # Copyright 2017-2020 Palantir Technologies, Inc.
 # Copyright 2021- Python Language Server Contributors.
 
+import os
+
 from pylsp import uris
 from pylsp.plugins.definition import pylsp_definitions
 from pylsp.workspace import Document
@@ -57,3 +59,36 @@ def test_assignment(config, workspace):
 
     doc = Document(DOC_URI, workspace, DOC)
     assert [{'uri': DOC_URI, 'range': def_range}] == pylsp_definitions(config, doc, cursor_pos)
+
+
+def test_document_path_definitions(config, workspace_other_root_path, tmpdir):
+    # Create a dummy module out of the workspace's root_path and try to get
+    # a definition on it in another file placed next to it.
+    module_content = '''
+def foo():
+    pass
+'''
+
+    p = tmpdir.join("mymodule.py")
+    p.write(module_content)
+
+    # Content of doc to test definition
+    doc_content = """from mymodule import foo"""
+    doc_path = str(tmpdir) + os.path.sep + 'myfile.py'
+    doc_uri = uris.from_fs_path(doc_path)
+    doc = Document(doc_uri, workspace_other_root_path, doc_content)
+
+    # The range where is defined in mymodule.py
+    def_range = {
+        'start': {'line': 1, 'character': 4},
+        'end': {'line': 1, 'character': 7}
+    }
+
+    # The position where foo is called in myfile.py
+    cursor_pos = {'line': 0, 'character': 24}
+
+    # The uri for mymodule.py
+    module_path = str(p)
+    module_uri = uris.from_fs_path(module_path)
+
+    assert [{'uri': module_uri, 'range': def_range}] == pylsp_definitions(config, doc, cursor_pos)
diff --git a/external-deps/python-lsp-server/test/plugins/test_hover.py b/external-deps/python-lsp-server/test/plugins/test_hover.py
--- a/external-deps/python-lsp-server/test/plugins/test_hover.py
+++ b/external-deps/python-lsp-server/test/plugins/test_hover.py
@@ -1,6 +1,8 @@
 # Copyright 2017-2020 Palantir Technologies, Inc.
 # Copyright 2021- Python Language Server Contributors.
 
+import os
+
 from pylsp import uris
 from pylsp.plugins.hover import pylsp_hover
 from pylsp.workspace import Document
@@ -72,3 +74,28 @@ def test_hover(workspace):
     } == pylsp_hover(doc, hov_position)
 
     assert {'contents': ''} == pylsp_hover(doc, no_hov_position)
+
+
+def test_document_path_hover(workspace_other_root_path, tmpdir):
+    # Create a dummy module out of the workspace's root_path and try to get
+    # a definition on it in another file placed next to it.
+    module_content = '''
+def foo():
+    """A docstring for foo."""
+    pass
+'''
+
+    p = tmpdir.join("mymodule.py")
+    p.write(module_content)
+
+    # Content of doc to test definition
+    doc_content = """from mymodule import foo
+foo"""
+    doc_path = str(tmpdir) + os.path.sep + 'myfile.py'
+    doc_uri = uris.from_fs_path(doc_path)
+    doc = Document(doc_uri, workspace_other_root_path, doc_content)
+
+    cursor_pos = {'line': 1, 'character': 3}
+    contents = pylsp_hover(doc, cursor_pos)['contents']
+
+    assert contents[1] == 'A docstring for foo.'
diff --git a/external-deps/python-lsp-server/test/test_language_server.py b/external-deps/python-lsp-server/test/test_language_server.py
--- a/external-deps/python-lsp-server/test/test_language_server.py
+++ b/external-deps/python-lsp-server/test/test_language_server.py
@@ -75,6 +75,7 @@ def client_exited_server():
     assert client_server_pair.process.is_alive() is False
 
 
+@pytest.mark.skipif(sys.platform == 'darwin', reason='Too flaky on Mac')
 def test_initialize(client_server):  # pylint: disable=redefined-outer-name
     response = client_server._endpoint.request('initialize', {
         'rootPath': os.path.dirname(__file__),