1
0
forked from VimPlug/jedi

test_evaluate -> test_inference

This commit is contained in:
Dave Halter
2019-08-14 23:56:44 +02:00
parent a23bbbfbb9
commit e4d1e5455f
62 changed files with 5 additions and 5 deletions

View File

View File

@@ -0,0 +1,14 @@
"""
This is a module that imports the *standard library* unittest,
despite there being a local "unittest" module. It specifies that it
wants the stdlib one with the ``absolute_import`` __future__ import.
The twisted equivalent of this module is ``twisted.trial._synctest``.
"""
from __future__ import absolute_import
import unittest
class Assertions(unittest.TestCase):
pass

View File

@@ -0,0 +1,14 @@
"""
This is a module that shadows a builtin (intentionally).
It imports a local module, which in turn imports stdlib unittest (the
name shadowed by this module). If that is properly resolved, there's
no problem. However, if jedi doesn't understand absolute_imports, it
will get this module again, causing infinite recursion.
"""
from local_module import Assertions
class TestCase(Assertions):
def test(self):
self.assertT

View File

@@ -0,0 +1 @@

View File

@@ -0,0 +1 @@

View File

@@ -0,0 +1 @@
Baz = 1

View File

@@ -0,0 +1,2 @@
class Foo(object):
pass

View File

@@ -0,0 +1,2 @@
class Bar(object):
pass

View File

@@ -0,0 +1 @@
Moo = 1

View File

@@ -0,0 +1 @@
foo = 'ns1_file!'

View File

@@ -0,0 +1 @@
foo = 'ns2_file!'

View File

@@ -0,0 +1 @@
CONST = 1

View File

@@ -0,0 +1,15 @@
#include "Python.h"
static struct PyModuleDef module = {
PyModuleDef_HEAD_INIT,
"init_extension_module",
NULL,
-1,
NULL
};
PyMODINIT_FUNC PyInit_init_extension_module(void){
PyObject *m = PyModule_Create(&module);
PyModule_AddObject(m, "foo", Py_None);
return m;
}

View File

@@ -0,0 +1,10 @@
from distutils.core import setup, Extension
setup(name='init_extension_module',
version='0.0',
description='',
ext_modules=[
Extension('init_extension_module.__init__',
sources=['module.c'])
]
)

View File

@@ -0,0 +1,9 @@
foo = 'ns1!'
# this is a namespace package
try:
import pkg_resources
pkg_resources.declare_namespace(__name__)
except ImportError:
import pkgutil
__path__ = pkgutil.extend_path(__path__, __name__)

View File

@@ -0,0 +1 @@
foo = 'ns1_file!'

View File

@@ -0,0 +1 @@
foo = 'ns1_folder!'

View File

@@ -0,0 +1 @@
foo = 'ns2_file!'

View File

@@ -0,0 +1 @@
foo = 'ns2_folder!'

View File

@@ -0,0 +1 @@
foo = 'nested!'

View File

@@ -0,0 +1,4 @@
try:
__import__('pkg_resources').declare_namespace(__name__)
except ImportError:
pass

View File

@@ -0,0 +1 @@
CONST = 1

View File

@@ -0,0 +1 @@
value = 3

View File

@@ -0,0 +1 @@
value = 'package'

View File

@@ -0,0 +1 @@
value = 'package.module'

View File

@@ -0,0 +1,7 @@
from not_in_sys_path import not_in_sys_path
from not_in_sys_path import not_in_sys_path_package
from not_in_sys_path.not_in_sys_path_package import module
not_in_sys_path.value
not_in_sys_path_package.value
module.value

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_foo()

View File

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

View File

@@ -0,0 +1,6 @@
import sys
sys.path.append('/foo/smth.py:module')
def extend_path_foo():
sys.path.append('/foo/smth.py:from_func')

View File

@@ -0,0 +1,11 @@
"""
Tests ``from __future__ import absolute_import`` (only important for
Python 2.X)
"""
from .. import helpers
@helpers.cwd_at("test/test_inference/absolute_import")
def test_can_complete_when_shadowing(Script):
script = Script(path="unittest.py")
assert script.completions()

View File

@@ -0,0 +1,64 @@
from textwrap import dedent
import pytest
def test_simple_annotations(Script, environment):
"""
Annotations only exist in Python 3.
If annotations adhere to PEP-0484, we use them (they override inference),
else they are parsed but ignored
"""
if environment.version_info.major == 2:
pytest.skip()
source = dedent("""\
def annot(a:3):
return a
annot('')""")
assert [d.name for d in Script(source).goto_definitions()] == ['str']
source = dedent("""\
def annot_ret(a:3) -> 3:
return a
annot_ret('')""")
assert [d.name for d in Script(source).goto_definitions()] == ['str']
source = dedent("""\
def annot(a:int):
return a
annot('')""")
assert [d.name for d in Script(source).goto_definitions()] == ['int']
@pytest.mark.parametrize('reference', [
'assert 1',
'1',
'def x(): pass',
'1, 2',
r'1\n'
])
def test_illegal_forward_references(Script, environment, reference):
if environment.version_info.major == 2:
pytest.skip()
source = 'def foo(bar: "%s"): bar' % reference
assert not Script(source).goto_definitions()
def test_lambda_forward_references(Script, environment):
if environment.version_info.major == 2:
pytest.skip()
source = 'def foo(bar: "lambda: 3"): bar'
# For now just receiving the 3 is ok. I'm doubting that this is what we
# want. We also execute functions. Should we only execute classes?
assert Script(source).goto_definitions()

View File

@@ -0,0 +1,91 @@
import os
from textwrap import dedent
from jedi._compatibility import force_unicode
from jedi.evaluate.sys_path import (_get_parent_dir_with_file,
_get_buildout_script_paths,
check_sys_path_modifications)
from ..helpers import cwd_at
def check_module_test(Script, code):
module_context = Script(code)._get_module()
return check_sys_path_modifications(module_context)
@cwd_at('test/examples/buildout_project/src/proj_name')
def test_parent_dir_with_file(Script):
parent = _get_parent_dir_with_file(
os.path.abspath(os.curdir), 'buildout.cfg')
assert parent is not None
assert parent.endswith(os.path.join('test', 'examples', 'buildout_project'))
@cwd_at('test/examples/buildout_project/src/proj_name')
def test_buildout_detection(Script):
scripts = list(_get_buildout_script_paths(os.path.abspath('./module_name.py')))
assert len(scripts) == 1
curdir = os.path.abspath(os.curdir)
appdir_path = os.path.normpath(os.path.join(curdir, '../../bin/app'))
assert scripts[0] == appdir_path
def test_append_on_non_sys_path(Script):
code = dedent("""
class Dummy(object):
path = []
d = Dummy()
d.path.append('foo')"""
)
paths = check_module_test(Script, code)
assert not paths
assert 'foo' not in paths
def test_path_from_invalid_sys_path_assignment(Script):
code = dedent("""
import sys
sys.path = 'invalid'"""
)
paths = check_module_test(Script, code)
assert not paths
assert 'invalid' not in paths
@cwd_at('test/examples/buildout_project/src/proj_name/')
def test_sys_path_with_modifications(Script):
code = dedent("""
import os
""")
path = os.path.abspath(os.path.join(os.curdir, 'module_name.py'))
paths = Script(code, path=path)._evaluator.get_sys_path()
assert '/tmp/.buildout/eggs/important_package.egg' in paths
def test_path_from_sys_path_assignment(Script):
code = dedent("""
#!/usr/bin/python
import sys
sys.path[0:0] = [
'/usr/lib/python3.4/site-packages',
'/home/test/.buildout/eggs/important_package.egg'
]
path[0:0] = [1]
import important_package
if __name__ == '__main__':
sys.exit(important_package.main())"""
)
paths = check_module_test(Script, code)
paths = list(map(force_unicode, paths))
assert 1 not in paths
assert '/home/test/.buildout/eggs/important_package.egg' in paths

View File

