mirror of
https://github.com/davidhalter/jedi.git
synced 2025-12-07 22:44:27 +08:00
Make the subprocesses work and return the right sys paths for the different versions
This commit is contained in:
@@ -289,25 +289,3 @@ def utf8_repr(func):
|
|||||||
return func
|
return func
|
||||||
else:
|
else:
|
||||||
return wrapper
|
return wrapper
|
||||||
|
|
||||||
|
|
||||||
try:
|
|
||||||
from subprocess import check_output
|
|
||||||
except ImportError:
|
|
||||||
def check_output(*popenargs, **kwargs):
|
|
||||||
"""
|
|
||||||
Taken from Python 2.6.
|
|
||||||
"""
|
|
||||||
from subprocess import Popen, PIPE, CalledProcessError
|
|
||||||
|
|
||||||
if 'stdout' in kwargs:
|
|
||||||
raise ValueError('stdout argument not allowed, it will be overridden.')
|
|
||||||
process = Popen(stdout=PIPE, *popenargs, **kwargs)
|
|
||||||
output, unused_err = process.communicate()
|
|
||||||
retcode = process.poll()
|
|
||||||
if retcode:
|
|
||||||
cmd = kwargs.get("args")
|
|
||||||
if cmd is None:
|
|
||||||
cmd = popenargs[0]
|
|
||||||
raise CalledProcessError(retcode, cmd, output=output)
|
|
||||||
return output
|
|
||||||
|
|||||||
@@ -1,11 +1,9 @@
|
|||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import sys
|
import sys
|
||||||
import sysconfig
|
from subprocess import Popen, PIPE
|
||||||
from subprocess import CalledProcessError
|
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
|
|
||||||
from jedi._compatibility import check_output
|
|
||||||
from jedi.evaluate.project import Project
|
from jedi.evaluate.project import Project
|
||||||
from jedi.cache import memoize_method
|
from jedi.cache import memoize_method
|
||||||
from jedi.evaluate.compiled.subprocess import get_subprocess
|
from jedi.evaluate.compiled.subprocess import get_subprocess
|
||||||
@@ -34,16 +32,11 @@ class Environment(object):
|
|||||||
|
|
||||||
@memoize_method
|
@memoize_method
|
||||||
def get_sys_path(self):
|
def get_sys_path(self):
|
||||||
vars = {
|
|
||||||
'base': self._path
|
|
||||||
}
|
|
||||||
lib_path = sysconfig.get_path('stdlib', vars=vars)
|
|
||||||
# It's pretty much impossible to generate the sys path without actually
|
# It's pretty much impossible to generate the sys path without actually
|
||||||
# executing Python. The sys path (when starting with -S) itself depends
|
# executing Python. The sys path (when starting with -S) itself depends
|
||||||
# on how the Python version was compiled (ENV variables).
|
# on how the Python version was compiled (ENV variables).
|
||||||
# If you omit -S when starting Python (normal case), additionally
|
# If you omit -S when starting Python (normal case), additionally
|
||||||
# site.py gets executed.
|
# site.py gets executed.
|
||||||
|
|
||||||
return self.get_subprocess().get_sys_path()
|
return self.get_subprocess().get_sys_path()
|
||||||
|
|
||||||
|
|
||||||
@@ -80,11 +73,18 @@ def _get_executable_path(path):
|
|||||||
|
|
||||||
def _get_version(executable):
|
def _get_version(executable):
|
||||||
try:
|
try:
|
||||||
output = check_output([executable, '--version'])
|
process = Popen([executable, '--version'], stdout=PIPE, stderr=PIPE)
|
||||||
except (CalledProcessError, OSError):
|
stdout, stderr = process.communicate()
|
||||||
|
retcode = process.poll()
|
||||||
|
if retcode:
|
||||||
|
raise NoVirtualEnv()
|
||||||
|
except OSError:
|
||||||
raise NoVirtualEnv()
|
raise NoVirtualEnv()
|
||||||
|
|
||||||
match = re.match(rb'Python (\d+)\.(\d+)\.(\d+)', output)
|
# Until Python 3.4 wthe version string is part of stderr, after that
|
||||||
|
# stdout.
|
||||||
|
output = stdout + stderr
|
||||||
|
match = re.match(br'Python (\d+)\.(\d+)\.(\d+)', output)
|
||||||
if match is None:
|
if match is None:
|
||||||
raise NoVirtualEnv()
|
raise NoVirtualEnv()
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ goals:
|
|||||||
2. Make it possible to handle different Python versions as well as virtualenvs.
|
2. Make it possible to handle different Python versions as well as virtualenvs.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
import sys
|
import sys
|
||||||
import subprocess
|
import subprocess
|
||||||
import weakref
|
import weakref
|
||||||
@@ -20,6 +21,8 @@ _PICKLE_PROTOCOL = 2
|
|||||||
|
|
||||||
_subprocesses = {}
|
_subprocesses = {}
|
||||||
|
|
||||||
|
_MAIN_PATH = os.path.join(os.path.dirname(__file__), '__main__.py')
|
||||||
|
|
||||||
|
|
||||||
def get_subprocess(executable):
|
def get_subprocess(executable):
|
||||||
try:
|
try:
|
||||||
@@ -88,8 +91,12 @@ class _Subprocess(object):
|
|||||||
|
|
||||||
class _CompiledSubprocess(_Subprocess):
|
class _CompiledSubprocess(_Subprocess):
|
||||||
def __init__(self, executable):
|
def __init__(self, executable):
|
||||||
|
parso_path = sys.modules['parso'].__file__
|
||||||
super(_CompiledSubprocess, self).__init__(
|
super(_CompiledSubprocess, self).__init__(
|
||||||
(executable, '-m', 'jedi.evaluate.compiled.subprocess')
|
(executable,
|
||||||
|
_MAIN_PATH,
|
||||||
|
os.path.dirname(os.path.dirname(parso_path))
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
def run(self, evaluator, function, *args, **kwargs):
|
def run(self, evaluator, function, *args, **kwargs):
|
||||||
|
|||||||
@@ -1,3 +1,15 @@
|
|||||||
|
import sys
|
||||||
|
import os
|
||||||
|
|
||||||
|
# Get the path to jedi.
|
||||||
|
_d = os.path.dirname
|
||||||
|
_jedi_path = _d(_d(_d(_d(_d(__file__)))))
|
||||||
|
_parso_path = sys.argv[1]
|
||||||
|
|
||||||
|
# This is kind of stupid. We actually don't want to modify the sys path but
|
||||||
|
# simply import something from a specific location.
|
||||||
|
sys.path[0:0] = [_jedi_path, _parso_path]
|
||||||
from jedi.evaluate.compiled import subprocess
|
from jedi.evaluate.compiled import subprocess
|
||||||
|
sys.path[0:2] = []
|
||||||
|
|
||||||
subprocess.Listener().listen()
|
subprocess.Listener().listen()
|
||||||
|
|||||||
@@ -17,7 +17,6 @@ from __future__ import print_function
|
|||||||
|
|
||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
from sysconfig import get_config_var
|
|
||||||
|
|
||||||
|
|
||||||
def makepath(*paths):
|
def makepath(*paths):
|
||||||
@@ -109,8 +108,3 @@ def addsitedir(sys_path, sitedir, known_paths=None):
|
|||||||
if reset:
|
if reset:
|
||||||
known_paths = None
|
known_paths = None
|
||||||
return known_paths
|
return known_paths
|
||||||
|
|
||||||
|
|
||||||
def getuserbase():
|
|
||||||
"""Returns the `user base` directory path."""
|
|
||||||
return get_config_var('userbase')
|
|
||||||
|
|||||||
@@ -1,5 +1,26 @@
|
|||||||
from jedi.api.virtualenv import Environment, DefaultEnvironment
|
import pytest
|
||||||
|
|
||||||
|
from jedi._compatibility import py_version
|
||||||
|
from jedi.api.virtualenv import Environment, DefaultEnvironment, NoVirtualEnv
|
||||||
|
|
||||||
|
|
||||||
def test_sys_path():
|
def test_sys_path():
|
||||||
assert DefaultEnvironment('/foo').get_sys_path()
|
assert DefaultEnvironment('/foo').get_sys_path()
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
'version',
|
||||||
|
['2.6', '2.7', '3.3', '3.4', '3.5', '3.6', '3.7']
|
||||||
|
)
|
||||||
|
def test_versions(version):
|
||||||
|
executable = 'python' + version
|
||||||
|
try:
|
||||||
|
env = Environment('some path', executable)
|
||||||
|
except NoVirtualEnv:
|
||||||
|
if int(version.replace('.', '')) == py_version:
|
||||||
|
# At least the current version has to work
|
||||||
|
raise
|
||||||
|
return
|
||||||
|
|
||||||
|
sys_path = env.get_sys_path()
|
||||||
|
assert any(executable in p for p in sys_path)
|
||||||
|
|||||||
Reference in New Issue
Block a user