1
0
forked from VimPlug/jedi

Use sys path mostly from project and move some sys path stuff around.

This commit is contained in:
Dave Halter
2017-10-05 10:06:28 +02:00
parent 383f749026
commit 51d2ffb078
7 changed files with 77 additions and 67 deletions
+3 -1
View File
@@ -111,7 +111,9 @@ class Script(object):
# Load the Python grammar of the current interpreter.
self._grammar = parso.load_grammar()
self._evaluator = Evaluator(self._grammar, Project(sys_path=sys_path))
project = Project(sys_path=sys_path)
self._evaluator = Evaluator(self._grammar, project)
project.add_script_path(self.path)
debug.speed('init')
@cache.memoize_method
-3
View File
@@ -12,7 +12,6 @@ there are global variables, which are holding the cache information. Some of
these variables are being cleaned after every API usage.
"""
import time
import inspect
from jedi import settings
from parso.cache import parser_cache
@@ -46,8 +45,6 @@ def underscore_memoization(func):
return getattr(self, name)
except AttributeError:
result = func(self)
if inspect.isgenerator(result):
result = list(result)
setattr(self, name, result)
return result
+1 -2
View File
@@ -62,7 +62,6 @@ only *evaluates* what needs to be *evaluated*. All the statements and modules
that are not used are just being ignored.
"""
import copy
import sys
from parso.python import tree
@@ -100,8 +99,8 @@ class Evaluator(object):
self.dynamic_params_depth = 0
self.is_analysis = False
self.python_version = sys.version_info[:2]
self.project = project
project.add_evaluator(self)
self.reset_recursion_limitations()
+19 -5
View File
@@ -1,7 +1,8 @@
import os
import sys
from jedi.evaluate.sys_path import get_venv_path
from jedi.evaluate.sys_path import get_venv_path, detect_additional_paths
from jedi.cache import underscore_memoization
class Project(object):
@@ -14,11 +15,24 @@ class Project(object):
if sys_path is None:
sys_path = sys.path
sys_path = list(sys_path)
base_sys_path = list(sys_path)
try:
sys_path.remove('')
base_sys_path.remove('')
except ValueError:
pass
self.sys_path = sys_path
self._base_sys_path = base_sys_path
def add_script_path(self, script_path):
self._script_path = script_path
def add_evaluator(self, evaluator):
self._evaluator = evaluator
@property
@underscore_memoization
def sys_path(self):
if self._script_path is None:
return self._base_sys_path
return self._base_sys_path + detect_additional_paths(self._evaluator, self._script_path)
+34 -28
View File
@@ -6,7 +6,6 @@ from jedi.evaluate.site import addsitedir
from jedi._compatibility import exec_function, unicode
from jedi.evaluate.cache import evaluator_function_cache
from jedi.evaluate.compiled import CompiledObject
from jedi.evaluate.base_context import ContextualizedNode
from jedi import settings
from jedi import debug
@@ -80,12 +79,24 @@ def _execute_code(module_path, code):
try:
res = variables['result']
if isinstance(res, str):
return [os.path.abspath(res)]
return _abs_path(module_path, res)
except KeyError:
pass
return []
return None
def _abs_path(module_path, path):
if os.path.isabs(path):
return path
if module_path is None:
# In this case we have no idea where we actually are in the file
# system.
return None
base_dir = os.path.dirname(module_path)
return os.path.abspath(os.path.join(base_dir, path))
def _paths_from_assignment(module_context, expr_stmt):
"""
Extracts the assigned strings from an assignment that looks as follows::
@@ -125,7 +136,9 @@ def _paths_from_assignment(module_context, expr_stmt):
for lazy_context in cn.infer().iterate(cn):
for context in lazy_context.infer():
if is_string(context):
yield context.obj
abs_path = _abs_path(module_context.py__file__(), context.obj)
if abs_path is not None:
yield abs_path
def _paths_from_list_modifications(module_path, trailer1, trailer2):
@@ -143,10 +156,11 @@ def _paths_from_list_modifications(module_path, trailer1, trailer2):
arg = trailer2.children[1]
if name == 'insert' and len(arg.children) in (3, 4): # Possible trailing comma.
arg = arg.children[2]
return _execute_code(module_path, arg.get_code())
path = _execute_code(module_path, arg.get_code())
return [] if path is None else [path]
def _check_module(module_context):
def check_sys_path_modifications(module_context):
"""
Detect sys.path modifications within module.
"""
@@ -161,10 +175,10 @@ def _check_module(module_context):
if n.type == 'name' and n.value == 'path':
yield name, power
sys_path = list(module_context.evaluator.project.sys_path) # copy
if isinstance(module_context, CompiledObject):
return sys_path
if module_context.tree_node is None:
return []
added = []
try:
possible_names = module_context.tree_node.get_used_names()['path']
except KeyError:
@@ -173,39 +187,30 @@ def _check_module(module_context):
for name, power in get_sys_path_powers(possible_names):
expr_stmt = power.parent
if len(power.children) >= 4:
sys_path.extend(
added.extend(
_paths_from_list_modifications(
module_context.py__file__(), *power.children[2:4]
)
)
elif expr_stmt is not None and expr_stmt.type == 'expr_stmt':
sys_path.extend(_paths_from_assignment(module_context, expr_stmt))
return sys_path
added.extend(_paths_from_assignment(module_context, expr_stmt))
return added
@evaluator_function_cache(default=[])
def sys_path_with_modifications(evaluator, module_context):
path = module_context.py__file__()
if path is None:
# Support for modules without a path is bad, therefore return the
# normal path.
return evaluator.project.sys_path
return evaluator.project.sys_path + check_sys_path_modifications(module_context)
curdir = os.path.abspath(os.curdir)
#TODO why do we need a chdir?
with ignored(OSError):
os.chdir(os.path.dirname(path))
def detect_additional_paths(evaluator, script_path):
django_paths = _detect_django_path(script_path)
buildout_script_paths = set()
result = _check_module(module_context)
result += _detect_django_path(path)
for buildout_script_path in _get_buildout_script_paths(path):
for buildout_script_path in _get_buildout_script_paths(script_path):
for path in _get_paths_from_buildout_script(evaluator, buildout_script_path):
buildout_script_paths.add(path)
# cleanup, back to old directory
os.chdir(curdir)
return list(result) + list(buildout_script_paths)
return django_paths + list(buildout_script_paths)
def _get_paths_from_buildout_script(evaluator, buildout_script_path):
@@ -220,7 +225,8 @@ def _get_paths_from_buildout_script(evaluator, buildout_script_path):
return
from jedi.evaluate.context import ModuleContext
for path in _check_module(ModuleContext(evaluator, module_node, buildout_script_path)):
module = ModuleContext(evaluator, module_node, buildout_script_path)
for path in check_sys_path_modifications(module):
yield path