@@ -0,0 +1,171 @@
from textwrap import dedent
import math
import sys
from collections import Counter
from datetime import datetime
import pytest
from jedi.evaluate import compiled
from jedi.evaluate.compiled.access import DirectObjectAccess
from jedi.evaluate.gradual.conversion import _stub_to_python_context_set
def test_simple(evaluator, environment):
obj = compiled.create_simple_object(evaluator, u'_str_')
upper, = obj.py__getattribute__(u'upper')
objs = list(upper.execute_with_values())
assert len(objs) == 1
if environment.version_info.major == 2:
expected = 'unicode'
else:
expected = 'str'
assert objs[0].name.string_name == expected
def test_builtin_loading(evaluator):
string, = evaluator.builtins_module.py__getattribute__(u'str')
from_name, = string.py__getattribute__(u'__init__')
assert from_name.tree_node
assert not from_name.py__doc__() # It's a stub
def test_next_docstr(evaluator):
next_ = compiled.builtin_from_name(evaluator, u'next')
assert next_.tree_node is not None
assert next_.py__doc__() == '' # It's a stub
for non_stub in _stub_to_python_context_set(next_):
assert non_stub.py__doc__() == next.__doc__
def test_parse_function_doc_illegal_docstr():
docstr = """
test_func(o
doesn't have a closing bracket.
"""
assert ('', '') == compiled.context._parse_function_doc(docstr)
def test_doc(evaluator):
"""
Even CompiledObject docs always return empty docstrings - not None, that's
just a Jedi API definition.
"""
str_ = compiled.create_simple_object(evaluator, u'')
# Equals `''.__getnewargs__`
obj, = str_.py__getattribute__(u'__getnewargs__')
assert obj.py__doc__() == ''
def test_string_literals(Script, environment):
def typ(string):
d = Script("a = %s; a" % string).goto_definitions()[0]
return d.name
assert typ('""') == 'str'
assert typ('r""') == 'str'
if environment.version_info.major > 2:
assert typ('br""') == 'bytes'
assert typ('b""') == 'bytes'
assert typ('u""') == 'str'
else:
assert typ('b""') == 'str'
assert typ('u""') == 'unicode'
def test_method_completion(Script, environment):
code = dedent('''
class Foo:
def bar(self):
pass
foo = Foo()
foo.bar.__func__''')
assert [c.name for c in Script(code).completions()] == ['__func__']
def test_time_docstring(Script):
import time
comp, = Script('import time\ntime.sleep').completions()
assert comp.docstring(raw=True) == time.sleep.__doc__
expected = 'sleep(secs: float) -> None\n\n' + time.sleep.__doc__
assert comp.docstring() == expected
def test_dict_values(Script, environment):
if environment.version_info.major == 2:
# It looks like typeshed for Python 2 returns Any.
pytest.skip()
assert Script('import sys\nsys.modules["alshdb;lasdhf"]').goto_definitions()
def test_getitem_on_none(Script):
script = Script('None[1j]')
assert not script.goto_definitions()
issue, = script._evaluator.analysis
assert issue.name == 'type-error-not-subscriptable'
def _return_int():
return 1
@pytest.mark.parametrize(
'attribute, expected_name, expected_parent', [
('x', 'int', 'builtins'),
('y', 'int', 'builtins'),
('z', 'bool', 'builtins'),
('cos', 'cos', 'math'),
('dec', 'Decimal', 'decimal'),
('dt', 'datetime', 'datetime'),
('ret_int', '_return_int', 'test.test_inference.test_compiled'),
]
)
def test_parent_context(same_process_evaluator, attribute, expected_name, expected_parent):
import decimal
class C:
x = 1
y = int
z = True
cos = math.cos
dec = decimal.Decimal(1)
dt = datetime(2000, 1, 1)
ret_int = _return_int
o = compiled.CompiledObject(
same_process_evaluator,
DirectObjectAccess(same_process_evaluator, C)
)
x, = o.py__getattribute__(attribute)
assert x.py__name__() == expected_name
module_name = x.parent_context.py__name__()
if module_name == '__builtin__':
module_name = 'builtins' # Python 2
assert module_name == expected_parent
assert x.parent_context.parent_context is None
@pytest.mark.skipif(sys.version_info[0] == 2, reason="Ignore Python 2, because EOL")
@pytest.mark.parametrize(
'obj, expected_names', [
('', ['str']),
(str, ['str']),
(''.upper, ['str', 'upper']),
(str.upper, ['str', 'upper']),
(math.cos, ['cos']),
(Counter, ['Counter']),
(Counter(""), ['Counter']),
(Counter.most_common, ['Counter', 'most_common']),
(Counter("").most_common, ['Counter', 'most_common']),
]
)
def test_qualified_names(same_process_evaluator, obj, expected_names):
o = compiled.CompiledObject(
same_process_evaluator,
DirectObjectAccess(same_process_evaluator, obj)
)
assert o.get_qualified_names() == tuple(expected_names)

View File

@@ -0,0 +1,21 @@
from jedi._compatibility import force_unicode
def test_module_attributes(Script):
def_, = Script('__name__').completions()
assert def_.name == '__name__'
assert def_.line is None
assert def_.column is None
str_, = def_.infer()
assert str_.name == 'str'
def test_module__file__(Script, environment):
assert not Script('__file__').goto_definitions()
def_, = Script('__file__', path='example.py').goto_definitions()
value = force_unicode(def_._name._context.get_safe_value())
assert value.endswith('example.py')
def_, = Script('import antigravity; antigravity.__file__').goto_definitions()
value = force_unicode(def_._name._context.get_safe_value())
assert value.endswith('.py')

View File

@@ -0,0 +1,416 @@
"""
Testing of docstring related issues and especially ``jedi.docstrings``.
"""
from textwrap import dedent
import jedi
import pytest
from ..helpers import unittest
import sys
try:
import numpydoc # NOQA
except ImportError:
numpydoc_unavailable = True
else:
numpydoc_unavailable = False
try:
import numpy # NOQA
except ImportError:
numpy_unavailable = True
else:
numpy_unavailable = False
if sys.version_info.major == 2:
# In Python 2 there's an issue with tox/docutils that makes the tests fail,
# Python 2 is soon end-of-life, so just don't support numpydoc for it anymore.
numpydoc_unavailable = True
def test_function_doc(Script):
defs = Script("""
def func():
'''Docstring of `func`.'''
func""").goto_definitions()
assert defs[0].docstring() == 'func()\n\nDocstring of `func`.'
def test_class_doc(Script):
defs = Script("""
class TestClass():
'''Docstring of `TestClass`.'''
TestClass""").goto_definitions()
expected = 'Docstring of `TestClass`.'
assert defs[0].docstring(raw=True) == expected
assert defs[0].docstring() == 'TestClass()\n\n' + expected
def test_class_doc_with_init(Script):
d, = Script("""
class TestClass():
'''Docstring'''
def __init__(self, foo, bar=3): pass
TestClass""").goto_definitions()
assert d.docstring() == 'TestClass(foo, bar=3)\n\nDocstring'
def test_instance_doc(Script):
defs = Script("""
class TestClass():
'''Docstring of `TestClass`.'''
tc = TestClass()
tc""").goto_definitions()
assert defs[0].docstring() == 'Docstring of `TestClass`.'
@unittest.skip('need evaluator class for that')
def test_attribute_docstring(Script):
defs = Script("""
x = None
'''Docstring of `x`.'''
x""").goto_definitions()
assert defs[0].docstring() == 'Docstring of `x`.'
@unittest.skip('need evaluator class for that')
def test_multiple_docstrings(Script):
defs = Script("""
def func():
'''Original docstring.'''
x = func
'''Docstring of `x`.'''
x""").goto_definitions()
docs = [d.docstring() for d in defs]
assert docs == ['Original docstring.', 'Docstring of `x`.']
def test_completion(Script):
assert Script('''
class DocstringCompletion():
#? []
""" asdfas """''').completions()
def test_docstrings_type_dotted_import(Script):
s = """
def func(arg):
'''
:type arg: random.Random
'''
arg."""
names = [c.name for c in Script(s).completions()]
assert 'seed' in names
def test_docstrings_param_type(Script):
s = """
def func(arg):
'''
:param str arg: some description
'''
arg."""
names = [c.name for c in Script(s).completions()]
assert 'join' in names
def test_docstrings_type_str(Script):
s = """
def func(arg):
'''
:type arg: str
'''
arg."""
names = [c.name for c in Script(s).completions()]
assert 'join' in names
def test_docstring_instance(Script):
# The types hint that it's a certain kind
s = dedent("""
class A:
def __init__(self,a):
'''
:type a: threading.Thread
'''
if a is not None:
a.start()
self.a = a
def method_b(c):
'''
:type c: A
'''
c.""")
names = [c.name for c in Script(s).completions()]
assert 'a' in names
assert '__init__' in names
assert 'mro' not in names # Exists only for types.
def test_docstring_keyword(Script):
completions = Script('assert').completions()
assert 'assert' in completions[0].docstring()
def test_docstring_params_formatting(Script):
defs = Script("""
def func(param1,
param2,
param3):
pass
func""").goto_definitions()
assert defs[0].docstring() == 'func(param1, param2, param3)'
# ---- Numpy Style Tests ---
@pytest.mark.skipif(numpydoc_unavailable,
reason='numpydoc module is unavailable')
def test_numpydoc_parameters():
s = dedent('''
def foobar(x, y):
"""
Parameters
----------
x : int
y : str
"""
y.''')
names = [c.name for c in jedi.Script(s).completions()]
assert 'isupper' in names
assert 'capitalize' in names
@pytest.mark.skipif(numpydoc_unavailable,
reason='numpydoc module is unavailable')
def test_numpydoc_parameters_set_of_values():
s = dedent('''
def foobar(x, y):
"""
Parameters
----------
x : {'foo', 'bar', 100500}, optional
"""
x.''')
names = [c.name for c in jedi.Script(s).completions()]
assert 'isupper' in names
assert 'capitalize' in names
assert 'numerator' in names
@pytest.mark.skipif(numpydoc_unavailable,
reason='numpydoc module is unavailable')
def test_numpydoc_parameters_alternative_types():
s = dedent('''
def foobar(x, y):
"""
Parameters
----------
x : int or str or list
"""
x.''')
names = [c.name for c in jedi.Script(s).completions()]
assert 'isupper' in names
assert 'capitalize' in names
assert 'numerator' in names
assert 'append' in names
@pytest.mark.skipif(numpydoc_unavailable,
reason='numpydoc module is unavailable')
def test_numpydoc_invalid():
s = dedent('''
def foobar(x, y):
"""
Parameters
----------
x : int (str, py.path.local
"""
x.''')
assert not jedi.Script(s).completions()
@pytest.mark.skipif(numpydoc_unavailable,
reason='numpydoc module is unavailable')
def test_numpydoc_returns():
s = dedent('''
def foobar():
"""
Returns
----------
x : int
y : str
"""
return x
def bazbiz():
z = foobar()
z.''')
names = [c.name for c in jedi.Script(s).completions()]
assert 'isupper' in names
assert 'capitalize' in names
assert 'numerator' in names
@pytest.mark.skipif(numpydoc_unavailable,
reason='numpydoc module is unavailable')
def test_numpydoc_returns_set_of_values():
s = dedent('''
def foobar():
"""
Returns
----------
x : {'foo', 'bar', 100500}
"""
return x
def bazbiz():
z = foobar()
z.''')
names = [c.name for c in jedi.Script(s).completions()]
assert 'isupper' in names
assert 'capitalize' in names
assert 'numerator' in names
@pytest.mark.skipif(numpydoc_unavailable,
reason='numpydoc module is unavailable')
def test_numpydoc_returns_alternative_types():
s = dedent('''
def foobar():
"""
Returns
----------
int or list of str
"""
return x
def bazbiz():
z = foobar()
z.''')
names = [c.name for c in jedi.Script(s).completions()]
assert 'isupper' not in names
assert 'capitalize' not in names
assert 'numerator' in names
assert 'append' in names
@pytest.mark.skipif(numpydoc_unavailable,
reason='numpydoc module is unavailable')
def test_numpydoc_returns_list_of():
s = dedent('''
def foobar():
"""
Returns
----------
list of str
"""
return x
def bazbiz():
z = foobar()
z.''')
names = [c.name for c in jedi.Script(s).completions()]
assert 'append' in names
assert 'isupper' not in names
assert 'capitalize' not in names
@pytest.mark.skipif(numpydoc_unavailable,
reason='numpydoc module is unavailable')
def test_numpydoc_returns_obj():
s = dedent('''
def foobar(x, y):
"""
Returns
----------
int or random.Random
"""
return x + y
def bazbiz():
z = foobar(x, y)
z.''')
script = jedi.Script(s)
names = [c.name for c in script.completions()]
assert 'numerator' in names
assert 'seed' in names
@pytest.mark.skipif(numpydoc_unavailable,
reason='numpydoc module is unavailable')
def test_numpydoc_yields():
s = dedent('''
def foobar():
"""
Yields
----------
x : int
y : str
"""
return x
def bazbiz():
z = foobar():
z.''')
names = [c.name for c in jedi.Script(s).completions()]
assert 'isupper' in names
assert 'capitalize' in names
assert 'numerator' in names
@pytest.mark.skipif(numpydoc_unavailable or numpy_unavailable,
reason='numpydoc or numpy module is unavailable')
def test_numpy_returns():
s = dedent('''
import numpy
x = numpy.asarray([])
x.d'''
)
names = [c.name for c in jedi.Script(s).completions()]
assert 'diagonal' in names
@pytest.mark.skipif(numpydoc_unavailable or numpy_unavailable,
reason='numpydoc or numpy module is unavailable')
def test_numpy_comp_returns():
s = dedent('''
import numpy
x = numpy.array([])
x.d'''
)
names = [c.name for c in jedi.Script(s).completions()]
assert 'diagonal' in names
def test_decorator(Script):
code = dedent('''
def decorator(name=None):
def _decorate(func):
@wraps(func)
def wrapper(*args, **kwargs):
"""wrapper docstring"""
return func(*args, **kwargs)
return wrapper
return _decorate
@decorator('testing')
def check_user(f):
"""Nice docstring"""
pass
check_user''')
d, = Script(code).goto_definitions()
assert d.docstring(raw=True) == 'Nice docstring'

