1
0
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:
Dave Halter
2017-12-19 21:05:04 +01:00
parent 96a67f9a4c
commit 456ae20aac
4 changed files with 17 additions and 195 deletions

View File

@@ -66,7 +66,7 @@ class InterpreterEnvironment(_BaseEnvironment):
return EvaluatorSameProcess(evaluator)
def get_sys_path(self):
return sys.sys_path
return sys.path
def get_default_environment():

View File

@@ -1,7 +1,4 @@
import os
import sys
from jedi.evaluate.sys_path import get_venv_path, detect_additional_paths
from jedi.evaluate.sys_path import detect_additional_paths
from jedi.cache import memoize_method
@@ -9,24 +6,8 @@ class Project(object):
def __init__(self, sys_path=None):
self._script_path = None
if sys_path is not None:
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):
self._script_path = script_path
@@ -36,7 +17,17 @@ class Project(object):
@property
@memoize_method
def sys_path(self):
if self._script_path is None:
return self._base_sys_path
sys_path = 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)

View File

@@ -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

View File

@@ -1,8 +1,5 @@
import glob
import os
import sys
import imp
from jedi.evaluate.site import addsitedir
from jedi._compatibility import unicode
from jedi.evaluate.cache import evaluator_method_cache
@@ -13,62 +10,6 @@ from jedi import debug
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):
module_path = module_context.py__file__()
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::
>>> 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').
However, it's not a big issue usually to add more paths to Jedi's sys_path,