forked from VimPlug/jedi
sys_path stuff has its own module, now.
This commit is contained in:
@@ -36,7 +36,7 @@ from jedi import common
|
|||||||
from jedi import debug
|
from jedi import debug
|
||||||
from jedi.parser import Parser
|
from jedi.parser import Parser
|
||||||
from jedi.parser import fast
|
from jedi.parser import fast
|
||||||
from jedi import modules
|
from jedi.evaluate.sys_path import get_sys_path
|
||||||
from jedi import cache
|
from jedi import cache
|
||||||
|
|
||||||
|
|
||||||
@@ -70,7 +70,7 @@ class BuiltinModule(object):
|
|||||||
|
|
||||||
def __init__(self, path=None, name=None, sys_path=None):
|
def __init__(self, path=None, name=None, sys_path=None):
|
||||||
if sys_path is None:
|
if sys_path is None:
|
||||||
sys_path = modules.get_sys_path()
|
sys_path = get_sys_path()
|
||||||
self.sys_path = list(sys_path)
|
self.sys_path = list(sys_path)
|
||||||
|
|
||||||
if not name:
|
if not name:
|
||||||
|
|||||||
@@ -19,11 +19,12 @@ import sys
|
|||||||
import itertools
|
import itertools
|
||||||
|
|
||||||
from jedi._compatibility import find_module
|
from jedi._compatibility import find_module
|
||||||
from jedi import modules
|
|
||||||
from jedi import common
|
from jedi import common
|
||||||
from jedi import debug
|
from jedi import debug
|
||||||
from jedi.parser import representation as pr
|
|
||||||
from jedi import cache
|
from jedi import cache
|
||||||
|
from jedi import modules
|
||||||
|
from jedi.parser import representation as pr
|
||||||
|
from jedi.evaluate import sys_path
|
||||||
|
|
||||||
|
|
||||||
class ModuleNotFound(Exception):
|
class ModuleNotFound(Exception):
|
||||||
@@ -177,7 +178,7 @@ class ImportPath(pr.Base):
|
|||||||
in_path.append(new)
|
in_path.append(new)
|
||||||
|
|
||||||
module = self.import_stmt.get_parent_until()
|
module = self.import_stmt.get_parent_until()
|
||||||
return in_path + modules.sys_path_with_modifications(module)
|
return in_path + sys_path.sys_path_with_modifications(module)
|
||||||
|
|
||||||
def follow(self, is_goto=False):
|
def follow(self, is_goto=False):
|
||||||
"""
|
"""
|
||||||
@@ -284,7 +285,7 @@ class ImportPath(pr.Base):
|
|||||||
sys_path_mod.append(temp_path)
|
sys_path_mod.append(temp_path)
|
||||||
old_path, temp_path = temp_path, os.path.dirname(temp_path)
|
old_path, temp_path = temp_path, os.path.dirname(temp_path)
|
||||||
else:
|
else:
|
||||||
sys_path_mod = list(modules.get_sys_path())
|
sys_path_mod = list(sys_path.get_sys_path())
|
||||||
|
|
||||||
return self._follow_sys_path(sys_path_mod)
|
return self._follow_sys_path(sys_path_mod)
|
||||||
|
|
||||||
|
|||||||
120
jedi/evaluate/sys_path.py
Normal file
120
jedi/evaluate/sys_path.py
Normal file
@@ -0,0 +1,120 @@
|
|||||||
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
|
from jedi._compatibility import exec_function
|
||||||
|
from jedi.parser import representation as pr
|
||||||
|
from jedi import debug
|
||||||
|
from jedi import common
|
||||||
|
|
||||||
|
|
||||||
|
def get_sys_path():
|
||||||
|
def check_virtual_env(sys_path):
|
||||||
|
""" Add virtualenv's site-packages to the `sys.path`."""
|
||||||
|
venv = os.getenv('VIRTUAL_ENV')
|
||||||
|
if not venv:
|
||||||
|
return
|
||||||
|
venv = os.path.abspath(venv)
|
||||||
|
p = os.path.join(
|
||||||
|
venv, 'lib', 'python%d.%d' % sys.version_info[:2], 'site-packages')
|
||||||
|
sys_path.insert(0, p)
|
||||||
|
|
||||||
|
check_virtual_env(sys.path)
|
||||||
|
return [p for p in sys.path if p != ""]
|
||||||
|
|
||||||
|
|
||||||
|
#@cache.memoize_default([]) TODO add some sort of cache again.
|
||||||
|
def sys_path_with_modifications(module):
|
||||||
|
def execute_code(code):
|
||||||
|
c = "import os; from os.path import *; result=%s"
|
||||||
|
variables = {'__file__': module.path}
|
||||||
|
try:
|
||||||
|
exec_function(c % code, variables)
|
||||||
|
except Exception:
|
||||||
|
debug.warning('sys path detected, but failed to evaluate')
|
||||||
|
return None
|
||||||
|
try:
|
||||||
|
res = variables['result']
|
||||||
|
if isinstance(res, str):
|
||||||
|
return os.path.abspath(res)
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
except KeyError:
|
||||||
|
return None
|
||||||
|
|
||||||
|
def check_module(module):
|
||||||
|
try:
|
||||||
|
possible_stmts = module.used_names['path']
|
||||||
|
except KeyError:
|
||||||
|
return get_sys_path()
|
||||||
|
|
||||||
|
sys_path = list(get_sys_path()) # copy
|
||||||
|
for p in possible_stmts:
|
||||||
|
if not isinstance(p, pr.Statement):
|
||||||
|
continue
|
||||||
|
expression_list = p.expression_list()
|
||||||
|
# sys.path command is just one thing.
|
||||||
|
if len(expression_list) != 1 or not isinstance(expression_list[0], pr.Call):
|
||||||
|
continue
|
||||||
|
call = expression_list[0]
|
||||||
|
n = call.name
|
||||||
|
if not isinstance(n, pr.Name) or len(n.names) != 3:
|
||||||
|
continue
|
||||||
|
if n.names[:2] != ('sys', 'path'):
|
||||||
|
continue
|
||||||
|
array_cmd = n.names[2]
|
||||||
|
if call.execution is None:
|
||||||
|
continue
|
||||||
|
exe = call.execution
|
||||||
|
if not (array_cmd == 'insert' and len(exe) == 2
|
||||||
|
or array_cmd == 'append' and len(exe) == 1):
|
||||||
|
continue
|
||||||
|
|
||||||
|
if array_cmd == 'insert':
|
||||||
|
exe_type, exe.type = exe.type, pr.Array.NOARRAY
|
||||||
|
exe_pop = exe.values.pop(0)
|
||||||
|
res = execute_code(exe.get_code())
|
||||||
|
if res is not None:
|
||||||
|
sys_path.insert(0, res)
|
||||||
|
debug.dbg('sys path inserted: %s' % res)
|
||||||
|
exe.type = exe_type
|
||||||
|
exe.values.insert(0, exe_pop)
|
||||||
|
elif array_cmd == 'append':
|
||||||
|
res = execute_code(exe.get_code())
|
||||||
|
if res is not None:
|
||||||
|
sys_path.append(res)
|
||||||
|
debug.dbg('sys path added: %s' % res)
|
||||||
|
return sys_path
|
||||||
|
|
||||||
|
if module.path is None:
|
||||||
|
# Support for modules without a path is bad, therefore return the
|
||||||
|
# normal path.
|
||||||
|
return list(get_sys_path())
|
||||||
|
|
||||||
|
curdir = os.path.abspath(os.curdir)
|
||||||
|
with common.ignored(OSError):
|
||||||
|
os.chdir(os.path.dirname(module.path))
|
||||||
|
|
||||||
|
result = check_module(module)
|
||||||
|
result += _detect_django_path(module.path)
|
||||||
|
|
||||||
|
# cleanup, back to old directory
|
||||||
|
os.chdir(curdir)
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
def _detect_django_path(module_path):
|
||||||
|
""" Detects the path of the very well known Django library (if used) """
|
||||||
|
result = []
|
||||||
|
while True:
|
||||||
|
new = os.path.dirname(module_path)
|
||||||
|
# If the module_path doesn't change anymore, we're finished -> /
|
||||||
|
if new == module_path:
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
module_path = new
|
||||||
|
|
||||||
|
with common.ignored(IOError):
|
||||||
|
with open(module_path + os.path.sep + 'manage.py'):
|
||||||
|
debug.dbg('Found django path: %s' % module_path)
|
||||||
|
result.append(module_path)
|
||||||
|
return result
|
||||||
119
jedi/modules.py
119
jedi/modules.py
@@ -20,13 +20,11 @@ import sys
|
|||||||
import os
|
import os
|
||||||
from ast import literal_eval
|
from ast import literal_eval
|
||||||
|
|
||||||
from jedi._compatibility import exec_function, unicode
|
from jedi._compatibility import unicode
|
||||||
from jedi import cache
|
from jedi import cache
|
||||||
from jedi.parser import representation as pr
|
|
||||||
from jedi.parser import tokenizer as tokenize
|
from jedi.parser import tokenizer as tokenize
|
||||||
from jedi.parser import fast
|
from jedi.parser import fast
|
||||||
from jedi import debug
|
from jedi import debug
|
||||||
from jedi import common
|
|
||||||
|
|
||||||
|
|
||||||
def load_module(path=None, source=None, name=None):
|
def load_module(path=None, source=None, name=None):
|
||||||
@@ -227,121 +225,6 @@ class ModuleWithCursor(object):
|
|||||||
|
|
||||||
def get_position_line(self):
|
def get_position_line(self):
|
||||||
return self.get_line(self.position[0])[:self.position[1]]
|
return self.get_line(self.position[0])[:self.position[1]]
|
||||||
|
|
||||||
|
|
||||||
def get_sys_path():
|
|
||||||
def check_virtual_env(sys_path):
|
|
||||||
""" Add virtualenv's site-packages to the `sys.path`."""
|
|
||||||
venv = os.getenv('VIRTUAL_ENV')
|
|
||||||
if not venv:
|
|
||||||
return
|
|
||||||
venv = os.path.abspath(venv)
|
|
||||||
p = os.path.join(
|
|
||||||
venv, 'lib', 'python%d.%d' % sys.version_info[:2], 'site-packages')
|
|
||||||
sys_path.insert(0, p)
|
|
||||||
|
|
||||||
check_virtual_env(sys.path)
|
|
||||||
return [p for p in sys.path if p != ""]
|
|
||||||
|
|
||||||
|
|
||||||
#@cache.memoize_default([]) TODO add some sort of cache again.
|
|
||||||
def sys_path_with_modifications(module):
|
|
||||||
def execute_code(code):
|
|
||||||
c = "import os; from os.path import *; result=%s"
|
|
||||||
variables = {'__file__': module.path}
|
|
||||||
try:
|
|
||||||
exec_function(c % code, variables)
|
|
||||||
except Exception:
|
|
||||||
debug.warning('sys path detected, but failed to evaluate')
|
|
||||||
return None
|
|
||||||
try:
|
|
||||||
res = variables['result']
|
|
||||||
if isinstance(res, str):
|
|
||||||
return os.path.abspath(res)
|
|
||||||
else:
|
|
||||||
return None
|
|
||||||
except KeyError:
|
|
||||||
return None
|
|
||||||
|
|
||||||
def check_module(module):
|
|
||||||
try:
|
|
||||||
possible_stmts = module.used_names['path']
|
|
||||||
except KeyError:
|
|
||||||
return get_sys_path()
|
|
||||||
|
|
||||||
sys_path = list(get_sys_path()) # copy
|
|
||||||
for p in possible_stmts:
|
|
||||||
if not isinstance(p, pr.Statement):
|
|
||||||
continue
|
|
||||||
expression_list = p.expression_list()
|
|
||||||
# sys.path command is just one thing.
|
|
||||||
if len(expression_list) != 1 or not isinstance(expression_list[0], pr.Call):
|
|
||||||
continue
|
|
||||||
call = expression_list[0]
|
|
||||||
n = call.name
|
|
||||||
if not isinstance(n, pr.Name) or len(n.names) != 3:
|
|
||||||
continue
|
|
||||||
if n.names[:2] != ('sys', 'path'):
|
|
||||||
continue
|
|
||||||
array_cmd = n.names[2]
|
|
||||||
if call.execution is None:
|
|
||||||
continue
|
|
||||||
exe = call.execution
|
|
||||||
if not (array_cmd == 'insert' and len(exe) == 2
|
|
||||||
or array_cmd == 'append' and len(exe) == 1):
|
|
||||||
continue
|
|
||||||
|
|
||||||
if array_cmd == 'insert':
|
|
||||||
exe_type, exe.type = exe.type, pr.Array.NOARRAY
|
|
||||||
exe_pop = exe.values.pop(0)
|
|
||||||
res = execute_code(exe.get_code())
|
|
||||||
if res is not None:
|
|
||||||
sys_path.insert(0, res)
|
|
||||||
debug.dbg('sys path inserted: %s' % res)
|
|
||||||
exe.type = exe_type
|
|
||||||
exe.values.insert(0, exe_pop)
|
|
||||||
elif array_cmd == 'append':
|
|
||||||
res = execute_code(exe.get_code())
|
|
||||||
if res is not None:
|
|
||||||
sys_path.append(res)
|
|
||||||
debug.dbg('sys path added: %s' % res)
|
|
||||||
return sys_path
|
|
||||||
|
|
||||||
if module.path is None:
|
|
||||||
# Support for modules without a path is bad, therefore return the
|
|
||||||
# normal path.
|
|
||||||
return list(get_sys_path())
|
|
||||||
|
|
||||||
curdir = os.path.abspath(os.curdir)
|
|
||||||
with common.ignored(OSError):
|
|
||||||
os.chdir(os.path.dirname(module.path))
|
|
||||||
|
|
||||||
result = check_module(module)
|
|
||||||
result += _detect_django_path(module.path)
|
|
||||||
|
|
||||||
# cleanup, back to old directory
|
|
||||||
os.chdir(curdir)
|
|
||||||
return result
|
|
||||||
|
|
||||||
|
|
||||||
def _detect_django_path(module_path):
|
|
||||||
""" Detects the path of the very well known Django library (if used) """
|
|
||||||
result = []
|
|
||||||
while True:
|
|
||||||
new = os.path.dirname(module_path)
|
|
||||||
# If the module_path doesn't change anymore, we're finished -> /
|
|
||||||
if new == module_path:
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
module_path = new
|
|
||||||
|
|
||||||
with common.ignored(IOError):
|
|
||||||
with open(module_path + os.path.sep + 'manage.py'):
|
|
||||||
debug.dbg('Found django path: %s' % module_path)
|
|
||||||
result.append(module_path)
|
|
||||||
return result
|
|
||||||
|
|
||||||
|
|
||||||
def source_to_unicode(source, encoding=None):
|
def source_to_unicode(source, encoding=None):
|
||||||
def detect_encoding():
|
def detect_encoding():
|
||||||
""" For the implementation of encoding definitions in Python, look at:
|
""" For the implementation of encoding definitions in Python, look at:
|
||||||
|
|||||||
Reference in New Issue
Block a user