View File

@@ -0,0 +1,57 @@
"""
Test compiled module
"""
import os
import jedi
from ..helpers import cwd_at
import pytest
def test_completions(Script):
s = Script('import _ctypes; _ctypes.')
assert len(s.completions()) >= 15
def test_call_signatures_extension(Script):
if os.name == 'nt':
func = 'LoadLibrary'
params = 1
else:
func = 'dlopen'
params = 2
s = Script('import _ctypes; _ctypes.%s(' % (func,))
sigs = s.call_signatures()
assert len(sigs) == 1
assert len(sigs[0].params) == params
def test_call_signatures_stdlib(Script):
s = Script('import math; math.cos(')
sigs = s.call_signatures()
assert len(sigs) == 1
assert len(sigs[0].params) == 1
# Check only on linux 64 bit platform and Python3.4.
@pytest.mark.skipif('sys.platform != "linux" or sys.maxsize <= 2**32 or sys.version_info[:2] != (3, 4)')
@cwd_at('test/test_inference')
def test_init_extension_module(Script):
"""
``__init__`` extension modules are also packages and Jedi should understand
that.
Originally coming from #472.
This test was built by the module.c and setup.py combination you can find
in the init_extension_module folder. You can easily build the
`__init__.cpython-34m.so` by compiling it (create a virtualenv and run
`setup.py install`.
This is also why this test only runs on certain systems (and Python 3.4).
"""
s = jedi.Script('import init_extension_module as i\ni.', path='not_existing.py')
assert 'foo' in [c.name for c in s.completions()]
s = jedi.Script('from init_extension_module import foo\nfoo', path='not_existing.py')
assert ['foo'] == [c.name for c in s.completions()]

View File

@@ -0,0 +1,19 @@
import pytest
from textwrap import dedent
@pytest.fixture(autouse=True)
def skip_not_supported(environment):
if environment.version_info < (3, 6):
pytest.skip()
def test_fstring_multiline(Script):
code = dedent("""\
'' f'''s{
str.uppe
'''
"""
)
c, = Script(code, line=2, column=9).completions()
assert c.name == 'upper'

View File

@@ -0,0 +1,27 @@
from functools import partial
from test.helpers import get_example_dir
from jedi.api.project import Project
import pytest
@pytest.fixture
def ScriptInStubFolder(Script):
path = get_example_dir('stub_packages')
project = Project(path, sys_path=[path], smart_sys_path=False)
return partial(Script, _project=project)
@pytest.mark.parametrize(
('code', 'expected'), [
('from no_python import foo', ['int']),
('from with_python import stub_only', ['str']),
('from with_python import python_only', ['int']),
('from with_python import both', ['int']),
('from with_python import something_random', []),
('from with_python.module import in_sub_module', ['int']),
]
)
def test_find_stubs_infer(ScriptInStubFolder, code, expected):
defs = ScriptInStubFolder(code).goto_definitions()
assert [d.name for d in defs] == expected

View File

@@ -0,0 +1,94 @@
import os
import pytest
from jedi.api.project import Project
from test.helpers import root_dir
@pytest.mark.parametrize('type_', ['goto', 'infer'])
@pytest.mark.parametrize('way', ['direct', 'indirect'])
@pytest.mark.parametrize(
'kwargs', [
dict(only_stubs=False, prefer_stubs=False),
dict(only_stubs=False, prefer_stubs=True),
dict(only_stubs=True, prefer_stubs=False),
]
)
@pytest.mark.parametrize(
('code', 'full_name', 'has_stub', 'has_python', 'goto_changes'), [
['import os; os.walk', 'os.walk', True, True, {}],
['from collections import Counter', 'collections.Counter', True, True, {}],
['from collections', 'collections', True, True, {}],
['from collections import Counter; Counter', 'collections.Counter', True, True, {}],
['from collections import Counter; Counter()', 'collections.Counter', True, True, {}],
['from collections import Counter; Counter.most_common',
'collections.Counter.most_common', True, True, {}],
['from collections import deque', 'collections.deque', True, False, {'has_python': True}],
['from keyword import kwlist; kwlist', 'typing.Sequence', True, True,
{'full_name': 'keyword.kwlist'}],
['from keyword import kwlist', 'typing.Sequence', True, True,
{'full_name': 'keyword.kwlist'}],
['from socket import AF_INET', 'socket.AddressFamily', True, False,
{'full_name': 'socket.AF_INET'}],
['from socket import socket', 'socket.socket', True, True, {}],
['import with_stub', 'with_stub', True, True, {}],
['import with_stub', 'with_stub', True, True, {}],
['import with_stub_folder.python_only', 'with_stub_folder.python_only', False, True, {}],
['import stub_only', 'stub_only', True, False, {}],
])
def test_infer_and_goto(Script, code, full_name, has_stub, has_python, way,
kwargs, type_, goto_changes, environment):
if environment.version_info < (3, 5):
# We just don't care about much of the detailed Python 2 failures
# anymore, because its end-of-life soon. (same for 3.4)
pytest.skip()
if type_ == 'infer' and full_name == 'typing.Sequence' and environment.version_info >= (3, 7):
# In Python 3.7+ there's not really a sequence definition, there's just
# a name that leads nowhere.
has_python = False
project = Project(os.path.join(root_dir, 'test', 'completion', 'stub_folder'))
s = Script(code, _project=project)
prefer_stubs = kwargs['prefer_stubs']
only_stubs = kwargs['only_stubs']
if type_ == 'goto':
full_name = goto_changes.get('full_name', full_name)
has_python = goto_changes.get('has_python', has_python)
if way == 'direct':
if type_ == 'goto':
defs = s.goto_assignments(follow_imports=True, **kwargs)
else:
defs = s.goto_definitions(**kwargs)
else:
goto_defs = s.goto_assignments(
# Prefering stubs when we want to go to python and vice versa
prefer_stubs=not (prefer_stubs or only_stubs),
follow_imports=True,
)
if type_ == 'goto':
defs = [d for goto_def in goto_defs for d in goto_def.goto_assignments(**kwargs)]
else:
defs = [d for goto_def in goto_defs for d in goto_def.infer(**kwargs)]
if not has_stub and only_stubs:
assert not defs
else:
assert defs
for d in defs:
if prefer_stubs and has_stub:
assert d.is_stub()
elif only_stubs:
assert d.is_stub()
else:
assert has_python == (not d.is_stub())
assert d.full_name == full_name
assert d.is_stub() == d.module_path.endswith('.pyi')

View File

