Merge dev into linter.

This commit is contained in:
Dave Halter
2015-11-10 21:49:32 +01:00
32 changed files with 451 additions and 123 deletions

View File

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

View File

@@ -0,0 +1,2 @@
# This file is here to force git to create the directory, as *.pth files only
# add existing directories.

View File

@@ -0,0 +1 @@
./dir-from-foo-pth

View File

@@ -0,0 +1 @@
import smth; smth.extend_path()

View File

@@ -0,0 +1 @@
./relative/egg-link/path

View File

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

View File

@@ -0,0 +1,2 @@
# This file is here to force git to create the directory, as *.pth files only
# add existing directories.

View File

@@ -0,0 +1 @@
/path/from/egg-link

View File

@@ -0,0 +1 @@
./dir-from-foo-pth

View File

@@ -0,0 +1 @@
import smth; smth.extend_path()

View File

@@ -0,0 +1 @@
./relative/egg-link/path

View File

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

View File

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

View File

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

View File

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

View 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')

View File

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