mirror of
https://github.com/davidhalter/jedi.git
synced 2026-01-09 21:42:20 +08:00
Merge dev into linter.
This commit is contained in:
@@ -1,7 +1,5 @@
|
||||
import os
|
||||
import shutil
|
||||
import re
|
||||
import tempfile
|
||||
|
||||
import pytest
|
||||
|
||||
@@ -125,25 +123,3 @@ def isolated_jedi_cache(monkeypatch, tmpdir):
|
||||
"""
|
||||
from jedi import settings
|
||||
monkeypatch.setattr(settings, 'cache_directory', str(tmpdir))
|
||||
|
||||
|
||||
@pytest.fixture(scope='session')
|
||||
def clean_jedi_cache(request):
|
||||
"""
|
||||
Set `jedi.settings.cache_directory` to a temporary directory during test.
|
||||
|
||||
Note that you can't use built-in `tmpdir` and `monkeypatch`
|
||||
fixture here because their scope is 'function', which is not used
|
||||
in 'session' scope fixture.
|
||||
|
||||
This fixture is activated in ../pytest.ini.
|
||||
"""
|
||||
from jedi import settings
|
||||
old = settings.cache_directory
|
||||
tmp = tempfile.mkdtemp(prefix='jedi-test-')
|
||||
settings.cache_directory = tmp
|
||||
|
||||
@request.addfinalizer
|
||||
def restore():
|
||||
settings.cache_directory = old
|
||||
shutil.rmtree(tmp)
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
# This file is here to force git to create the directory, as *.pth files only
|
||||
# add existing directories.
|
||||
@@ -0,0 +1 @@
|
||||
./dir-from-foo-pth
|
||||
@@ -0,0 +1 @@
|
||||
import smth; smth.extend_path()
|
||||
@@ -0,0 +1 @@
|
||||
./relative/egg-link/path
|
||||
@@ -0,0 +1,6 @@
|
||||
import sys
|
||||
sys.path.append('/path/from/smth.py')
|
||||
|
||||
|
||||
def extend_path():
|
||||
sys.path.append('/path/from/smth.py:extend_path')
|
||||
@@ -0,0 +1,2 @@
|
||||
# This file is here to force git to create the directory, as *.pth files only
|
||||
# add existing directories.
|
||||
@@ -0,0 +1 @@
|
||||
/path/from/egg-link
|
||||
@@ -0,0 +1 @@
|
||||
./dir-from-foo-pth
|
||||
@@ -0,0 +1 @@
|
||||
import smth; smth.extend_path()
|
||||
@@ -0,0 +1 @@
|
||||
./relative/egg-link/path
|
||||
@@ -0,0 +1,6 @@
|
||||
import sys
|
||||
sys.path.append('/path/from/smth.py')
|
||||
|
||||
|
||||
def extend_path():
|
||||
sys.path.append('/path/from/smth.py:extend_path')
|
||||
@@ -46,11 +46,8 @@ def test_flask_ext(script, name):
|
||||
"""flask.ext.foo is really imported from flaskext.foo or flask_foo.
|
||||
"""
|
||||
path = os.path.join(os.path.dirname(__file__), 'flask-site-packages')
|
||||
sys.path.append(path)
|
||||
try:
|
||||
assert name in [c.name for c in jedi.Script(script).completions()]
|
||||
finally:
|
||||
sys.path.remove(path)
|
||||
completions = jedi.Script(script, sys_path=[path]).completions()
|
||||
assert name in [c.name for c in completions]
|
||||
|
||||
|
||||
@cwd_at('test/test_evaluate/')
|
||||
@@ -64,3 +61,19 @@ def test_import_unique():
|
||||
defs = jedi.Script(src, path='example.py').goto_definitions()
|
||||
defs = [d._definition for d in defs]
|
||||
assert len(defs) == len(set(defs))
|
||||
|
||||
|
||||
def test_cache_works_with_sys_path_param(tmpdir):
|
||||
foo_path = tmpdir.join('foo')
|
||||
bar_path = tmpdir.join('bar')
|
||||
foo_path.join('module.py').write('foo = 123', ensure=True)
|
||||
bar_path.join('module.py').write('bar = 123', ensure=True)
|
||||
foo_completions = jedi.Script('import module; module.',
|
||||
sys_path=[foo_path.strpath]).completions()
|
||||
bar_completions = jedi.Script('import module; module.',
|
||||
sys_path=[bar_path.strpath]).completions()
|
||||
assert 'foo' in [c.name for c in foo_completions]
|
||||
assert 'bar' not in [c.name for c in foo_completions]
|
||||
|
||||
assert 'bar' in [c.name for c in bar_completions]
|
||||
assert 'foo' not in [c.name for c in bar_completions]
|
||||
|
||||
@@ -1,55 +1,53 @@
|
||||
import jedi
|
||||
import sys
|
||||
from os.path import dirname, join
|
||||
|
||||
|
||||
def test_namespace_package():
|
||||
sys.path.insert(0, join(dirname(__file__), 'namespace_package/ns1'))
|
||||
sys.path.insert(1, join(dirname(__file__), 'namespace_package/ns2'))
|
||||
try:
|
||||
# goto definition
|
||||
assert jedi.Script('from pkg import ns1_file').goto_definitions()
|
||||
assert jedi.Script('from pkg import ns2_file').goto_definitions()
|
||||
assert not jedi.Script('from pkg import ns3_file').goto_definitions()
|
||||
sys_path = [join(dirname(__file__), d)
|
||||
for d in ['namespace_package/ns1', 'namespace_package/ns2']]
|
||||
|
||||
# goto assignment
|
||||
tests = {
|
||||
'from pkg.ns2_folder.nested import foo': 'nested!',
|
||||
'from pkg.ns2_folder import foo': 'ns2_folder!',
|
||||
'from pkg.ns2_file import foo': 'ns2_file!',
|
||||
'from pkg.ns1_folder import foo': 'ns1_folder!',
|
||||
'from pkg.ns1_file import foo': 'ns1_file!',
|
||||
'from pkg import foo': 'ns1!',
|
||||
}
|
||||
for source, solution in tests.items():
|
||||
ass = jedi.Script(source).goto_assignments()
|
||||
assert len(ass) == 1
|
||||
assert ass[0].description == "foo = '%s'" % solution
|
||||
def script_with_path(*args, **kwargs):
|
||||
return jedi.Script(sys_path=sys_path, *args, **kwargs)
|
||||
|
||||
# completion
|
||||
completions = jedi.Script('from pkg import ').completions()
|
||||
names = [str(c.name) for c in completions] # str because of unicode
|
||||
compare = ['foo', 'ns1_file', 'ns1_folder', 'ns2_folder', 'ns2_file',
|
||||
'pkg_resources', 'pkgutil', '__name__', '__path__',
|
||||
'__package__', '__file__', '__doc__']
|
||||
# must at least contain these items, other items are not important
|
||||
assert set(compare) == set(names)
|
||||
# goto definition
|
||||
assert script_with_path('from pkg import ns1_file').goto_definitions()
|
||||
assert script_with_path('from pkg import ns2_file').goto_definitions()
|
||||
assert not script_with_path('from pkg import ns3_file').goto_definitions()
|
||||
|
||||
tests = {
|
||||
'from pkg import ns2_folder as x': 'ns2_folder!',
|
||||
'from pkg import ns2_file as x': 'ns2_file!',
|
||||
'from pkg.ns2_folder import nested as x': 'nested!',
|
||||
'from pkg import ns1_folder as x': 'ns1_folder!',
|
||||
'from pkg import ns1_file as x': 'ns1_file!',
|
||||
'import pkg as x': 'ns1!',
|
||||
}
|
||||
for source, solution in tests.items():
|
||||
for c in jedi.Script(source + '; x.').completions():
|
||||
if c.name == 'foo':
|
||||
completion = c
|
||||
solution = "statement: foo = '%s'" % solution
|
||||
assert completion.description == solution
|
||||
# goto assignment
|
||||
tests = {
|
||||
'from pkg.ns2_folder.nested import foo': 'nested!',
|
||||
'from pkg.ns2_folder import foo': 'ns2_folder!',
|
||||
'from pkg.ns2_file import foo': 'ns2_file!',
|
||||
'from pkg.ns1_folder import foo': 'ns1_folder!',
|
||||
'from pkg.ns1_file import foo': 'ns1_file!',
|
||||
'from pkg import foo': 'ns1!',
|
||||
}
|
||||
for source, solution in tests.items():
|
||||
ass = script_with_path(source).goto_assignments()
|
||||
assert len(ass) == 1
|
||||
assert ass[0].description == "foo = '%s'" % solution
|
||||
|
||||
finally:
|
||||
sys.path.pop(0)
|
||||
sys.path.pop(0)
|
||||
# completion
|
||||
completions = script_with_path('from pkg import ').completions()
|
||||
names = [str(c.name) for c in completions] # str because of unicode
|
||||
compare = ['foo', 'ns1_file', 'ns1_folder', 'ns2_folder', 'ns2_file',
|
||||
'pkg_resources', 'pkgutil', '__name__', '__path__',
|
||||
'__package__', '__file__', '__doc__']
|
||||
# must at least contain these items, other items are not important
|
||||
assert set(compare) == set(names)
|
||||
|
||||
tests = {
|
||||
'from pkg import ns2_folder as x': 'ns2_folder!',
|
||||
'from pkg import ns2_file as x': 'ns2_file!',
|
||||
'from pkg.ns2_folder import nested as x': 'nested!',
|
||||
'from pkg import ns1_folder as x': 'ns1_folder!',
|
||||
'from pkg import ns1_file as x': 'ns1_file!',
|
||||
'import pkg as x': 'ns1!',
|
||||
}
|
||||
for source, solution in tests.items():
|
||||
for c in script_with_path(source + '; x.').completions():
|
||||
if c.name == 'foo':
|
||||
completion = c
|
||||
solution = "statement: foo = '%s'" % solution
|
||||
assert completion.description == solution
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
import os
|
||||
from glob import glob
|
||||
import sys
|
||||
|
||||
import pytest
|
||||
|
||||
from jedi._compatibility import unicode
|
||||
from jedi.parser import Parser, load_grammar
|
||||
@@ -19,13 +23,37 @@ def test_paths_from_assignment():
|
||||
assert paths('sys.path, other = ["a"], 2') == set()
|
||||
|
||||
|
||||
def test_get_sys_path(monkeypatch):
|
||||
monkeypatch.setenv('VIRTUAL_ENV', os.path.join(os.path.dirname(__file__),
|
||||
'egg-link', 'venv'))
|
||||
def sitepackages_dir(venv):
|
||||
return os.path.join(venv, 'lib', 'python3.4', 'site-packages')
|
||||
# Currently venv site-packages resolution only seeks pythonX.Y/site-packages
|
||||
# that belong to the same version as the interpreter to avoid issues with
|
||||
# cross-version imports. "venvs/" dir contains "venv27" and "venv34" that
|
||||
# mimic venvs created for py2.7 and py3.4 respectively. If test runner is
|
||||
# invoked with one of those versions, the test below will be run for the
|
||||
# matching directory.
|
||||
CUR_DIR = os.path.dirname(__file__)
|
||||
VENVS = list(glob(
|
||||
os.path.join(CUR_DIR, 'sample_venvs/venv%d%d' % sys.version_info[:2])))
|
||||
|
||||
monkeypatch.setattr('jedi.evaluate.sys_path._get_venv_sitepackages',
|
||||
sitepackages_dir)
|
||||
|
||||
assert '/path/from/egg-link' in sys_path.get_sys_path()
|
||||
@pytest.mark.parametrize('venv', VENVS)
|
||||
def test_get_venv_path(venv):
|
||||
pjoin = os.path.join
|
||||
venv_path = sys_path.get_venv_path(venv)
|
||||
|
||||
site_pkgs = (glob(pjoin(venv, 'lib', 'python*', 'site-packages')) +
|
||||
glob(pjoin(venv, 'lib', 'site-packages')))[0]
|
||||
ETALON = [
|
||||
site_pkgs,
|
||||
pjoin('/path', 'from', 'egg-link'),
|
||||
pjoin(site_pkgs, '.', 'relative', 'egg-link', 'path'),
|
||||
pjoin(site_pkgs, 'dir-from-foo-pth'),
|
||||
]
|
||||
|
||||
# Ensure that pth and egg-link paths were added.
|
||||
assert venv_path[:len(ETALON)] == ETALON
|
||||
|
||||
# Ensure that none of venv dirs leaked to the interpreter.
|
||||
assert not set(sys.path).intersection(ETALON)
|
||||
|
||||
# Ensure that "import ..." lines were ignored.
|
||||
assert pjoin('/path', 'from', 'smth.py') not in venv_path
|
||||
assert pjoin('/path', 'from', 'smth.py:extend_path') not in venv_path
|
||||
|
||||
64
test/test_parser/test_parser_tree.py
Normal file
64
test/test_parser/test_parser_tree.py
Normal file
@@ -0,0 +1,64 @@
|
||||
# -*- coding: utf-8 # This file contains Unicode characters.
|
||||
|
||||
from textwrap import dedent
|
||||
|
||||
import pytest
|
||||
|
||||
from jedi._compatibility import u, unicode
|
||||
from jedi.parser import Parser, load_grammar
|
||||
from jedi.parser import tree as pt
|
||||
|
||||
|
||||
class TestsFunctionAndLambdaParsing(object):
|
||||
|
||||
FIXTURES = [
|
||||
('def my_function(x, y, z):\n return x + y * z\n', {
|
||||
'name': 'my_function',
|
||||
'call_sig': 'my_function(x, y, z)',
|
||||
'params': ['x', 'y', 'z'],
|
||||
}),
|
||||
('lambda x, y, z: x + y * z\n', {
|
||||
'name': '<lambda>',
|
||||
'call_sig': '<lambda>(x, y, z)',
|
||||
'params': ['x', 'y', 'z'],
|
||||
}),
|
||||
]
|
||||
|
||||
@pytest.fixture(params=FIXTURES)
|
||||
def node(self, request):
|
||||
parsed = Parser(load_grammar(), dedent(u(request.param[0])))
|
||||
request.keywords['expected'] = request.param[1]
|
||||
return parsed.module.subscopes[0]
|
||||
|
||||
@pytest.fixture()
|
||||
def expected(self, request, node):
|
||||
return request.keywords['expected']
|
||||
|
||||
def test_name(self, node, expected):
|
||||
assert isinstance(node.name, pt.Name)
|
||||
assert unicode(node.name) == u(expected['name'])
|
||||
|
||||
def test_params(self, node, expected):
|
||||
assert isinstance(node.params, list)
|
||||
assert all(isinstance(x, pt.Param) for x in node.params)
|
||||
assert [unicode(x.name) for x in node.params] == [u(x) for x in expected['params']]
|
||||
|
||||
def test_is_generator(self, node, expected):
|
||||
assert node.is_generator() is expected.get('is_generator', False)
|
||||
|
||||
def test_yields(self, node, expected):
|
||||
# TODO: There's a comment in the code noting that the current implementation is incorrect. This returns an
|
||||
# empty list at the moment (not e.g. False).
|
||||
if expected.get('yields', False):
|
||||
assert node.yields
|
||||
else:
|
||||
assert not node.yields
|
||||
|
||||
def test_annotation(self, node, expected):
|
||||
assert node.annotation() is expected.get('annotation', None)
|
||||
|
||||
def test_get_call_signature(self, node, expected):
|
||||
assert node.get_call_signature() == expected['call_sig']
|
||||
|
||||
def test_doc(self, node, expected):
|
||||
assert node.doc == expected.get('doc') or (expected['call_sig'] + '\n\n')
|
||||
@@ -66,8 +66,9 @@ class TestRegression(TestCase):
|
||||
src1 = "def r(a): return a"
|
||||
# Other fictional modules in another place in the fs.
|
||||
src2 = 'from .. import setup; setup.r(1)'
|
||||
imports.load_module(os.path.abspath(fname), src2)
|
||||
result = Script(src1, path='../setup.py').goto_definitions()
|
||||
script = Script(src1, path='../setup.py')
|
||||
imports.load_module(script._evaluator, os.path.abspath(fname), src2)
|
||||
result = script.goto_definitions()
|
||||
assert len(result) == 1
|
||||
assert result[0].description == 'class int'
|
||||
|
||||
|
||||
Reference in New Issue
Block a user