Merge remote-tracking branch 'origin/master' into typeshed

This commit is contained in:
Dave Halter
2018-09-24 00:16:13 +02:00
8 changed files with 118 additions and 34 deletions

View File

@@ -17,7 +17,7 @@ import parso
_VersionInfo = namedtuple('VersionInfo', 'major minor micro') _VersionInfo = namedtuple('VersionInfo', 'major minor micro')
_SUPPORTED_PYTHONS = ['3.6', '3.5', '3.4', '3.3', '2.7'] _SUPPORTED_PYTHONS = ['3.7', '3.6', '3.5', '3.4', '3.3', '2.7']
_SAFE_PATHS = ['/usr/bin', '/usr/local/bin'] _SAFE_PATHS = ['/usr/bin', '/usr/local/bin']
_CURRENT_VERSION = '%s.%s' % (sys.version_info.major, sys.version_info.minor) _CURRENT_VERSION = '%s.%s' % (sys.version_info.major, sys.version_info.minor)
@@ -147,13 +147,18 @@ class InterpreterEnvironment(_BaseEnvironment):
def _get_virtual_env_from_var(): def _get_virtual_env_from_var():
"""Get virtualenv environment from VIRTUAL_ENV environment variable.
It uses `safe=False` with ``create_environment``, because the environment
variable is considered to be safe / controlled by the user solely.
"""
var = os.environ.get('VIRTUAL_ENV') var = os.environ.get('VIRTUAL_ENV')
if var is not None: if var is not None:
if var == sys.prefix: if var == sys.prefix:
return SameEnvironment() return SameEnvironment()
try: try:
return create_environment(var) return create_environment(var, safe=False)
except InvalidPythonEnvironment: except InvalidPythonEnvironment:
pass pass
@@ -318,10 +323,10 @@ def _get_executables_from_windows_registry(version):
# TODO: support Python Anaconda. # TODO: support Python Anaconda.
sub_keys = [ sub_keys = [
r'SOFTWARE\Python\PythonCore\{version}\InstallPath', r'SOFTWARE\Python\PythonCore\{version}\InstallPath',
r'SOFTWARE\Wow6432Node\Python\PythonCore\{version}\InstallPath', r'SOFTWARE\Wow6432Node\Python\PythonCore\{version}\InstallPath',
r'SOFTWARE\Python\PythonCore\{version}-32\InstallPath', r'SOFTWARE\Python\PythonCore\{version}-32\InstallPath',
r'SOFTWARE\Wow6432Node\Python\PythonCore\{version}-32\InstallPath' r'SOFTWARE\Wow6432Node\Python\PythonCore\{version}-32\InstallPath'
] ]
for root_key in [winreg.HKEY_CURRENT_USER, winreg.HKEY_LOCAL_MACHINE]: for root_key in [winreg.HKEY_CURRENT_USER, winreg.HKEY_LOCAL_MACHINE]:
for sub_key in sub_keys: for sub_key in sub_keys:

View File

@@ -358,21 +358,39 @@ class SequenceLiteralContext(Sequence):
return [] # Direct closing bracket, doesn't contain items. return [] # Direct closing bracket, doesn't contain items.
if array_node.type == 'testlist_comp': if array_node.type == 'testlist_comp':
return array_node.children[::2] # filter out (for now) pep 448 single-star unpacking
return [value for value in array_node.children[::2]
if value.type != "star_expr"]
elif array_node.type == 'dictorsetmaker': elif array_node.type == 'dictorsetmaker':
kv = [] kv = []
iterator = iter(array_node.children) iterator = iter(array_node.children)
for key in iterator: for key in iterator:
op = next(iterator, None) if key == "**":
if op is None or op == ',': # dict with pep 448 double-star unpacking
kv.append(key) # A set. # for now ignoring the values imported by **
else: next(iterator)
assert op == ':' # A dict.
kv.append((key, next(iterator)))
next(iterator, None) # Possible comma. next(iterator, None) # Possible comma.
else:
op = next(iterator, None)
if op is None or op == ',':
if key.type == "star_expr":
# pep 448 single-star unpacking
# for now ignoring values imported by *
pass
else:
kv.append(key) # A set.
else:
assert op == ':' # A dict.
kv.append((key, next(iterator)))
next(iterator, None) # Possible comma.
return kv return kv
else: else:
return [array_node] if array_node.type == "star_expr":
# pep 448 single-star unpacking
# for now ignoring values imported by *
return []
else:
return [array_node]
def exact_key_items(self): def exact_key_items(self):
""" """

View File

@@ -264,7 +264,8 @@ def eval_atom(context, atom):
array_node_c = array_node.children array_node_c = array_node.children
except AttributeError: except AttributeError:
array_node_c = [] array_node_c = []
if c[0] == '{' and (array_node == '}' or ':' in array_node_c): if c[0] == '{' and (array_node == '}' or ':' in array_node_c or
'**' in array_node_c):
context = iterable.DictLiteralContext(context.evaluator, context, atom) context = iterable.DictLiteralContext(context.evaluator, context, atom)
else: else:
context = iterable.SequenceLiteralContext(context.evaluator, context, atom) context = iterable.SequenceLiteralContext(context.evaluator, context, atom)

View File

