Closed ggilmore closed 6 years ago
I'd appreciate someone to double check the logic behind my fix, and to make sure that it's correct behavior and mimics what python/jedi actually does.
I'd appreciate someone to double check the logic behind my fix, and to make sure that it's correct behavior and mimics what python/jedi actually does.
Reviewing now
This PR includes a simple test project with no third party dependencies, along with a corresponding test suite. It's not exhaustive (since there are no external dependencies), but having test cases that don't break due to not having pinned versions of external packages is valuable.
In the course of writing these tests, I discovered an issue when we try to jump to def / hover over this line: https://github.com/sourcegraph/python-langserver/blob/simple-tests/test/repos/fizzbuzz_service/fizzbuzz_service/checkers/fizzbuzz/fizzbuzz_checker.py#L6:25 (No definition would be returned).
After tracing our modifications to jedi, I realized that our logic to search for internal project packages seems incorrect.
The relevant directory structure for the file mentioned above is:
fizzbuzz_checker.py
has a relative import that the top of the file for..fizz
. The..
refers to the parentcheckers
package.Previously, when resolving the
checkers
package (and weren't given any specific paths to check forcheckers
from jedi) - we'd only consider the paths:/checkers
/fizzbuzz_service/checkers/fizzbuzz
,/fizzbuzz_service/checkers/fizzbuzz/checkers
when looking for the
checkers
package. None of the paths above are correct (and two don't exist). We'd then assume thatcheckers
is some externalpypi
package.checkers
isn't apypi
package, so fetching that would fail and cause the response to be incorrect.The fix is to more closely mimic jedi's strategy when resolving these imports. When jedi is asked to resolve the
checkers
import on/fizzbuzz_service/checkers/fizzbuzz/fizzbuzz_checker.py
, it:walks up all the parents of
/fizzbuzz_service/checkers/fizzbuzz/fizzbuzz_checker.py
:/fizzbuzz_service/checkers/fizzbuzz
/fizzbuzz_service/checkers
/fizzbuzz_service
/
if any of those parents end in a folder named
checkers
, jedi saves them, e.g.matching_dirs = ['/fizzbuzz_service/checkers']
and then it inserts
matching_dirs
to the start ofsys.path
, which is used during python's native module resolution strategy.My solution mimics this behavior, and includes a test case for the above example.