From 03b4177d3dd741df18651e87e0283d55192a6d34 Mon Sep 17 00:00:00 2001 From: Sam Roeca Date: Thu, 28 Nov 2019 23:04:08 -0500 Subject: [PATCH] Fix: no longer shows folders recursively to root In the previous implementation, Jedi would's traverse_parents function traversed parent directories to the system root every time. This would inadvertently add every folder to the system root every time. Obviously, this is not the behavior desired for the import system. This pull request provides a new argument to the traverse_parents function, "root", which represents the root parent for the search. This argument defaults to None, thereby preserving the existing behavior of the function. I chose to duplicate some code for performance reasons. Since I'm trying to avoid too much path manipulation magic, we do: * a search to a valid specified root, OR * a simple upward search until hitting the system root when there is no valid root specified. --- jedi/api/project.py | 5 ++++- jedi/common/utils.py | 26 +++++++++++++++++++++----- 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/jedi/api/project.py b/jedi/api/project.py index f39ba90f..d4ef879a 100644 --- a/jedi/api/project.py +++ b/jedi/api/project.py @@ -110,7 +110,10 @@ class Project(object): suffixed += discover_buildout_paths(inference_state, inference_state.script_path) if add_parent_paths: - traversed = list(traverse_parents(inference_state.script_path)) + traversed = list(traverse_parents( + inference_state.script_path, + root=self._path, + )) # AFAIK some libraries have imports like `foo.foo.bar`, which # leads to the conclusion to by default prefer longer paths diff --git a/jedi/common/utils.py b/jedi/common/utils.py index bc71cafd..2427f7e9 100644 --- a/jedi/common/utils.py +++ b/jedi/common/utils.py @@ -2,15 +2,31 @@ import os from contextlib import contextmanager -def traverse_parents(path, include_current=False): +def traverse_parents(path, root=None, include_current=False): + """Iterate directories from a path to search root + + :path: the path of the script/directory to check. + :root: the root of the upward search. Assumes the system root if root is + None. + :include_current: includes the current file / directory. + + If the root path is not a substring of the provided path, assume the root + search path as well. + """ if not include_current: path = os.path.dirname(path) previous = None - while previous != path: - yield path - previous = path - path = os.path.dirname(path) + if root is None or not path.startswith(root): + while previous != path: + yield path + previous = path + path = os.path.dirname(path) + else: + while previous != root: + yield path + previous = path + path = os.path.dirname(path) @contextmanager