@@ -0,0 +1,236 @@
import os
import pytest
from parso.utils import PythonVersionInfo
from jedi.evaluate.gradual import typeshed, stub_context
from jedi.evaluate.context import TreeInstance, BoundMethod, FunctionContext, \
MethodContext, ClassContext
TYPESHED_PYTHON3 = os.path.join(typeshed.TYPESHED_PATH, 'stdlib', '3')
def test_get_typeshed_directories():
def get_dirs(version_info):
return {
d.replace(typeshed.TYPESHED_PATH, '').lstrip(os.path.sep)
for d in typeshed._get_typeshed_directories(version_info)
}
def transform(set_):
return {x.replace('/', os.path.sep) for x in set_}
dirs = get_dirs(PythonVersionInfo(2, 7))
assert dirs == transform({'stdlib/2and3', 'stdlib/2', 'third_party/2and3', 'third_party/2'})
dirs = get_dirs(PythonVersionInfo(3, 4))
assert dirs == transform({'stdlib/2and3', 'stdlib/3', 'third_party/2and3', 'third_party/3'})
dirs = get_dirs(PythonVersionInfo(3, 5))
assert dirs == transform({'stdlib/2and3', 'stdlib/3', 'stdlib/3.5',
'third_party/2and3', 'third_party/3', 'third_party/3.5'})
dirs = get_dirs(PythonVersionInfo(3, 6))
assert dirs == transform({'stdlib/2and3', 'stdlib/3', 'stdlib/3.5',
'stdlib/3.6', 'third_party/2and3',
'third_party/3', 'third_party/3.5', 'third_party/3.6'})
def test_get_stub_files():
def get_map(version_info):
return typeshed._create_stub_map(version_info)
map_ = typeshed._create_stub_map(TYPESHED_PYTHON3)
assert map_['functools'] == os.path.join(TYPESHED_PYTHON3, 'functools.pyi')
def test_function(Script, environment):
code = 'import threading; threading.current_thread'
def_, = Script(code).goto_definitions()
context = def_._name._context
assert isinstance(context, FunctionContext), context
def_, = Script(code + '()').goto_definitions()
context = def_._name._context
assert isinstance(context, TreeInstance)
def_, = Script('import threading; threading.Thread').goto_definitions()
assert isinstance(def_._name._context, ClassContext), def_
def test_keywords_variable(Script):
code = 'import keyword; keyword.kwlist'
for seq in Script(code).goto_definitions():
assert seq.name == 'Sequence'
# This points towards the typeshed implementation
stub_seq, = seq.goto_assignments(only_stubs=True)
assert typeshed.TYPESHED_PATH in stub_seq.module_path
def test_class(Script):
def_, = Script('import threading; threading.Thread').goto_definitions()
context = def_._name._context
assert isinstance(context, ClassContext), context
def test_instance(Script):
def_, = Script('import threading; threading.Thread()').goto_definitions()
context = def_._name._context
assert isinstance(context, TreeInstance)
def test_class_function(Script):
def_, = Script('import threading; threading.Thread.getName').goto_definitions()
context = def_._name._context
assert isinstance(context, MethodContext), context
def test_method(Script):
code = 'import threading; threading.Thread().getName'
def_, = Script(code).goto_definitions()
context = def_._name._context
assert isinstance(context, BoundMethod), context
assert isinstance(context._wrapped_context, MethodContext), context
def_, = Script(code + '()').goto_definitions()
context = def_._name._context
assert isinstance(context, TreeInstance)
assert context.class_context.py__name__() == 'str'
def test_sys_exc_info(Script):
code = 'import sys; sys.exc_info()'
none, def_ = Script(code + '[1]').goto_definitions()
# It's an optional.
assert def_.name == 'BaseException'
assert def_.type == 'instance'
assert none.name == 'NoneType'
none, def_ = Script(code + '[0]').goto_definitions()
assert def_.name == 'BaseException'
assert def_.type == 'class'
def test_sys_getwindowsversion(Script, environment):
# This should only exist on Windows, but type inference should happen
# everywhere.
definitions = Script('import sys; sys.getwindowsversion().major').goto_definitions()
if environment.version_info.major == 2:
assert not definitions
else:
def_, = definitions
assert def_.name == 'int'
def test_sys_hexversion(Script):
script = Script('import sys; sys.hexversion')
def_, = script.completions()
assert isinstance(def_._name, stub_context._StubName), def_._name
assert typeshed.TYPESHED_PATH in def_.module_path
def_, = script.goto_definitions()
assert def_.name == 'int'
def test_math(Script):
def_, = Script('import math; math.acos()').goto_definitions()
assert def_.name == 'float'
context = def_._name._context
assert context
def test_type_var(Script):
def_, = Script('import typing; T = typing.TypeVar("T1")').goto_definitions()
assert def_.name == 'TypeVar'
assert def_.description == 'TypeVar = object()'
@pytest.mark.parametrize(
'code, full_name', (
('import math', 'math'),
('from math import cos', 'math.cos')
)
)
def test_math_is_stub(Script, code, full_name):
s = Script(code)
cos, = s.goto_definitions()
wanted = os.path.join('typeshed', 'stdlib', '2and3', 'math.pyi')
assert cos.module_path.endswith(wanted)
assert cos.is_stub() is True
assert cos.goto_assignments(only_stubs=True) == [cos]
assert cos.full_name == full_name
cos, = s.goto_assignments()
assert cos.module_path.endswith(wanted)
assert cos.goto_assignments(only_stubs=True) == [cos]
assert cos.is_stub() is True
assert cos.full_name == full_name
def test_goto_stubs(Script):
s = Script('import os; os')
os_module, = s.goto_definitions()
assert os_module.full_name == 'os'
assert os_module.is_stub() is False
stub, = os_module.goto_assignments(only_stubs=True)
assert stub.is_stub() is True
os_module, = s.goto_assignments()
def _assert_is_same(d1, d2):
assert d1.name == d2.name
assert d1.module_path == d2.module_path
assert d1.line == d2.line
assert d1.column == d2.column
@pytest.mark.parametrize('type_', ['goto', 'infer'])
@pytest.mark.parametrize(
'code', [
'import os; os.walk',
'from collections import Counter; Counter',
'from collections import Counter; Counter()',
'from collections import Counter; Counter.most_common',
])
def test_goto_stubs_on_itself(Script, code, type_):
"""
If goto_stubs is used on an identifier in e.g. the stdlib, we should goto
the stub of it.
"""
s = Script(code)
if type_ == 'infer':
def_, = s.goto_definitions()
else:
def_, = s.goto_assignments(follow_imports=True)
stub, = def_.goto_assignments(only_stubs=True)
script_on_source = Script(
path=def_.module_path,
line=def_.line,
column=def_.column
)
if type_ == 'infer':
definition, = script_on_source.goto_definitions()
else:
definition, = script_on_source.goto_assignments()
same_stub, = definition.goto_assignments(only_stubs=True)
_assert_is_same(same_stub, stub)
_assert_is_same(definition, def_)
assert same_stub.module_path != def_.module_path
# And the reverse.
script_on_stub = Script(
path=same_stub.module_path,
line=same_stub.line,
column=same_stub.column
)
if type_ == 'infer':
same_definition, = script_on_stub.goto_definitions()
same_definition2, = same_stub.infer()
else:
same_definition, = script_on_stub.goto_assignments()
same_definition2, = same_stub.goto_assignments()
_assert_is_same(same_definition, definition)
_assert_is_same(same_definition, same_definition2)

View File

@@ -0,0 +1,16 @@
from textwrap import dedent
from jedi import names
from jedi.evaluate import helpers
def test_call_of_leaf_in_brackets(environment):
s = dedent("""
x = 1
type(x)
""")
last_x = names(s, references=True, definitions=False, environment=environment)[-1]
name = last_x._name.tree_name
call = helpers.call_of_leaf(name)
assert call == name

View File

@@ -0,0 +1,105 @@
from os.path import dirname, join
import pytest
@pytest.fixture(autouse=True)
def skip_not_supported_versions(environment):
if environment.version_info < (3, 4):
pytest.skip()
def test_implicit_namespace_package(Script):
sys_path = [join(dirname(__file__), d)
for d in ['implicit_namespace_package/ns1', 'implicit_namespace_package/ns2']]
def script_with_path(*args, **kwargs):
return Script(sys_path=sys_path, *args, **kwargs)
# 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()
# goto assignment
tests = {
'from pkg.ns2_file import foo': 'ns2_file!',
'from pkg.ns1_file import foo': 'ns1_file!',
}
for source, solution in tests.items():
ass = script_with_path(source).goto_assignments()
assert len(ass) == 1
assert ass[0].description == "foo = '%s'" % solution
# completion
completions = script_with_path('from pkg import ').completions()
names = [c.name for c in completions]
compare = ['ns1_file', 'ns2_file']
# must at least contain these items, other items are not important
assert set(compare) == set(names)
tests = {
'from pkg import ns2_file as x': 'ns2_file!',
'from pkg import ns1_file as x': 'ns1_file!'
}
for source, solution in tests.items():
for c in script_with_path(source + '; x.').completions():
if c.name == 'foo':
completion = c
solution = "foo = '%s'" % solution
assert completion.description == solution
def test_implicit_nested_namespace_package(Script):
code = 'from implicit_nested_namespaces.namespace.pkg.module import CONST'
sys_path = [dirname(__file__)]
script = Script(sys_path=sys_path, source=code, line=1, column=61)
result = script.goto_definitions()
assert len(result) == 1
implicit_pkg, = Script(code, column=10, sys_path=sys_path).goto_definitions()
assert implicit_pkg.type == 'module'
assert implicit_pkg.module_path is None
def test_implicit_namespace_package_import_autocomplete(Script):
CODE = 'from implicit_name'
sys_path = [dirname(__file__)]
script = Script(sys_path=sys_path, source=CODE)
compl = script.completions()
assert [c.name for c in compl] == ['implicit_namespace_package']
def test_namespace_package_in_multiple_directories_autocompletion(Script):
CODE = 'from pkg.'
sys_path = [join(dirname(__file__), d)
for d in ['implicit_namespace_package/ns1', 'implicit_namespace_package/ns2']]
script = Script(sys_path=sys_path, source=CODE)
compl = script.completions()
assert set(c.name for c in compl) == set(['ns1_file', 'ns2_file'])
def test_namespace_package_in_multiple_directories_goto_definition(Script):
CODE = 'from pkg import ns1_file'
sys_path = [join(dirname(__file__), d)
for d in ['implicit_namespace_package/ns1', 'implicit_namespace_package/ns2']]
script = Script(sys_path=sys_path, source=CODE)
result = script.goto_definitions()
assert len(result) == 1
def test_namespace_name_autocompletion_full_name(Script):
CODE = 'from pk'
sys_path = [join(dirname(__file__), d)
for d in ['implicit_namespace_package/ns1', 'implicit_namespace_package/ns2']]
script = Script(sys_path=sys_path, source=CODE)
compl = script.completions()
assert set(c.full_name for c in compl) == set(['pkg'])

View File

