forked from VimPlug/jedi
Start using the new virtualenv code
There used to be a lot of code to kind of understand virtualenvs. This can all be removed now, because this is done in a subprocess with the correct interpreter
This commit is contained in:
@@ -66,7 +66,7 @@ class InterpreterEnvironment(_BaseEnvironment):
|
|||||||
return EvaluatorSameProcess(evaluator)
|
return EvaluatorSameProcess(evaluator)
|
||||||
|
|
||||||
def get_sys_path(self):
|
def get_sys_path(self):
|
||||||
return sys.sys_path
|
return sys.path
|
||||||
|
|
||||||
|
|
||||||
def get_default_environment():
|
def get_default_environment():
|
||||||
|
|||||||
@@ -1,7 +1,4 @@
|
|||||||
import os
|
from jedi.evaluate.sys_path import detect_additional_paths
|
||||||
import sys
|
|
||||||
|
|
||||||
from jedi.evaluate.sys_path import get_venv_path, detect_additional_paths
|
|
||||||
from jedi.cache import memoize_method
|
from jedi.cache import memoize_method
|
||||||
|
|
||||||
|
|
||||||
@@ -9,24 +6,8 @@ class Project(object):
|
|||||||
def __init__(self, sys_path=None):
|
def __init__(self, sys_path=None):
|
||||||
self._script_path = None
|
self._script_path = None
|
||||||
|
|
||||||
if sys_path is not None:
|
|
||||||
self._base_sys_path = sys_path
|
self._base_sys_path = sys_path
|
||||||
|
|
||||||
if sys_path is None:
|
|
||||||
venv = os.getenv('VIRTUAL_ENV')
|
|
||||||
if venv:
|
|
||||||
sys_path = get_venv_path(venv)
|
|
||||||
else:
|
|
||||||
sys_path = sys.path
|
|
||||||
|
|
||||||
base_sys_path = list(sys_path)
|
|
||||||
try:
|
|
||||||
base_sys_path.remove('')
|
|
||||||
except ValueError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
self._base_sys_path = base_sys_path
|
|
||||||
|
|
||||||
def add_script_path(self, script_path):
|
def add_script_path(self, script_path):
|
||||||
self._script_path = script_path
|
self._script_path = script_path
|
||||||
|
|
||||||
@@ -36,7 +17,17 @@ class Project(object):
|
|||||||
@property
|
@property
|
||||||
@memoize_method
|
@memoize_method
|
||||||
def sys_path(self):
|
def sys_path(self):
|
||||||
if self._script_path is None:
|
sys_path = self._base_sys_path
|
||||||
return self._base_sys_path
|
if sys_path is None:
|
||||||
|
sys_path = self._evaluator.environment.get_sys_path()
|
||||||
|
|
||||||
return self._base_sys_path + detect_additional_paths(self._evaluator, self._script_path)
|
sys_path = list(sys_path)
|
||||||
|
try:
|
||||||
|
sys_path.remove('')
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
if self._script_path is None:
|
||||||
|
return sys_path
|
||||||
|
|
||||||
|
return sys_path + detect_additional_paths(self._evaluator, self._script_path)
|
||||||
|
|||||||
@@ -1,110 +0,0 @@
|
|||||||
"""An adapted copy of relevant site-packages functionality from Python stdlib.
|
|
||||||
|
|
||||||
This file contains some functions related to handling site-packages in Python
|
|
||||||
with jedi-specific modifications:
|
|
||||||
|
|
||||||
- the functions operate on sys_path argument rather than global sys.path
|
|
||||||
|
|
||||||
- in .pth files "import ..." lines that allow execution of arbitrary code are
|
|
||||||
skipped to prevent code injection into jedi interpreter
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
|
|
||||||
# 2011, 2012, 2013, 2014, 2015 Python Software Foundation; All Rights Reserved
|
|
||||||
|
|
||||||
from __future__ import print_function
|
|
||||||
|
|
||||||
import sys
|
|
||||||
import os
|
|
||||||
|
|
||||||
|
|
||||||
def makepath(*paths):
|
|
||||||
dir = os.path.join(*paths)
|
|
||||||
try:
|
|
||||||
dir = os.path.abspath(dir)
|
|
||||||
except OSError:
|
|
||||||
pass
|
|
||||||
return dir, os.path.normcase(dir)
|
|
||||||
|
|
||||||
|
|
||||||
def _init_pathinfo(sys_path):
|
|
||||||
"""Return a set containing all existing directory entries from sys_path"""
|
|
||||||
d = set()
|
|
||||||
for dir in sys_path:
|
|
||||||
try:
|
|
||||||
if os.path.isdir(dir):
|
|
||||||
dir, dircase = makepath(dir)
|
|
||||||
d.add(dircase)
|
|
||||||
except TypeError:
|
|
||||||
continue
|
|
||||||
return d
|
|
||||||
|
|
||||||
|
|
||||||
def addpackage(sys_path, sitedir, name, known_paths):
|
|
||||||
"""Process a .pth file within the site-packages directory:
|
|
||||||
For each line in the file, either combine it with sitedir to a path
|
|
||||||
and add that to known_paths, or execute it if it starts with 'import '.
|
|
||||||
"""
|
|
||||||
if known_paths is None:
|
|
||||||
known_paths = _init_pathinfo(sys_path)
|
|
||||||
reset = 1
|
|
||||||
else:
|
|
||||||
reset = 0
|
|
||||||
fullname = os.path.join(sitedir, name)
|
|
||||||
try:
|
|
||||||
f = open(fullname, "r")
|
|
||||||
except OSError:
|
|
||||||
return
|
|
||||||
with f:
|
|
||||||
for n, line in enumerate(f):
|
|
||||||
if line.startswith("#"):
|
|
||||||
continue
|
|
||||||
try:
|
|
||||||
if line.startswith(("import ", "import\t")):
|
|
||||||
# Change by immerrr: don't evaluate import lines to prevent
|
|
||||||
# code injection into jedi through pth files.
|
|
||||||
#
|
|
||||||
# exec(line)
|
|
||||||
continue
|
|
||||||
line = line.rstrip()
|
|
||||||
dir, dircase = makepath(sitedir, line)
|
|
||||||
if not dircase in known_paths and os.path.exists(dir):
|
|
||||||
sys_path.append(dir)
|
|
||||||
known_paths.add(dircase)
|
|
||||||
except Exception:
|
|
||||||
print("Error processing line {:d} of {}:\n".format(n+1, fullname),
|
|
||||||
file=sys.stderr)
|
|
||||||
import traceback
|
|
||||||
for record in traceback.format_exception(*sys.exc_info()):
|
|
||||||
for line in record.splitlines():
|
|
||||||
print(' '+line, file=sys.stderr)
|
|
||||||
print("\nRemainder of file ignored", file=sys.stderr)
|
|
||||||
break
|
|
||||||
if reset:
|
|
||||||
known_paths = None
|
|
||||||
return known_paths
|
|
||||||
|
|
||||||
|
|
||||||
def addsitedir(sys_path, sitedir, known_paths=None):
|
|
||||||
"""Add 'sitedir' argument to sys_path if missing and handle .pth files in
|
|
||||||
'sitedir'"""
|
|
||||||
if known_paths is None:
|
|
||||||
known_paths = _init_pathinfo(sys_path)
|
|
||||||
reset = 1
|
|
||||||
else:
|
|
||||||
reset = 0
|
|
||||||
sitedir, sitedircase = makepath(sitedir)
|
|
||||||
if not sitedircase in known_paths:
|
|
||||||
sys_path.append(sitedir) # Add path component
|
|
||||||
known_paths.add(sitedircase)
|
|
||||||
try:
|
|
||||||
names = os.listdir(sitedir)
|
|
||||||
except OSError:
|
|
||||||
return
|
|
||||||
names = [name for name in names if name.endswith(".pth")]
|
|
||||||
for name in sorted(names):
|
|
||||||
addpackage(sys_path, sitedir, name, known_paths)
|
|
||||||
if reset:
|
|
||||||
known_paths = None
|
|
||||||
return known_paths
|
|
||||||
@@ -1,8 +1,5 @@
|
|||||||
import glob
|
|
||||||
import os
|
import os
|
||||||
import sys
|
|
||||||
import imp
|
import imp
|
||||||
from jedi.evaluate.site import addsitedir
|
|
||||||
|
|
||||||
from jedi._compatibility import unicode
|
from jedi._compatibility import unicode
|
||||||
from jedi.evaluate.cache import evaluator_method_cache
|
from jedi.evaluate.cache import evaluator_method_cache
|
||||||
@@ -13,62 +10,6 @@ from jedi import debug
|
|||||||
from jedi.evaluate.utils import ignored
|
from jedi.evaluate.utils import ignored
|
||||||
|
|
||||||
|
|
||||||
def get_venv_path(venv):
|
|
||||||
"""Get sys.path for specified virtual environment."""
|
|
||||||
sys_path = _get_venv_path_dirs(venv)
|
|
||||||
with ignored(ValueError):
|
|
||||||
sys_path.remove('')
|
|
||||||
sys_path = _get_sys_path_with_egglinks(sys_path)
|
|
||||||
# As of now, get_venv_path_dirs does not scan built-in pythonpath and
|
|
||||||
# user-local site-packages, let's approximate them using path from Jedi
|
|
||||||
# interpreter.
|
|
||||||
return sys_path + sys.path
|
|
||||||
|
|
||||||
|
|
||||||
def _get_sys_path_with_egglinks(sys_path):
|
|
||||||
"""Find all paths including those referenced by egg-links.
|
|
||||||
|
|
||||||
Egg-link-referenced directories are inserted into path immediately before
|
|
||||||
the directory on which their links were found. Such directories are not
|
|
||||||
taken into consideration by normal import mechanism, but they are traversed
|
|
||||||
when doing pkg_resources.require.
|
|
||||||
"""
|
|
||||||
result = []
|
|
||||||
for p in sys_path:
|
|
||||||
# pkg_resources does not define a specific order for egg-link files
|
|
||||||
# using os.listdir to enumerate them, we're sorting them to have
|
|
||||||
# reproducible tests.
|
|
||||||
for egg_link in sorted(glob.glob(os.path.join(p, '*.egg-link'))):
|
|
||||||
with open(egg_link) as fd:
|
|
||||||
for line in fd:
|
|
||||||
line = line.strip()
|
|
||||||
if line:
|
|
||||||
result.append(os.path.join(p, line))
|
|
||||||
# pkg_resources package only interprets the first
|
|
||||||
# non-empty line in egg-link files.
|
|
||||||
break
|
|
||||||
result.append(p)
|
|
||||||
return result
|
|
||||||
|
|
||||||
|
|
||||||
def _get_venv_path_dirs(venv):
|
|
||||||
"""Get sys.path for venv without starting up the interpreter."""
|
|
||||||
venv = os.path.abspath(venv)
|
|
||||||
sitedir = _get_venv_sitepackages(venv)
|
|
||||||
sys_path = []
|
|
||||||
addsitedir(sys_path, sitedir)
|
|
||||||
return sys_path
|
|
||||||
|
|
||||||
|
|
||||||
def _get_venv_sitepackages(venv):
|
|
||||||
if os.name == 'nt':
|
|
||||||
p = os.path.join(venv, 'lib', 'site-packages')
|
|
||||||
else:
|
|
||||||
p = os.path.join(venv, 'lib', 'python%d.%d' % sys.version_info[:2],
|
|
||||||
'site-packages')
|
|
||||||
return p
|
|
||||||
|
|
||||||
|
|
||||||
def _abs_path(module_context, path):
|
def _abs_path(module_context, path):
|
||||||
module_path = module_context.py__file__()
|
module_path = module_context.py__file__()
|
||||||
if os.path.isabs(path):
|
if os.path.isabs(path):
|
||||||
@@ -87,7 +28,7 @@ def _paths_from_assignment(module_context, expr_stmt):
|
|||||||
"""
|
"""
|
||||||
Extracts the assigned strings from an assignment that looks as follows::
|
Extracts the assigned strings from an assignment that looks as follows::
|
||||||
|
|
||||||
>>> sys.path[0:0] = ['module/path', 'another/module/path']
|
sys.path[0:0] = ['module/path', 'another/module/path']
|
||||||
|
|
||||||
This function is in general pretty tolerant (and therefore 'buggy').
|
This function is in general pretty tolerant (and therefore 'buggy').
|
||||||
However, it's not a big issue usually to add more paths to Jedi's sys_path,
|
However, it's not a big issue usually to add more paths to Jedi's sys_path,
|
||||||
|
|||||||
Reference in New Issue
Block a user