@@ -31,7 +31,15 @@ setup(name='jedi',
packages=find_packages(exclude=['test', 'test.*']), packages=find_packages(exclude=['test', 'test.*']),
python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*', python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*',
install_requires=install_requires, install_requires=install_requires,
extras_require={'dev': ['docopt']}, extras_require={
'testing': [
'pytest>=2.3.5',
# docopt for sith doctests
'docopt',
# coloroma for colored debug output
'colorama',
],
},
package_data={'jedi': ['evaluate/compiled/fake/*.pym']}, package_data={'jedi': ['evaluate/compiled/fake/*.pym']},
platforms=['any'], platforms=['any'],
classifiers=[ classifiers=[

View File

@@ -131,3 +131,46 @@ set_t2 = set()
#? ['clear', 'copy'] #? ['clear', 'copy']
set_t2.c set_t2.c
# -----------------
# pep 448 unpacking generalizations
# -----------------
# python >= 3.5
d = {'a': 3}
#? dict()
{**d}
#? str()
{**d, "b": "b"}["b"]
# Should resolve to int() but jedi is not smart enough yet
# Here to make sure it doesn't result in crash though
#?
{**d}["a"]
s = {1, 2, 3}
#? set()
{*s}
#? set()
{*s, 4, *s}
s = {1, 2, 3}
# Should resolve to int() but jedi is not smart enough yet
# Here to make sure it doesn't result in crash though
#?
{*s}.pop()
#? int()
{*s, 4}.pop()
# Should resolve to int() but jedi is not smart enough yet
# Here to make sure it doesn't result in crash though
#?
[*s][0]
#? int()
[*s, 4][0]

View File

@@ -126,11 +126,12 @@ class StaticAnalysisCase(object):
return "<%s: %s>" % (self.__class__.__name__, os.path.basename(self._path)) return "<%s: %s>" % (self.__class__.__name__, os.path.basename(self._path))
@pytest.fixture() @pytest.fixture(scope='session')
def venv_path(tmpdir, environment): def venv_path(tmpdir_factory, environment):
if environment.version_info.major < 3: if environment.version_info.major < 3:
pytest.skip("python -m venv does not exist in Python 2") pytest.skip("python -m venv does not exist in Python 2")
tmpdir = tmpdir_factory.mktemp('venv_path')
dirname = os.path.join(tmpdir.dirname, 'venv') dirname = os.path.join(tmpdir.dirname, 'venv')
# We cannot use the Python from tox because tox creates virtualenvs and # We cannot use the Python from tox because tox creates virtualenvs and

View File

@@ -110,3 +110,22 @@ def test_create_environment_venv_path(venv_path):
def test_create_environment_executable(): def test_create_environment_executable():
environment = create_environment(sys.executable) environment = create_environment(sys.executable)
assert environment.executable == sys.executable assert environment.executable == sys.executable
def test_get_default_environment_from_env_does_not_use_safe(tmpdir, monkeypatch):
fake_python = os.path.join(str(tmpdir), 'fake_python')
with open(fake_python, 'w') as f:
f.write('')
def _get_subprocess(self):
if self._start_executable != fake_python:
raise RuntimeError('Should not get called!')
self.executable = fake_python
self.path = 'fake'
monkeypatch.setattr('jedi.api.environment.Environment._get_subprocess',
_get_subprocess)
monkeypatch.setenv('VIRTUAL_ENV', fake_python)
env = get_default_environment()
assert env.path == 'fake'

21
tox.ini
View File

@@ -1,16 +1,10 @@
[tox] [tox]
envlist = py27, py34, py35, py36 envlist = py27, py34, py35, py36
[testenv] [testenv]
deps = extras = testing
pytest>=2.3.5
pytest-cache
# docopt for sith doctests
docopt
# coloroma for colored debug output
colorama
# Overwrite the parso version (only used sometimes). # Overwrite the parso version (only used sometimes).
# git+https://github.com/davidhalter/parso.git # deps =
-rrequirements.txt # git+https://github.com/davidhalter/parso.git
passenv = JEDI_TEST_ENVIRONMENT passenv = JEDI_TEST_ENVIRONMENT
setenv = setenv =
# https://github.com/tomchristie/django-rest-framework/issues/1957 # https://github.com/tomchristie/django-rest-framework/issues/1957
@@ -24,34 +18,29 @@ setenv =
env36: JEDI_TEST_ENVIRONMENT=36 env36: JEDI_TEST_ENVIRONMENT=36
env37: JEDI_TEST_ENVIRONMENT=37 env37: JEDI_TEST_ENVIRONMENT=37
commands = commands =
py.test {posargs:jedi test} pytest {posargs:jedi test}
[testenv:py27] [testenv:py27]
deps = deps =
# for testing the typing module # for testing the typing module
typing typing
# numpydoc for typing scipy stack # numpydoc for typing scipy stack
numpydoc numpydoc
{[testenv]deps}
[testenv:py34] [testenv:py34]
deps = deps =
typing typing
numpydoc numpydoc
{[testenv]deps}
[testenv:py35] [testenv:py35]
deps = deps =
numpydoc numpydoc
{[testenv]deps}
[testenv:py36] [testenv:py36]
deps = deps =
numpydoc numpydoc
{[testenv]deps}
[testenv:cov] [testenv:cov]
deps = deps =
coverage coverage
numpydoc numpydoc
{[testenv]deps}
commands = commands =
coverage run --source jedi -m py.test coverage run --source jedi -m pytest
coverage report coverage report
[testenv:sith] [testenv:sith]
commands = commands =