@@ -0,0 +1,477 @@
"""
Tests of various import related things that could not be tested with "Black Box
Tests".
"""
import os
import pytest
from jedi.file_io import FileIO, KnownContentFileIO
from jedi._compatibility import find_module_py33, find_module
from jedi.evaluate import compiled
from jedi.evaluate import imports
from jedi.api.project import Project
from jedi.evaluate.gradual.conversion import _stub_to_python_context_set
from ..helpers import cwd_at, get_example_dir, test_dir, root_dir
THIS_DIR = os.path.dirname(__file__)
@pytest.mark.skipif('sys.version_info < (3,3)')
def test_find_module_py33():
"""Needs to work like the old find_module."""
assert find_module_py33('_io') == (None, False)
with pytest.raises(ImportError):
assert find_module_py33('_DOESNTEXIST_') == (None, None)
def test_find_module_package():
file_io, is_package = find_module('json')
assert file_io.path.endswith(os.path.join('json', '__init__.py'))
assert is_package is True
def test_find_module_not_package():
file_io, is_package = find_module('io')
assert file_io.path.endswith('io.py')
assert is_package is False
pkg_zip_path = os.path.join(os.path.dirname(__file__),
'zipped_imports',
'pkg.zip')
def test_find_module_package_zipped(Script, evaluator, environment):
sys_path = environment.get_sys_path() + [pkg_zip_path]
script = Script('import pkg; pkg.mod', sys_path=sys_path)
assert len(script.completions()) == 1
file_io, is_package = evaluator.compiled_subprocess.get_module_info(
sys_path=sys_path,
string=u'pkg',
full_name=u'pkg'
)
assert file_io is not None
assert file_io.path.endswith(os.path.join('pkg.zip', 'pkg', '__init__.py'))
assert file_io._zip_path.endswith('pkg.zip')
assert is_package is True
@pytest.mark.parametrize(
'code, file, package, path', [
('import pkg', '__init__.py', 'pkg', 'pkg'),
('import pkg', '__init__.py', 'pkg', 'pkg'),
('from pkg import module', 'module.py', 'pkg', None),
('from pkg.module', 'module.py', 'pkg', None),
('from pkg import nested', os.path.join('nested', '__init__.py'),
'pkg.nested', os.path.join('pkg', 'nested')),
('from pkg.nested', os.path.join('nested', '__init__.py'),
'pkg.nested', os.path.join('pkg', 'nested')),
('from pkg.nested import nested_module',
os.path.join('nested', 'nested_module.py'), 'pkg.nested', None),
('from pkg.nested.nested_module',
os.path.join('nested', 'nested_module.py'), 'pkg.nested', None),
('from pkg.namespace import namespace_module',
os.path.join('namespace', 'namespace_module.py'), 'pkg.namespace', None),
('from pkg.namespace.namespace_module',
os.path.join('namespace', 'namespace_module.py'), 'pkg.namespace', None),
]
)
def test_correct_zip_package_behavior(Script, evaluator, environment, code,
file, package, path, skip_python2):
sys_path = environment.get_sys_path() + [pkg_zip_path]
pkg, = Script(code, sys_path=sys_path).goto_definitions()
context, = pkg._name.infer()
assert context.py__file__() == os.path.join(pkg_zip_path, 'pkg', file)
assert '.'.join(context.py__package__()) == package
assert context.is_package is (path is not None)
if path is not None:
assert context.py__path__() == [os.path.join(pkg_zip_path, path)]
def test_find_module_not_package_zipped(Script, evaluator, environment):
path = os.path.join(os.path.dirname(__file__), 'zipped_imports/not_pkg.zip')
sys_path = environment.get_sys_path() + [path]
script = Script('import not_pkg; not_pkg.val', sys_path=sys_path)
assert len(script.completions()) == 1
file_io, is_package = evaluator.compiled_subprocess.get_module_info(
sys_path=sys_path,
string=u'not_pkg',
full_name=u'not_pkg'
)
assert file_io.path.endswith(os.path.join('not_pkg.zip', 'not_pkg.py'))
assert is_package is False
@cwd_at('test/test_inference/not_in_sys_path/pkg')
def test_import_not_in_sys_path(Script):
"""
non-direct imports (not in sys.path)
"""
a = Script(path='module.py', line=5).goto_definitions()
assert a[0].name == 'int'
a = Script(path='module.py', line=6).goto_definitions()
assert a[0].name == 'str'
a = Script(path='module.py', line=7).goto_definitions()
assert a[0].name == 'str'
@pytest.mark.parametrize("code,name", [
("from flask.ext import foo; foo.", "Foo"), # flask_foo.py
("from flask.ext import bar; bar.", "Bar"), # flaskext/bar.py
("from flask.ext import baz; baz.", "Baz"), # flask_baz/__init__.py
("from flask.ext import moo; moo.", "Moo"), # flaskext/moo/__init__.py
("from flask.ext.", "foo"),
("from flask.ext.", "bar"),
("from flask.ext.", "baz"),
("from flask.ext.", "moo"),
pytest.param("import flask.ext.foo; flask.ext.foo.", "Foo", marks=pytest.mark.xfail),
pytest.param("import flask.ext.bar; flask.ext.bar.", "Foo", marks=pytest.mark.xfail),
pytest.param("import flask.ext.baz; flask.ext.baz.", "Foo", marks=pytest.mark.xfail),
pytest.param("import flask.ext.moo; flask.ext.moo.", "Foo", marks=pytest.mark.xfail),
])
def test_flask_ext(Script, code, name):
"""flask.ext.foo is really imported from flaskext.foo or flask_foo.
"""
path = os.path.join(os.path.dirname(__file__), 'flask-site-packages')
completions = Script(code, sys_path=[path]).completions()
assert name in [c.name for c in completions]
@cwd_at('test/test_inference/')
def test_not_importable_file(Script):
src = 'import not_importable_file as x; x.'
assert not Script(src, path='example.py').completions()
def test_import_unique(Script):
src = "import os; os.path"
defs = Script(src, path='example.py').goto_definitions()
parent_contexts = [d._name._context for d in defs]
assert len(parent_contexts) == len(set(parent_contexts))
def test_cache_works_with_sys_path_param(Script, 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 = Script('import module; module.',
sys_path=[foo_path.strpath]).completions()
bar_completions = 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]
def test_import_completion_docstring(Script):
import abc
s = Script('"""test"""\nimport ab')
abc_completions = [c for c in s.completions() if c.name == 'abc']
assert len(abc_completions) == 1
assert abc_completions[0].docstring(fast=False) == abc.__doc__
# However for performance reasons not all modules are loaded and the
# docstring is empty in this case.
assert abc_completions[0].docstring() == ''
def test_goto_definition_on_import(Script):
assert Script("import sys_blabla", 1, 8).goto_definitions() == []
assert len(Script("import sys", 1, 8).goto_definitions()) == 1
@cwd_at('jedi')
def test_complete_on_empty_import(Script):
assert Script("from datetime import").completions()[0].name == 'import'
# should just list the files in the directory
assert 10 < len(Script("from .", path='whatever.py').completions()) < 30
# Global import
assert len(Script("from . import", 1, 5, 'whatever.py').completions()) > 30
# relative import
assert 10 < len(Script("from . import", 1, 6, 'whatever.py').completions()) < 30
# Global import
assert len(Script("from . import classes", 1, 5, 'whatever.py').completions()) > 30
# relative import
assert 10 < len(Script("from . import classes", 1, 6, 'whatever.py').completions()) < 30
wanted = {'ImportError', 'import', 'ImportWarning'}
assert {c.name for c in Script("import").completions()} == wanted
assert len(Script("import import", path='').completions()) > 0
# 111
assert Script("from datetime import").completions()[0].name == 'import'
assert Script("from datetime import ").completions()
def test_imports_on_global_namespace_without_path(Script):
"""If the path is None, there shouldn't be any import problem"""
completions = Script("import operator").completions()
assert [c.name for c in completions] == ['operator']
completions = Script("import operator", path='example.py').completions()
assert [c.name for c in completions] == ['operator']
# the first one has a path the second doesn't
completions = Script("import keyword", path='example.py').completions()
assert [c.name for c in completions] == ['keyword']
completions = Script("import keyword").completions()
assert [c.name for c in completions] == ['keyword']
def test_named_import(Script):
"""named import - jedi-vim issue #8"""
s = "import time as dt"
assert len(Script(s, 1, 15, '/').goto_definitions()) == 1
assert len(Script(s, 1, 10, '/').goto_definitions()) == 1
@pytest.mark.skipif('True', reason='The nested import stuff is still very messy.')
def test_goto_following_on_imports(Script):
s = "import multiprocessing.dummy; multiprocessing.dummy"
g = Script(s).goto_assignments()
assert len(g) == 1
assert (g[0].line, g[0].column) != (0, 0)
def test_goto_assignments(Script):
sys, = Script("import sys", 1, 10).goto_assignments(follow_imports=True)
assert sys.type == 'module'
def test_os_after_from(Script):
def check(source, result, column=None):
completions = Script(source, column=column).completions()
assert [c.name for c in completions] == result
check('\nfrom os. ', ['path'])
check('\nfrom os ', ['import'])
check('from os ', ['import'])
check('\nfrom os import whatever', ['import'], len('from os im'))
check('from os\\\n', ['import'])
check('from os \\\n', ['import'])
def test_os_issues(Script):
def import_names(*args, **kwargs):
return [d.name for d in Script(*args, **kwargs).completions()]
# Github issue #759
s = 'import os, s'
assert 'sys' in import_names(s)
assert 'path' not in import_names(s, column=len(s) - 1)
assert 'os' in import_names(s, column=len(s) - 3)
# Some more checks
s = 'from os import path, e'
assert 'environ' in import_names(s)
assert 'json' not in import_names(s, column=len(s) - 1)
assert 'environ' in import_names(s, column=len(s) - 1)
assert 'path' in import_names(s, column=len(s) - 3)
def test_path_issues(Script):
"""
See pull request #684 for details.
"""
source = '''from datetime import '''
assert Script(source).completions()
def test_compiled_import_none(monkeypatch, Script):
"""
Related to #1079. An import might somehow fail and return None.
"""
script = Script('import sys')
monkeypatch.setattr(compiled, 'load_module', lambda *args, **kwargs: None)
def_, = script.goto_definitions()
assert def_.type == 'module'
context, = def_._name.infer()
assert not _stub_to_python_context_set(context)
@pytest.mark.parametrize(
('path', 'is_package', 'goal'), [
(os.path.join(THIS_DIR, 'test_docstring.py'), False, ('ok', 'lala', 'test_imports')),
(os.path.join(THIS_DIR, '__init__.py'), True, ('ok', 'lala', 'x', 'test_imports')),
]
)
def test_get_modules_containing_name(evaluator, path, goal, is_package):
module = imports._load_python_module(
evaluator,
FileIO(path),
import_names=('ok', 'lala', 'x'),
is_package=is_package,
)
assert module
input_module, found_module = imports.get_modules_containing_name(
evaluator,
[module],
'string_that_only_exists_here'
)
assert input_module is module
assert found_module.string_names == goal
@pytest.mark.parametrize(
('path', 'base_names', 'is_package', 'names'), [
('/foo/bar.py', ('foo',), False, ('foo', 'bar')),
('/foo/bar.py', ('foo', 'baz'), False, ('foo', 'baz', 'bar')),
('/foo/__init__.py', ('foo',), True, ('foo',)),
('/__init__.py', ('foo',), True, ('foo',)),
('/foo/bar/__init__.py', ('foo',), True, ('foo',)),
('/foo/bar/__init__.py', ('foo', 'bar'), True, ('foo', 'bar')),
]
)
def test_load_module_from_path(evaluator, path, base_names, is_package, names):
file_io = KnownContentFileIO(path, '')
m = imports._load_module_from_path(evaluator, file_io, base_names)
assert m.is_package == is_package
assert m.string_names == names
@pytest.mark.parametrize(
'path', ('api/whatever/test_this.py', 'api/whatever/file'))
@pytest.mark.parametrize('empty_sys_path', (False, True))
def test_relative_imports_with_multiple_similar_directories(Script, path, empty_sys_path):
dir = get_example_dir('issue1209')
if empty_sys_path:
project = Project(dir, sys_path=(), smart_sys_path=False)
else:
project = Project(dir)
script = Script(
"from . ",
path=os.path.join(dir, path),
_project=project,
)
name, import_ = script.completions()
assert import_.name == 'import'
assert name.name == 'api_test1'
def test_relative_imports_with_outside_paths(Script):
dir = get_example_dir('issue1209')
project = Project(dir, sys_path=[], smart_sys_path=False)
script = Script(
"from ...",
path=os.path.join(dir, 'api/whatever/test_this.py'),
_project=project,
)
assert [c.name for c in script.completions()] == ['api', 'import', 'whatever']
script = Script(
"from " + '.' * 100,
path=os.path.join(dir, 'api/whatever/test_this.py'),
_project=project,
)
assert [c.name for c in script.completions()] == ['import']
@cwd_at('test/examples/issue1209/api/whatever/')
def test_relative_imports_without_path(Script):
project = Project('.', sys_path=[], smart_sys_path=False)
script = Script("from . ", _project=project)
assert [c.name for c in script.completions()] == ['api_test1', 'import']
script = Script("from .. ", _project=project)
assert [c.name for c in script.completions()] == ['import', 'whatever']
script = Script("from ... ", _project=project)
assert [c.name for c in script.completions()] == ['api', 'import', 'whatever']
def test_relative_import_out_of_file_system(Script):
script = Script("from " + '.' * 100)
import_, = script.completions()
assert import_.name == 'import'
script = Script("from " + '.' * 100 + 'abc import ABCMeta')
assert not script.goto_definitions()
assert not script.completions()
@pytest.mark.parametrize(
'level, directory, project_path, result', [
(1, '/a/b/c', '/a', (['b', 'c'], '/a')),
(2, '/a/b/c', '/a', (['b'], '/a')),
(3, '/a/b/c', '/a', ([], '/a')),
(4, '/a/b/c', '/a', (None, '/')),
(5, '/a/b/c', '/a', (None, None)),
(1, '/', '/', ([], '/')),
(2, '/', '/', (None, None)),
(1, '/a/b', '/a/b/c', (None, '/a/b')),
(2, '/a/b', '/a/b/c', (None, '/a')),
(3, '/a/b', '/a/b/c', (None, '/')),
]
)
def test_level_to_import_path(level, directory, project_path, result):
assert imports._level_to_base_import_path(project_path, directory, level) == result
def test_import_name_calculation(Script):
s = Script(path=os.path.join(test_dir, 'completion', 'isinstance.py'))
m = s._get_module()
assert m.string_names == ('test', 'completion', 'isinstance')
@pytest.mark.parametrize('name', ('builtins', 'typing'))
def test_pre_defined_imports_module(Script, environment, name):
if environment.version_info.major < 3 and name == 'builtins':
name = '__builtin__'
path = os.path.join(root_dir, name + '.py')
module = Script('', path=path)._get_module()
assert module.string_names == (name,)
assert module.evaluator.builtins_module.py__file__() != path
assert module.evaluator.typing_module.py__file__() != path
@pytest.mark.parametrize('name', ('builtins', 'typing'))
def test_import_needed_modules_by_jedi(Script, environment, tmpdir, name):
if environment.version_info.major < 3 and name == 'builtins':
name = '__builtin__'
module_path = tmpdir.join(name + '.py')
module_path.write('int = ...')
script = Script(
'import ' + name,
path=tmpdir.join('something.py').strpath,
sys_path=[tmpdir.strpath] + environment.get_sys_path(),
)
module, = script.goto_definitions()
assert module._evaluator.builtins_module.py__file__() != module_path
assert module._evaluator.typing_module.py__file__() != module_path
def test_import_with_semicolon(Script):
names = [c.name for c in Script('xzy; from abc import ').completions()]
assert 'ABCMeta' in names
assert 'abc' not in names
def test_relative_import_star(Script):
# Coming from github #1235
import jedi
source = """
from . import *
furl.c
"""
script = jedi.Script(source, 3, len("furl.c"), 'export.py')
assert script.completions()

