diff --git a/jedi/api/__init__.py b/jedi/api/__init__.py index 8961fa35..cbb3b7a8 100644 --- a/jedi/api/__init__.py +++ b/jedi/api/__init__.py @@ -27,9 +27,10 @@ from jedi.api import helpers from jedi.api.completion import Completion from jedi.evaluate import Evaluator from jedi.evaluate import imports +from jedi.evaluate.project import Project from jedi.evaluate.arguments import try_iter_content from jedi.evaluate.helpers import get_module_names, evaluate_call_of_leaf -from jedi.evaluate.sys_path import get_venv_path, dotted_path_in_sys_path +from jedi.evaluate.sys_path import dotted_path_in_sys_path from jedi.evaluate.filters import TreeNameDefinition from jedi.evaluate.syntax_tree import tree_name_to_contexts from jedi.evaluate.context import ModuleContext @@ -110,11 +111,7 @@ class Script(object): # Load the Python grammar of the current interpreter. self._grammar = parso.load_grammar() - if sys_path is None: - venv = os.getenv('VIRTUAL_ENV') - if venv: - sys_path = list(get_venv_path(venv)) - self._evaluator = Evaluator(self._grammar, sys_path=sys_path) + self._evaluator = Evaluator(self._grammar, Project(sys_path=sys_path)) debug.speed('init') @cache.memoize_method @@ -135,7 +132,7 @@ class Script(object): self.path ) if self.path is not None: - name = dotted_path_in_sys_path(self._evaluator.sys_path, self.path) + name = dotted_path_in_sys_path(self._evaluator.project.sys_path, self.path) if name is not None: imports.add_module(self._evaluator, name, module) return module diff --git a/jedi/evaluate/__init__.py b/jedi/evaluate/__init__.py index b726bd25..d0825797 100644 --- a/jedi/evaluate/__init__.py +++ b/jedi/evaluate/__init__.py @@ -87,7 +87,7 @@ from jedi.evaluate.syntax_tree import eval_trailer, eval_expr_stmt, \ class Evaluator(object): - def __init__(self, grammar, sys_path=None): + def __init__(self, grammar, project): self.grammar = grammar self.latest_grammar = parso.load_grammar(version='3.6') self.memoize_cache = {} # for memoize decorators @@ -101,13 +101,7 @@ class Evaluator(object): self.is_analysis = False self.python_version = sys.version_info[:2] - if sys_path is None: - sys_path = sys.path - self.sys_path = copy.copy(sys_path) - try: - self.sys_path.remove('') - except ValueError: - pass + self.project = project self.reset_recursion_limitations() diff --git a/jedi/evaluate/arguments.py b/jedi/evaluate/arguments.py index 02000ce5..32b9238c 100644 --- a/jedi/evaluate/arguments.py +++ b/jedi/evaluate/arguments.py @@ -243,5 +243,3 @@ def _star_star_dict(context, array, input_node, funcdef): % (funcdef.name.value, array) analysis.add(context, 'type-error-star-star', input_node, message=m) return {} - - diff --git a/jedi/evaluate/compiled/__init__.py b/jedi/evaluate/compiled/__init__.py index b29c080e..551e6964 100644 --- a/jedi/evaluate/compiled/__init__.py +++ b/jedi/evaluate/compiled/__init__.py @@ -444,7 +444,7 @@ def dotted_from_fs_path(fs_path, sys_path): def load_module(evaluator, path=None, name=None): - sys_path = evaluator.sys_path + sys_path = list(evaluator.project.sys_path) if path is not None: dotted_path = dotted_from_fs_path(path, sys_path=sys_path) else: diff --git a/jedi/evaluate/context/module.py b/jedi/evaluate/context/module.py index 471f3165..a19fea1b 100644 --- a/jedi/evaluate/context/module.py +++ b/jedi/evaluate/context/module.py @@ -135,7 +135,7 @@ class ModuleContext(use_metaclass(CachedMetaClass, TreeContext)): return self.py__name__() def _py__path__(self): - search_path = self.evaluator.sys_path + search_path = self.evaluator.project.sys_path init_path = self.py__file__() if os.path.basename(init_path) == '__init__.py': with open(init_path, 'rb') as f: diff --git a/jedi/evaluate/imports.py b/jedi/evaluate/imports.py index adfef8fa..3a1d93af 100644 --- a/jedi/evaluate/imports.py +++ b/jedi/evaluate/imports.py @@ -480,7 +480,7 @@ class Importer(object): def _load_module(evaluator, path=None, code=None, sys_path=None, parent_module=None): if sys_path is None: - sys_path = evaluator.sys_path + sys_path = evaluator.project.sys_path dotted_path = path and compiled.dotted_from_fs_path(path, sys_path) if path is not None and path.endswith(('.py', '.zip', '.egg')) \ @@ -530,7 +530,7 @@ def get_modules_containing_name(evaluator, modules, name): if name in code: module = _load_module(evaluator, path, code) - module_name = sys_path.dotted_path_in_sys_path(evaluator.sys_path, path) + module_name = sys_path.dotted_path_in_sys_path(evaluator.project.sys_path, path) if module_name is not None: add_module(evaluator, module_name, module) return module diff --git a/jedi/evaluate/project.py b/jedi/evaluate/project.py new file mode 100644 index 00000000..e76aab75 --- /dev/null +++ b/jedi/evaluate/project.py @@ -0,0 +1,24 @@ +import os +import sys + +from jedi.evaluate.sys_path import get_venv_path + + +class Project(object): + def __init__(self, sys_path=None): + if sys_path is None: + venv = os.getenv('VIRTUAL_ENV') + if venv: + sys_path = get_venv_path(venv) + + if sys_path is None: + sys_path = sys.path + + sys_path = list(sys_path) + + try: + sys_path.remove('') + except ValueError: + pass + + self.sys_path = sys_path diff --git a/jedi/evaluate/sys_path.py b/jedi/evaluate/sys_path.py index 28071dce..842a9ae2 100644 --- a/jedi/evaluate/sys_path.py +++ b/jedi/evaluate/sys_path.py @@ -161,7 +161,7 @@ def _check_module(module_context): if n.type == 'name' and n.value == 'path': yield name, power - sys_path = list(module_context.evaluator.sys_path) # copy + sys_path = list(module_context.evaluator.project.sys_path) # copy if isinstance(module_context, CompiledObject): return sys_path @@ -189,7 +189,7 @@ def sys_path_with_modifications(evaluator, module_context): if path is None: # Support for modules without a path is bad, therefore return the # normal path. - return list(evaluator.sys_path) + return evaluator.project.sys_path curdir = os.path.abspath(os.curdir) #TODO why do we need a chdir? diff --git a/test/test_evaluate/test_buildout_detection.py b/test/test_evaluate/test_buildout_detection.py index 04ede288..e5e51ba7 100644 --- a/test/test_evaluate/test_buildout_detection.py +++ b/test/test_evaluate/test_buildout_detection.py @@ -9,6 +9,7 @@ from jedi.evaluate.sys_path import (_get_parent_dir_with_file, sys_path_with_modifications, _check_module) from jedi.evaluate import Evaluator +from jedi.evaluate.project import Project from jedi.evaluate.context.module import ModuleContext from ..helpers import cwd_at @@ -16,7 +17,8 @@ from ..helpers import cwd_at def check_module_test(code): grammar = parso.load_grammar() - module_context = ModuleContext(Evaluator(grammar), parso.parse(code), path=None) + e = Evaluator(grammar, Project()) + module_context = ModuleContext(e, parso.parse(code), path=None) return _check_module(module_context) @@ -69,7 +71,7 @@ def test_sys_path_with_modifications(): path = os.path.abspath(os.path.join(os.curdir, 'module_name.py')) grammar = parso.load_grammar() module_node = parso.parse(code, path=path) - module_context = ModuleContext(Evaluator(grammar), module_node, path=path) + module_context = ModuleContext(Evaluator(grammar, Project()), module_node, path=path) paths = sys_path_with_modifications(module_context.evaluator, module_context) assert '/tmp/.buildout/eggs/important_package.egg' in paths diff --git a/test/test_evaluate/test_compiled.py b/test/test_evaluate/test_compiled.py index dff964c9..44aef93b 100644 --- a/test/test_evaluate/test_compiled.py +++ b/test/test_evaluate/test_compiled.py @@ -7,12 +7,13 @@ from jedi.evaluate import compiled from jedi.evaluate.context import instance from jedi.evaluate.context.function import FunctionContext from jedi.evaluate import Evaluator +from jedi.evaluate.project import Project from jedi.parser_utils import clean_scope_docstring from jedi import Script def _evaluator(): - return Evaluator(parso.load_grammar()) + return Evaluator(parso.load_grammar(), Project()) def test_simple():