View File

@@ -0,0 +1,46 @@
import pytest
from jedi.evaluate.context import TreeInstance
def _eval_literal(Script, code, is_fstring=False):
def_, = Script(code).goto_definitions()
if is_fstring:
assert def_.name == 'str'
assert isinstance(def_._name._context, TreeInstance)
return ''
else:
return def_._name._context.get_safe_value()
def test_f_strings(Script, environment):
"""
f literals are not really supported in Jedi. They just get ignored and an
empty string is returned.
"""
if environment.version_info < (3, 6):
pytest.skip()
assert _eval_literal(Script, 'f"asdf"', is_fstring=True) == ''
assert _eval_literal(Script, 'f"{asdf} "', is_fstring=True) == ''
assert _eval_literal(Script, 'F"{asdf} "', is_fstring=True) == ''
assert _eval_literal(Script, 'rF"{asdf} "', is_fstring=True) == ''
def test_rb_strings(Script, environment):
assert _eval_literal(Script, 'br"asdf"') == b'asdf'
obj = _eval_literal(Script, 'rb"asdf"')
# rb is not valid in Python 2. Due to error recovery we just get a
# string.
assert obj == b'asdf'
def test_thousand_separators(Script, environment):
if environment.version_info < (3, 6):
pytest.skip()
assert _eval_literal(Script, '1_2_3') == 123
assert _eval_literal(Script, '123_456_789') == 123456789
assert _eval_literal(Script, '0x3_4') == 52
assert _eval_literal(Script, '0b1_0') == 2
assert _eval_literal(Script, '0o1_0') == 8

View File

@@ -0,0 +1,7 @@
import jedi
def test_on_code():
from functools import wraps
i = jedi.Interpreter("wraps.__code__", [{'wraps':wraps}])
assert i.goto_definitions()

View File

@@ -0,0 +1,96 @@
from os.path import dirname, join
import pytest
import py
from ..helpers import get_example_dir
SYS_PATH = [join(dirname(__file__), d)
for d in ['namespace_package/ns1', 'namespace_package/ns2']]
def script_with_path(Script, *args, **kwargs):
return Script(sys_path=SYS_PATH, *args, **kwargs)
def test_goto_definition(Script):
assert script_with_path(Script, 'from pkg import ns1_file').goto_definitions()
assert script_with_path(Script, 'from pkg import ns2_file').goto_definitions()
assert not script_with_path(Script, 'from pkg import ns3_file').goto_definitions()
@pytest.mark.parametrize(
('source', 'solution'), [
('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!'),
]
)
def test_goto_assignment(Script, source, solution):
ass = script_with_path(Script, source).goto_assignments()
assert len(ass) == 1
assert ass[0].description == "foo = '%s'" % solution
def test_simple_completions(Script):
# completion
completions = script_with_path(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)
@pytest.mark.parametrize(
('source', 'solution'), [
('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!'),
]
)
def test_completions(Script, source, solution):
for c in script_with_path(Script, source + '; x.').completions():
if c.name == 'foo':
completion = c
solution = "foo = '%s'" % solution
assert completion.description == solution
def test_nested_namespace_package(Script):
code = 'from nested_namespaces.namespace.pkg import CONST'
sys_path = [dirname(__file__)]
script = Script(sys_path=sys_path, source=code, line=1, column=45)
result = script.goto_definitions()
assert len(result) == 1
def test_relative_import(Script, environment, tmpdir):
"""
Attempt a relative import in a very simple namespace package.
"""
if environment.version_info < (3, 4):
pytest.skip()
directory = get_example_dir('namespace_package_relative_import')
# Need to copy the content in a directory where there's no __init__.py.
py.path.local(directory).copy(tmpdir)
file_path = join(tmpdir.strpath, "rel1.py")
script = Script(path=file_path, line=1)
d, = script.goto_definitions()
assert d.name == 'int'
d, = script.goto_assignments()
assert d.name == 'name'
assert d.module_name == 'rel2'

View File

@@ -0,0 +1,18 @@
from jedi.evaluate.compiled import CompiledObject
import pytest
@pytest.mark.parametrize('source', [
pytest.param('1 == 1'),
pytest.param('1.0 == 1'),
# Unfortunately for now not possible, because it's a typeshed object.
pytest.param('... == ...', marks=pytest.mark.xfail),
])
def test_equals(Script, environment, source):
if environment.version_info.major < 3:
pytest.skip("Ellipsis does not exists in 2")
script = Script(source)
node = script._module_node.children[0]
first, = script._get_module().eval_node(node)
assert isinstance(first, CompiledObject) and first.get_safe_value() is True

View File

@@ -0,0 +1,73 @@
"""
Test completions from *.pyc files:
- generate a dummy python module
- compile the dummy module to generate a *.pyc
- delete the pure python dummy module
- try jedi on the generated *.pyc
"""
import os
import shutil
import sys
import pytest
import jedi
from jedi.api.environment import SameEnvironment, InterpreterEnvironment
SRC = """class Foo:
pass
class Bar:
pass
"""
@pytest.fixture
def pyc_project_path(tmpdir):
path = tmpdir.strpath
dummy_package_path = os.path.join(path, "dummy_package")
os.mkdir(dummy_package_path)
with open(os.path.join(dummy_package_path, "__init__.py"), 'w'):
pass
dummy_path = os.path.join(dummy_package_path, 'dummy.py')
with open(dummy_path, 'w') as f:
f.write(SRC)
import compileall
compileall.compile_file(dummy_path)
os.remove(dummy_path)
if sys.version_info.major == 3:
# Python3 specific:
# To import pyc modules, we must move them out of the __pycache__
# directory and rename them to remove ".cpython-%s%d"
# see: http://stackoverflow.com/questions/11648440/python-does-not-detect-pyc-files
pycache = os.path.join(dummy_package_path, "__pycache__")
for f in os.listdir(pycache):
dst = f.replace('.cpython-%s%s' % sys.version_info[:2], "")
dst = os.path.join(dummy_package_path, dst)
shutil.copy(os.path.join(pycache, f), dst)
try:
yield path
finally:
shutil.rmtree(path)
def test_pyc(pyc_project_path, environment):
"""
The list of completion must be greater than 2.
"""
path = os.path.join(pyc_project_path, 'blub.py')
if not isinstance(environment, InterpreterEnvironment):
# We are using the same version for pyc completions here, because it
# was compiled in that version. However with interpreter environments
# we also have the same version and it's easier to debug.
environment = SameEnvironment()
environment = environment
s = jedi.Script(
"from dummy_package import dummy; dummy.",
path=path,
environment=environment)
assert len(s.completions()) >= 2

View File

@@ -0,0 +1,34 @@
from textwrap import dedent
def get_definition_and_evaluator(Script, source):
first, = Script(dedent(source)).goto_definitions()
return first._name._context, first._evaluator
def test_function_execution(Script):
"""
We've been having an issue of a mutable list that was changed inside the
function execution. Test if an execution always returns the same result.
"""
s = """
def x():
return str()
x"""
func, evaluator = get_definition_and_evaluator(Script, s)
# Now just use the internals of the result (easiest way to get a fully
# usable function).
# Should return the same result both times.
assert len(func.execute_with_values()) == 1
assert len(func.execute_with_values()) == 1
def test_class_mro(Script):
s = """
class X(object):
pass
X"""
cls, evaluator = get_definition_and_evaluator(Script, s)
mro = cls.py__mro__()
assert [c.name.string_name for c in mro] == ['X', 'object']

View File

@@ -0,0 +1,268 @@
from textwrap import dedent
from operator import ge, lt
import re
import pytest
from jedi.evaluate.gradual.conversion import _stub_to_python_context_set
@pytest.mark.parametrize(
'code, sig, names, op, version', [
('import math; math.cos', 'cos(x, /)', ['x'], ge, (2, 7)),
('next', 'next(iterator, default=None, /)', ['iterator', 'default'], ge, (2, 7)),
('str', "str(object='', /) -> str", ['object'], ge, (2, 7)),
('pow', 'pow(x, y, z=None, /) -> number', ['x', 'y', 'z'], lt, (3, 5)),
('pow', 'pow(x, y, z=None, /)', ['x', 'y', 'z'], ge, (3, 5)),
('bytes.partition', 'partition(self, sep, /) -> (head, sep, tail)', ['self', 'sep'], lt, (3, 5)),
('bytes.partition', 'partition(self, sep, /)', ['self', 'sep'], ge, (3, 5)),
('bytes().partition', 'partition(sep, /) -> (head, sep, tail)', ['sep'], lt, (3, 5)),
('bytes().partition', 'partition(sep, /)', ['sep'], ge, (3, 5)),
]
)
def test_compiled_signature(Script, environment, code, sig, names, op, version):
if not op(environment.version_info, version):
return # The test right next to it should take over.
d, = Script(code).goto_definitions()
context, = d._name.infer()
compiled, = _stub_to_python_context_set(context)
signature, = compiled.get_signatures()
assert signature.to_string() == sig
assert [n.string_name for n in signature.get_param_names()] == names
classmethod_code = '''
class X:
@classmethod
def x(cls, a, b):
pass
@staticmethod
def static(a, b):
pass
'''
partial_code = '''
import functools
def func(a, b, c):
pass
a = functools.partial(func)
b = functools.partial(func, 1)
c = functools.partial(func, 1, c=2)
d = functools.partial()
'''
@pytest.mark.parametrize(
'code, expected', [
('def f(a, * args, x): pass\n f(', 'f(a, *args, x)'),
('def f(a, *, x): pass\n f(', 'f(a, *, x)'),
('def f(*, x= 3,**kwargs): pass\n f(', 'f(*, x=3, **kwargs)'),
('def f(x,/,y,* ,z): pass\n f(', 'f(x, /, y, *, z)'),
('def f(a, /, *, x=3, **kwargs): pass\n f(', 'f(a, /, *, x=3, **kwargs)'),
(classmethod_code + 'X.x(', 'x(cls, a, b)'),
(classmethod_code + 'X().x(', 'x(cls, a, b)'),
(classmethod_code + 'X.static(', 'static(a, b)'),
(classmethod_code + 'X().static(', 'static(a, b)'),
(partial_code + 'a(', 'func(a, b, c)'),
(partial_code + 'b(', 'func(b, c)'),
(partial_code + 'c(', 'func(b)'),
(partial_code + 'd(', None),
]
)
def test_tree_signature(Script, environment, code, expected):
# Only test this in the latest version, because of /
if environment.version_info < (3, 8):
pytest.skip()
if expected is None:
assert not Script(code).call_signatures()
else:
sig, = Script(code).call_signatures()
assert expected == sig.to_string()
@pytest.mark.parametrize(
'combination, expected', [
# Functions
('full_redirect(simple)', 'b, *, c'),
('full_redirect(simple4)', 'b, x: int'),
('full_redirect(a)', 'b, *args'),
('full_redirect(kw)', 'b, *, c, **kwargs'),
('full_redirect(akw)', 'c, *args, **kwargs'),
# Non functions
('full_redirect(lambda x, y: ...)', 'y'),
('full_redirect()', '*args, **kwargs'),
('full_redirect(1)', '*args, **kwargs'),
# Classes / inheritance
('full_redirect(C)', 'z, *, c'),
('full_redirect(C())', 'y'),
('D', 'D(a, z, /)'),
('D()', 'D(x, y)'),
('D().foo', 'foo(a, *, bar, z, **kwargs)'),
# Merging
('two_redirects(simple, simple)', 'a, b, *, c'),
('two_redirects(simple2, simple2)', 'x'),
('two_redirects(akw, kw)', 'a, c, *args, **kwargs'),
('two_redirects(kw, akw)', 'a, b, *args, c, **kwargs'),
('combined_redirect(simple, simple2)', 'a, b, /, *, x'),
('combined_redirect(simple, simple3)', 'a, b, /, *, a, x: int'),
('combined_redirect(simple2, simple)', 'x, /, *, a, b, c'),
('combined_redirect(simple3, simple)', 'a, x: int, /, *, a, b, c'),
('combined_redirect(simple, kw)', 'a, b, /, *, a, b, c, **kwargs'),
('combined_redirect(kw, simple)', 'a, b, /, *, a, b, c'),
('combined_lot_of_args(kw, simple4)', '*, b'),
('combined_lot_of_args(simple4, kw)', '*, b, c, **kwargs'),
('combined_redirect(combined_redirect(simple2, simple4), combined_redirect(kw, simple5))',
'x, /, *, y'),
('combined_redirect(combined_redirect(simple4, simple2), combined_redirect(simple5, kw))',
'a, b, x: int, /, *, a, b, c, **kwargs'),
('combined_redirect(combined_redirect(a, kw), combined_redirect(kw, simple5))',
'a, b, /, *args, y'),
('no_redirect(kw)', '*args, **kwargs'),
('no_redirect(akw)', '*args, **kwargs'),
('no_redirect(simple)', '*args, **kwargs'),
]
)
def test_nested_signatures(Script, environment, combination, expected, skip_pre_python35):
code = dedent('''
def simple(a, b, *, c): ...
def simple2(x): ...
def simple3(a, x: int): ...
def simple4(a, b, x: int): ...
def simple5(y): ...
def a(a, b, *args): ...
def kw(a, b, *, c, **kwargs): ...
def akw(a, c, *args, **kwargs): ...
def no_redirect(func):
return lambda *args, **kwargs: func(1)
def full_redirect(func):
return lambda *args, **kwargs: func(1, *args, **kwargs)
def two_redirects(func1, func2):
return lambda *args, **kwargs: func1(*args, **kwargs) + func2(1, *args, **kwargs)
def combined_redirect(func1, func2):
return lambda *args, **kwargs: func1(*args) + func2(**kwargs)
def combined_lot_of_args(func1, func2):
return lambda *args, **kwargs: func1(1, 2, 3, 4, *args) + func2(a=3, x=1, y=1, **kwargs)
class C:
def __init__(self, a, z, *, c): ...
def __call__(self, x, y): ...
def foo(self, bar, z, **kwargs): ...
class D(C):
def __init__(self, *args):
super().__init__(*args)
def foo(self, a, **kwargs):
super().foo(**kwargs)
''')
code += 'z = ' + combination + '\nz('
sig, = Script(code).call_signatures()
computed = sig.to_string()
if not re.match(r'\w+\(', expected):
expected = '<lambda>(' + expected + ')'
assert expected == computed
def test_pow_signature(Script):
# See github #1357
sigs = Script('pow(').call_signatures()
strings = {sig.to_string() for sig in sigs}
assert strings == {'pow(x: float, y: float, z: float, /) -> float',
'pow(x: float, y: float, /) -> float',
'pow(x: int, y: int, z: int, /) -> Any',
'pow(x: int, y: int, /) -> Any'}
@pytest.mark.parametrize(
'code, signature', [
[dedent('''
import functools
def f(x):
pass
def x(f):
@functools.wraps(f)
def wrapper(*args):
# Have no arguments here, but because of wraps, the signature
# should still be f's.
return f(*args)
return wrapper
x(f)('''), 'f(x, /)'],
[dedent('''
import functools
def f(x):
pass
def x(f):
@functools.wraps(f)
def wrapper():
# Have no arguments here, but because of wraps, the signature
# should still be f's.
return 1
return wrapper
x(f)('''), 'f()'],
]
)
def test_wraps_signature(Script, code, signature, skip_pre_python35):
sigs = Script(code).call_signatures()
assert {sig.to_string() for sig in sigs} == {signature}
@pytest.mark.parametrize(
'start, start_params', [
['@dataclass\nclass X:', []],
['@dataclass(eq=True)\nclass X:', []],
[dedent('''
class Y():
y: int
@dataclass
class X(Y):'''), []],
[dedent('''
@dataclass
class Y():
y: int
z = 5
@dataclass
class X(Y):'''), ['y']],
]
)
def test_dataclass_signature(Script, skip_pre_python37, start, start_params):
code = dedent('''
name: str
foo = 3
price: float
quantity: int = 0.0
X(''')
code = 'from dataclasses import dataclass\n' + start + code
sig, = Script(code).call_signatures()
assert [p.name for p in sig.params] == start_params + ['name', 'price', 'quantity']
quantity, = sig.params[-1].infer()
assert quantity.name == 'int'
price, = sig.params[-2].infer()
assert price.name == 'float'

View File

@@ -0,0 +1,103 @@
"""
Tests of various stdlib related things that could not be tested
with "Black Box Tests".
"""
from textwrap import dedent
import pytest
@pytest.mark.parametrize(['letter', 'expected'], [
('n', ['name']),
('s', ['smart']),
])
def test_namedtuple_str(letter, expected, Script):
source = dedent("""\
import collections
Person = collections.namedtuple('Person', 'name smart')
dave = Person('Dave', False)
dave.%s""") % letter
result = Script(source).completions()
completions = set(r.name for r in result)
assert completions == set(expected)
def test_namedtuple_list(Script):
source = dedent("""\
import collections
Cat = collections.namedtuple('Person', ['legs', u'length', 'large'])
garfield = Cat(4, '85cm', True)
garfield.l""")
result = Script(source).completions()
completions = set(r.name for r in result)
assert completions == {'legs', 'length', 'large'}
def test_namedtuple_content(Script):
source = dedent("""\
import collections
Foo = collections.namedtuple('Foo', ['bar', 'baz'])
named = Foo(baz=4, bar=3.0)
unnamed = Foo(4, '')
""")
def d(source):
x, = Script(source).goto_definitions()
return x.name
assert d(source + 'unnamed.bar') == 'int'
assert d(source + 'unnamed.baz') == 'str'
assert d(source + 'named.bar') == 'float'
assert d(source + 'named.baz') == 'int'
def test_nested_namedtuples(Script):
"""
From issue #730.
"""
s = Script(dedent('''
import collections
Dataset = collections.namedtuple('Dataset', ['data'])
Datasets = collections.namedtuple('Datasets', ['train'])
train_x = Datasets(train=Dataset('data_value'))
train_x.train.'''
))
assert 'data' in [c.name for c in s.completions()]
def test_namedtuple_goto_definitions(Script):
source = dedent("""
from collections import namedtuple
Foo = namedtuple('Foo', 'id timestamp gps_timestamp attributes')
Foo""")
from jedi.api import Script
d1, = Script(source).goto_definitions()
assert d1.get_line_code() == "class Foo(tuple):\n"
assert d1.module_path is None
def test_re_sub(Script, environment):
"""
This whole test was taken out of completion/stdlib.py, because of the
version differences.
"""
def run(code):
defs = Script(code).goto_definitions()
return {d.name for d in defs}
names = run("import re; re.sub('a', 'a', 'f')")
if environment.version_info.major == 2:
assert names == {'str'}
else:
assert names == {'str'}
# This param is missing because of overloading.
names = run("import re; re.sub('a', 'a')")
if environment.version_info.major == 2:
assert names == {'str', 'unicode'}
else:
assert names == {'str', 'bytes'}

View File

@@ -0,0 +1,110 @@
import os
from glob import glob
import sys
import shutil
import pytest
from ..helpers import skip_if_windows, skip_if_not_windows
from jedi.evaluate import sys_path
from jedi.api.environment import create_environment
def test_paths_from_assignment(Script):
def paths(src):
script = Script(src, path='/foo/bar.py')
expr_stmt = script._module_node.children[0]
return set(sys_path._paths_from_assignment(script._get_module(), expr_stmt))
# Normalize paths for Windows.
path_a = os.path.abspath('/foo/a')
path_b = os.path.abspath('/foo/b')
path_c = os.path.abspath('/foo/c')
assert paths('sys.path[0:0] = ["a"]') == {path_a}
assert paths('sys.path = ["b", 1, x + 3, y, "c"]') == {path_b, path_c}
assert paths('sys.path = a = ["a"]') == {path_a}
# Fail for complicated examples.
assert paths('sys.path, other = ["a"], 2') == set()
def test_venv_and_pths(venv_path):
pjoin = os.path.join
CUR_DIR = os.path.dirname(__file__)
site_pkg_path = pjoin(venv_path, 'lib')
if os.name == 'nt':
site_pkg_path = pjoin(site_pkg_path, 'site-packages')
else:
site_pkg_path = glob(pjoin(site_pkg_path, 'python*', 'site-packages'))[0]
shutil.rmtree(site_pkg_path)
shutil.copytree(pjoin(CUR_DIR, 'sample_venvs', 'pth_directory'), site_pkg_path)
virtualenv = create_environment(venv_path)
venv_paths = virtualenv.get_sys_path()
ETALON = [
# For now disable egg-links. I have no idea how they work... ~ dave
#pjoin('/path', 'from', 'egg-link'),
#pjoin(site_pkg_path, '.', 'relative', 'egg-link', 'path'),
site_pkg_path,
pjoin(site_pkg_path, 'dir-from-foo-pth'),
'/foo/smth.py:module',
# Not sure why it's added twice. It has to do with site.py which is not
# something we can change. However this obviously also doesn't matter.
'/foo/smth.py:from_func',
'/foo/smth.py:from_func',
]
# Ensure that pth and egg-link paths were added.
assert venv_paths[-len(ETALON):] == ETALON
# Ensure that none of venv dirs leaked to the interpreter.
assert not set(sys.path).intersection(ETALON)
_s = ['/a', '/b', '/c/d/']
@pytest.mark.parametrize(
'sys_path_, module_path, expected, is_package', [
(_s, '/a/b', ('b',), False),
(_s, '/a/b/c', ('b', 'c'), False),
(_s, '/a/b.py', ('b',), False),
(_s, '/a/b/c.py', ('b', 'c'), False),
(_s, '/x/b.py', None, False),
(_s, '/c/d/x.py', ('x',), False),
(_s, '/c/d/x.py', ('x',), False),
(_s, '/c/d/x/y.py', ('x', 'y'), False),
# If dots are in there they also resolve. These are obviously illegal
# in Python, but Jedi can handle them. Give the user a bit more freedom
# that he will have to correct eventually.
(_s, '/a/b.c.py', ('b.c',), False),
(_s, '/a/b.d/foo.bar.py', ('b.d', 'foo.bar'), False),
(_s, '/a/.py', None, False),
(_s, '/a/c/.py', None, False),
(['/foo'], '/foo/bar/__init__.py', ('bar',), True),
(['/foo'], '/foo/bar/baz/__init__.py', ('bar', 'baz'), True),
skip_if_windows(['/foo'], '/foo/bar.so', ('bar',), False),
skip_if_windows(['/foo'], '/foo/bar/__init__.so', ('bar',), True),
skip_if_not_windows(['/foo'], '/foo/bar.pyd', ('bar',), False),
skip_if_not_windows(['/foo'], '/foo/bar/__init__.pyd', ('bar',), True),
(['/foo'], '/x/bar.py', None, False),
(['/foo'], '/foo/bar.xyz', ('bar.xyz',), False),
(['/foo', '/foo/bar'], '/foo/bar/baz', ('baz',), False),
(['/foo/bar', '/foo'], '/foo/bar/baz', ('baz',), False),
(['/'], '/bar/baz.py', ('bar', 'baz',), False),
])
def test_transform_path_to_dotted(sys_path_, module_path, expected, is_package):
# transform_path_to_dotted expects normalized absolute paths.
sys_path_ = [os.path.abspath(path) for path in sys_path_]
module_path = os.path.abspath(module_path)
assert sys_path.transform_path_to_dotted(sys_path_, module_path) \
== (expected, is_package)

Binary file not shown.

Binary file not shown.