Adding new stuff
This commit is contained in:
parent
9ef8a96f9a
commit
0b3d063cb3
1580 changed files with 0 additions and 0 deletions
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
#!/usr/bin/python
|
||||
|
||||
import sys
|
||||
sys.path[0:0] = [
|
||||
'/usr/lib/python3.4/site-packages',
|
||||
'/tmp/.buildout/eggs/important_package.egg'
|
||||
]
|
||||
|
||||
import important_package
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(important_package.main())
|
||||
|
|
@ -0,0 +1 @@
|
|||
‰PNG
|
||||
|
|
@ -0,0 +1 @@
|
|||
|
||||
|
|
@ -0,0 +1 @@
|
|||
|
||||
|
|
@ -0,0 +1 @@
|
|||
Baz = 1
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
class Foo(object):
|
||||
pass
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
class Bar(object):
|
||||
pass
|
||||
|
|
@ -0,0 +1 @@
|
|||
Moo = 1
|
||||
Binary file not shown.
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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'])
|
||||
]
|
||||
)
|
||||
|
|
@ -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__)
|
||||
|
|
@ -0,0 +1 @@
|
|||
foo = 'ns1_file!'
|
||||
|
|
@ -0,0 +1 @@
|
|||
foo = 'ns1_folder!'
|
||||
|
|
@ -0,0 +1 @@
|
|||
foo = 'ns2_file!'
|
||||
|
|
@ -0,0 +1 @@
|
|||
foo = 'ns2_folder!'
|
||||
|
|
@ -0,0 +1 @@
|
|||
foo = 'nested!'
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
try:
|
||||
__import__('pkg_resources').declare_namespace(__name__)
|
||||
except ImportError:
|
||||
pass
|
||||
|
|
@ -0,0 +1 @@
|
|||
CONST = 1
|
||||
|
|
@ -0,0 +1 @@
|
|||
value = 3
|
||||
|
|
@ -0,0 +1 @@
|
|||
value = 'package'
|
||||
|
|
@ -0,0 +1 @@
|
|||
value = 'package.module'
|
||||
|
|
@ -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
|
||||
|
|
@ -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')
|
||||
|
|
@ -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')
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
"""
|
||||
Tests ``from __future__ import absolute_import`` (only important for
|
||||
Python 2.X)
|
||||
"""
|
||||
import jedi
|
||||
from jedi._compatibility import u
|
||||
from jedi.parser import ParserWithRecovery, load_grammar
|
||||
from .. import helpers
|
||||
|
||||
|
||||
def test_explicit_absolute_imports():
|
||||
"""
|
||||
Detect modules with ``from __future__ import absolute_import``.
|
||||
"""
|
||||
parser = ParserWithRecovery(load_grammar(), u("from __future__ import absolute_import"), "test.py")
|
||||
assert parser.module.has_explicit_absolute_import
|
||||
|
||||
|
||||
def test_no_explicit_absolute_imports():
|
||||
"""
|
||||
Detect modules without ``from __future__ import absolute_import``.
|
||||
"""
|
||||
parser = ParserWithRecovery(load_grammar(), u("1"), "test.py")
|
||||
assert not parser.module.has_explicit_absolute_import
|
||||
|
||||
|
||||
def test_dont_break_imports_without_namespaces():
|
||||
"""
|
||||
The code checking for ``from __future__ import absolute_import`` shouldn't
|
||||
assume that all imports have non-``None`` namespaces.
|
||||
"""
|
||||
src = u("from __future__ import absolute_import\nimport xyzzy")
|
||||
parser = ParserWithRecovery(load_grammar(), src, "test.py")
|
||||
assert parser.module.has_explicit_absolute_import
|
||||
|
||||
|
||||
@helpers.cwd_at("test/test_evaluate/absolute_import")
|
||||
def test_can_complete_when_shadowing():
|
||||
script = jedi.Script(path="unittest.py")
|
||||
assert script.completions()
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
from textwrap import dedent
|
||||
|
||||
import jedi
|
||||
import pytest
|
||||
|
||||
|
||||
@pytest.mark.skipif('sys.version_info[0] < 3')
|
||||
def test_simple_annotations():
|
||||
"""
|
||||
Annotations only exist in Python 3.
|
||||
If annotations adhere to PEP-0484, we use them (they override inference),
|
||||
else they are parsed but ignored
|
||||
"""
|
||||
|
||||
source = dedent("""\
|
||||
def annot(a:3):
|
||||
return a
|
||||
|
||||
annot('')""")
|
||||
|
||||
assert [d.name for d in jedi.Script(source, ).goto_definitions()] == ['str']
|
||||
|
||||
source = dedent("""\
|
||||
|
||||
def annot_ret(a:3) -> 3:
|
||||
return a
|
||||
|
||||
annot_ret('')""")
|
||||
assert [d.name for d in jedi.Script(source, ).goto_definitions()] == ['str']
|
||||
|
||||
source = dedent("""\
|
||||
def annot(a:int):
|
||||
return a
|
||||
|
||||
annot('')""")
|
||||
|
||||
assert [d.name for d in jedi.Script(source, ).goto_definitions()] == ['int']
|
||||
|
||||
|
||||
@pytest.mark.skipif('sys.version_info[0] < 3')
|
||||
@pytest.mark.parametrize('reference', [
|
||||
'assert 1',
|
||||
'1',
|
||||
'def x(): pass',
|
||||
'1, 2',
|
||||
r'1\n'
|
||||
])
|
||||
def test_illegal_forward_references(reference):
|
||||
source = 'def foo(bar: "%s"): bar' % reference
|
||||
|
||||
assert not jedi.Script(source).goto_definitions()
|
||||
|
||||
|
||||
@pytest.mark.skipif('sys.version_info[0] < 3')
|
||||
def test_lambda_forward_references():
|
||||
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 jedi.Script(source).goto_definitions()
|
||||
|
|
@ -0,0 +1,89 @@
|
|||
import os
|
||||
from textwrap import dedent
|
||||
|
||||
from jedi._compatibility import u
|
||||
from jedi.evaluate.sys_path import (_get_parent_dir_with_file,
|
||||
_get_buildout_scripts,
|
||||
sys_path_with_modifications,
|
||||
_check_module)
|
||||
from jedi.evaluate import Evaluator
|
||||
from jedi.parser import ParserWithRecovery, load_grammar
|
||||
|
||||
from ..helpers import cwd_at
|
||||
|
||||
|
||||
@cwd_at('test/test_evaluate/buildout_project/src/proj_name')
|
||||
def test_parent_dir_with_file():
|
||||
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', 'test_evaluate', 'buildout_project'))
|
||||
|
||||
|
||||
@cwd_at('test/test_evaluate/buildout_project/src/proj_name')
|
||||
def test_buildout_detection():
|
||||
scripts = _get_buildout_scripts(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():
|
||||
SRC = dedent(u("""
|
||||
class Dummy(object):
|
||||
path = []
|
||||
|
||||
d = Dummy()
|
||||
d.path.append('foo')"""))
|
||||
grammar = load_grammar()
|
||||
p = ParserWithRecovery(grammar, SRC)
|
||||
paths = _check_module(Evaluator(grammar), p.module)
|
||||
assert len(paths) > 0
|
||||
assert 'foo' not in paths
|
||||
|
||||
|
||||
def test_path_from_invalid_sys_path_assignment():
|
||||
SRC = dedent(u("""
|
||||
import sys
|
||||
sys.path = 'invalid'"""))
|
||||
grammar = load_grammar()
|
||||
p = ParserWithRecovery(grammar, SRC)
|
||||
paths = _check_module(Evaluator(grammar), p.module)
|
||||
assert len(paths) > 0
|
||||
assert 'invalid' not in paths
|
||||
|
||||
|
||||
@cwd_at('test/test_evaluate/buildout_project/src/proj_name/')
|
||||
def test_sys_path_with_modifications():
|
||||
SRC = dedent(u("""
|
||||
import os
|
||||
"""))
|
||||
grammar = load_grammar()
|
||||
p = ParserWithRecovery(grammar, SRC)
|
||||
p.module.path = os.path.abspath(os.path.join(os.curdir, 'module_name.py'))
|
||||
paths = sys_path_with_modifications(Evaluator(grammar), p.module)
|
||||
assert '/tmp/.buildout/eggs/important_package.egg' in paths
|
||||
|
||||
|
||||
def test_path_from_sys_path_assignment():
|
||||
SRC = dedent(u("""
|
||||
#!/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())"""))
|
||||
grammar = load_grammar()
|
||||
p = ParserWithRecovery(grammar, SRC)
|
||||
paths = _check_module(Evaluator(grammar), p.module)
|
||||
assert 1 not in paths
|
||||
assert '/home/test/.buildout/eggs/important_package.egg' in paths
|
||||
|
|
@ -0,0 +1,86 @@
|
|||
from textwrap import dedent
|
||||
|
||||
from jedi._compatibility import builtins, is_py3
|
||||
from jedi.parser import load_grammar
|
||||
from jedi.parser.tree import Function
|
||||
from jedi.evaluate import compiled, representation
|
||||
from jedi.evaluate import Evaluator
|
||||
from jedi import Script
|
||||
|
||||
|
||||
def _evaluator():
|
||||
return Evaluator(load_grammar())
|
||||
|
||||
|
||||
def test_simple():
|
||||
e = _evaluator()
|
||||
bltn = compiled.CompiledObject(e, builtins)
|
||||
obj = compiled.CompiledObject(e, '_str_', bltn)
|
||||
upper = e.find_types(obj, 'upper')
|
||||
assert len(upper) == 1
|
||||
objs = list(e.execute(list(upper)[0]))
|
||||
assert len(objs) == 1
|
||||
assert isinstance(objs[0], representation.Instance)
|
||||
|
||||
|
||||
def test_fake_loading():
|
||||
e = _evaluator()
|
||||
assert isinstance(compiled.create(e, next), Function)
|
||||
|
||||
builtin = compiled.get_special_object(e, 'BUILTINS')
|
||||
string = builtin.get_subscope_by_name('str')
|
||||
from_name = compiled._create_from_name(e, builtin, string, '__init__')
|
||||
assert isinstance(from_name, Function)
|
||||
|
||||
|
||||
def test_fake_docstr():
|
||||
assert compiled.create(_evaluator(), next).raw_doc == next.__doc__
|
||||
|
||||
|
||||
def test_parse_function_doc_illegal_docstr():
|
||||
docstr = """
|
||||
test_func(o
|
||||
|
||||
doesn't have a closing bracket.
|
||||
"""
|
||||
assert ('', '') == compiled._parse_function_doc(docstr)
|
||||
|
||||
|
||||
def test_doc():
|
||||
"""
|
||||
Even CompiledObject docs always return empty docstrings - not None, that's
|
||||
just a Jedi API definition.
|
||||
"""
|
||||
obj = compiled.CompiledObject(_evaluator(), ''.__getnewargs__)
|
||||
assert obj.doc == ''
|
||||
|
||||
|
||||
def test_string_literals():
|
||||
def typ(string):
|
||||
d = Script("a = %s; a" % string).goto_definitions()[0]
|
||||
return d.name
|
||||
|
||||
assert typ('""') == 'str'
|
||||
assert typ('r""') == 'str'
|
||||
if is_py3:
|
||||
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():
|
||||
code = dedent('''
|
||||
class Foo:
|
||||
def bar(self):
|
||||
pass
|
||||
|
||||
foo = Foo()
|
||||
foo.bar.__func__''')
|
||||
if is_py3:
|
||||
result = []
|
||||
else:
|
||||
result = ['__func__']
|
||||
assert [c.name for c in Script(code).completions()] == result
|
||||
|
|
@ -0,0 +1,152 @@
|
|||
"""
|
||||
Testing of docstring related issues and especially ``jedi.docstrings``.
|
||||
"""
|
||||
|
||||
from textwrap import dedent
|
||||
import jedi
|
||||
from ..helpers import unittest
|
||||
|
||||
try:
|
||||
import numpydoc
|
||||
except ImportError:
|
||||
numpydoc_unavailable = True
|
||||
else:
|
||||
numpydoc_unavailable = False
|
||||
|
||||
|
||||
class TestDocstring(unittest.TestCase):
|
||||
def test_function_doc(self):
|
||||
defs = jedi.Script("""
|
||||
def func():
|
||||
'''Docstring of `func`.'''
|
||||
func""").goto_definitions()
|
||||
self.assertEqual(defs[0].raw_doc, 'Docstring of `func`.')
|
||||
|
||||
@unittest.skip('need evaluator class for that')
|
||||
def test_attribute_docstring(self):
|
||||
defs = jedi.Script("""
|
||||
x = None
|
||||
'''Docstring of `x`.'''
|
||||
x""").goto_definitions()
|
||||
self.assertEqual(defs[0].raw_doc, 'Docstring of `x`.')
|
||||
|
||||
@unittest.skip('need evaluator class for that')
|
||||
def test_multiple_docstrings(self):
|
||||
defs = jedi.Script("""
|
||||
def func():
|
||||
'''Original docstring.'''
|
||||
x = func
|
||||
'''Docstring of `x`.'''
|
||||
x""").goto_definitions()
|
||||
docs = [d.raw_doc for d in defs]
|
||||
self.assertEqual(docs, ['Original docstring.', 'Docstring of `x`.'])
|
||||
|
||||
def test_completion(self):
|
||||
assert jedi.Script('''
|
||||
class DocstringCompletion():
|
||||
#? []
|
||||
""" asdfas """''').completions()
|
||||
|
||||
def test_docstrings_type_dotted_import(self):
|
||||
s = """
|
||||
def func(arg):
|
||||
'''
|
||||
:type arg: random.Random
|
||||
'''
|
||||
arg."""
|
||||
names = [c.name for c in jedi.Script(s).completions()]
|
||||
assert 'seed' in names
|
||||
|
||||
def test_docstrings_param_type(self):
|
||||
s = """
|
||||
def func(arg):
|
||||
'''
|
||||
:param str arg: some description
|
||||
'''
|
||||
arg."""
|
||||
names = [c.name for c in jedi.Script(s).completions()]
|
||||
assert 'join' in names
|
||||
|
||||
def test_docstrings_type_str(self):
|
||||
s = """
|
||||
def func(arg):
|
||||
'''
|
||||
:type arg: str
|
||||
'''
|
||||
arg."""
|
||||
|
||||
names = [c.name for c in jedi.Script(s).completions()]
|
||||
assert 'join' in names
|
||||
|
||||
def test_docstring_instance(self):
|
||||
# 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 jedi.Script(s).completions()]
|
||||
assert 'a' in names
|
||||
assert '__init__' in names
|
||||
assert 'mro' not in names # Exists only for types.
|
||||
|
||||
@unittest.skipIf(numpydoc_unavailable, 'numpydoc module is unavailable')
|
||||
def test_numpydoc_docstring(self):
|
||||
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
|
||||
|
||||
@unittest.skipIf(numpydoc_unavailable, 'numpydoc module is unavailable')
|
||||
def test_numpydoc_docstring_set_of_values(self):
|
||||
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
|
||||
|
||||
@unittest.skipIf(numpydoc_unavailable, 'numpydoc module is unavailable')
|
||||
def test_numpydoc_alternative_types(self):
|
||||
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
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
"""
|
||||
Test compiled module
|
||||
"""
|
||||
import os
|
||||
|
||||
import jedi
|
||||
from ..helpers import cwd_at
|
||||
import pytest
|
||||
|
||||
|
||||
def test_completions():
|
||||
s = jedi.Script('import _ctypes; _ctypes.')
|
||||
assert len(s.completions()) >= 15
|
||||
|
||||
|
||||
def test_call_signatures_extension():
|
||||
if os.name == 'nt':
|
||||
func = 'LoadLibrary'
|
||||
params = 1
|
||||
else:
|
||||
func = 'dlopen'
|
||||
params = 2
|
||||
s = jedi.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():
|
||||
s = jedi.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_evaluate')
|
||||
def test_init_extension_module():
|
||||
"""
|
||||
``__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()]
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
from textwrap import dedent
|
||||
|
||||
from jedi import names
|
||||
from jedi.evaluate import helpers
|
||||
|
||||
|
||||
def test_call_of_leaf_in_brackets():
|
||||
s = dedent("""
|
||||
x = 1
|
||||
type(x)
|
||||
""")
|
||||
last_x = names(s, references=True, definitions=False)[-1]
|
||||
name = last_x._name
|
||||
|
||||
call = helpers.call_of_leaf(name)
|
||||
assert call == name
|
||||
|
|
@ -0,0 +1,129 @@
|
|||
import os
|
||||
import sys
|
||||
|
||||
import pytest
|
||||
|
||||
import jedi
|
||||
from jedi._compatibility import find_module_py33, find_module
|
||||
from ..helpers import cwd_at
|
||||
|
||||
|
||||
@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, '_io', False)
|
||||
|
||||
|
||||
def test_find_module_package():
|
||||
file, path, is_package = find_module('json')
|
||||
assert file is None
|
||||
assert path.endswith('json')
|
||||
assert is_package is True
|
||||
|
||||
|
||||
def test_find_module_not_package():
|
||||
file, path, is_package = find_module('io')
|
||||
assert file is not None
|
||||
assert path.endswith('io.py')
|
||||
assert is_package is False
|
||||
|
||||
|
||||
def test_find_module_package_zipped():
|
||||
if 'zipped_imports/pkg.zip' not in sys.path:
|
||||
sys.path.append(os.path.join(os.path.dirname(__file__),
|
||||
'zipped_imports/pkg.zip'))
|
||||
file, path, is_package = find_module('pkg')
|
||||
assert file is not None
|
||||
assert path.endswith('pkg.zip')
|
||||
assert is_package is True
|
||||
assert len(jedi.Script('import pkg; pkg.mod', 1, 19).completions()) == 1
|
||||
|
||||
|
||||
@pytest.mark.skipif('sys.version_info < (2,7)')
|
||||
def test_find_module_not_package_zipped():
|
||||
if 'zipped_imports/not_pkg.zip' not in sys.path:
|
||||
sys.path.append(os.path.join(os.path.dirname(__file__),
|
||||
'zipped_imports/not_pkg.zip'))
|
||||
file, path, is_package = find_module('not_pkg')
|
||||
assert file is not None
|
||||
assert path.endswith('not_pkg.zip')
|
||||
assert is_package is False
|
||||
assert len(
|
||||
jedi.Script('import not_pkg; not_pkg.val', 1, 27).completions()) == 1
|
||||
|
||||
|
||||
@cwd_at('test/test_evaluate/not_in_sys_path/pkg')
|
||||
def test_import_not_in_sys_path():
|
||||
"""
|
||||
non-direct imports (not in sys.path)
|
||||
"""
|
||||
a = jedi.Script(path='module.py', line=5).goto_definitions()
|
||||
assert a[0].name == 'int'
|
||||
|
||||
a = jedi.Script(path='module.py', line=6).goto_definitions()
|
||||
assert a[0].name == 'str'
|
||||
a = jedi.Script(path='module.py', line=7).goto_definitions()
|
||||
assert a[0].name == 'str'
|
||||
|
||||
|
||||
@pytest.mark.parametrize("script,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.mark.xfail(("import flask.ext.foo; flask.ext.foo.", "Foo")),
|
||||
pytest.mark.xfail(("import flask.ext.bar; flask.ext.bar.", "Foo")),
|
||||
pytest.mark.xfail(("import flask.ext.baz; flask.ext.baz.", "Foo")),
|
||||
pytest.mark.xfail(("import flask.ext.moo; flask.ext.moo.", "Foo")),
|
||||
])
|
||||
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')
|
||||
completions = jedi.Script(script, sys_path=[path]).completions()
|
||||
assert name in [c.name for c in completions]
|
||||
|
||||
|
||||
@cwd_at('test/test_evaluate/')
|
||||
def test_not_importable_file():
|
||||
src = 'import not_importable_file as x; x.'
|
||||
assert not jedi.Script(src, path='example.py').completions()
|
||||
|
||||
|
||||
def test_import_unique():
|
||||
src = "import os; os.path"
|
||||
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]
|
||||
|
||||
|
||||
def test_import_completion_docstring():
|
||||
import abc
|
||||
s = jedi.Script('"""test"""\nimport ab')
|
||||
completions = s.completions()
|
||||
assert len(completions) == 1
|
||||
assert 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 completions[0].docstring() == ''
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
import jedi
|
||||
from os.path import dirname, join
|
||||
|
||||
|
||||
def test_namespace_package():
|
||||
sys_path = [join(dirname(__file__), d)
|
||||
for d in ['namespace_package/ns1', 'namespace_package/ns2']]
|
||||
|
||||
def script_with_path(*args, **kwargs):
|
||||
return jedi.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_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
|
||||
|
||||
# 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
|
||||
|
||||
|
||||
def test_nested_namespace_package():
|
||||
CODE = 'from nested_namespaces.namespace.pkg import CONST'
|
||||
|
||||
sys_path = [dirname(__file__)]
|
||||
|
||||
script = jedi.Script(sys_path=sys_path, source=CODE, line=1, column=45)
|
||||
|
||||
result = script.goto_definitions()
|
||||
|
||||
assert len(result) == 1
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
from jedi.parser import load_grammar, Parser
|
||||
from jedi.evaluate import Evaluator
|
||||
from jedi.evaluate.compiled import CompiledObject
|
||||
|
||||
import pytest
|
||||
|
||||
|
||||
@pytest.mark.skipif('sys.version_info[0] < 3') # Ellipsis does not exists in 2
|
||||
@pytest.mark.parametrize('source', [
|
||||
'1 == 1',
|
||||
'1.0 == 1',
|
||||
'... == ...'
|
||||
])
|
||||
def test_equals(source):
|
||||
evaluator = Evaluator(load_grammar())
|
||||
node = Parser(load_grammar(), source, 'eval_input').get_parsed_node()
|
||||
results = evaluator.eval_element(node)
|
||||
assert len(results) == 1
|
||||
first = results.pop()
|
||||
assert isinstance(first, CompiledObject) and first.obj is True
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
"""
|
||||
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 ..helpers import cwd_at
|
||||
|
||||
|
||||
SRC = """class Foo:
|
||||
pass
|
||||
|
||||
class Bar:
|
||||
pass
|
||||
"""
|
||||
|
||||
|
||||
def generate_pyc():
|
||||
os.mkdir("dummy_package")
|
||||
with open("dummy_package/__init__.py", 'w'):
|
||||
pass
|
||||
with open("dummy_package/dummy.py", 'w') as f:
|
||||
f.write(SRC)
|
||||
import compileall
|
||||
compileall.compile_file("dummy_package/dummy.py")
|
||||
os.remove("dummy_package/dummy.py")
|
||||
|
||||
if sys.version_info[0] == 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
|
||||
for f in os.listdir("dummy_package/__pycache__"):
|
||||
dst = f.replace('.cpython-%s%s' % sys.version_info[:2], "")
|
||||
dst = os.path.join("dummy_package", dst)
|
||||
shutil.copy(os.path.join("dummy_package/__pycache__", f), dst)
|
||||
|
||||
|
||||
# Python 2.6 does not necessarily come with `compileall.compile_file`.
|
||||
@pytest.mark.skipif("sys.version_info > (2,6)")
|
||||
@cwd_at('test/test_evaluate')
|
||||
def test_pyc():
|
||||
"""
|
||||
The list of completion must be greater than 2.
|
||||
"""
|
||||
try:
|
||||
generate_pyc()
|
||||
s = jedi.Script("from dummy_package import dummy; dummy.", path='blub.py')
|
||||
assert len(s.completions()) >= 2
|
||||
finally:
|
||||
shutil.rmtree("dummy_package")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
test_pyc()
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
from textwrap import dedent
|
||||
|
||||
from jedi import Script
|
||||
|
||||
|
||||
def get_definition_and_evaluator(source):
|
||||
d = Script(dedent(source)).goto_definitions()[0]
|
||||
return d._name.parent, d._evaluator
|
||||
|
||||
|
||||
def test_function_execution():
|
||||
"""
|
||||
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(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(evaluator.execute(func)) == 1
|
||||
assert len(evaluator.execute(func)) == 1
|
||||
|
||||
|
||||
def test_class_mro():
|
||||
s = """
|
||||
class X(object):
|
||||
pass
|
||||
X"""
|
||||
cls, evaluator = get_definition_and_evaluator(s)
|
||||
mro = cls.py__mro__()
|
||||
assert [str(c.name) for c in mro] == ['X', 'object']
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
import os
|
||||
from glob import glob
|
||||
import sys
|
||||
|
||||
import pytest
|
||||
|
||||
from jedi._compatibility import unicode
|
||||
from jedi.parser import ParserWithRecovery, load_grammar
|
||||
from jedi.evaluate import sys_path, Evaluator
|
||||
|
||||
|
||||
def test_paths_from_assignment():
|
||||
def paths(src):
|
||||
grammar = load_grammar()
|
||||
stmt = ParserWithRecovery(grammar, unicode(src)).module.statements[0]
|
||||
return set(sys_path._paths_from_assignment(Evaluator(grammar), stmt))
|
||||
|
||||
assert paths('sys.path[0:0] = ["a"]') == set(['a'])
|
||||
assert paths('sys.path = ["b", 1, x + 3, y, "c"]') == set(['b', 'c'])
|
||||
assert paths('sys.path = a = ["a"]') == set(['a'])
|
||||
|
||||
# Fail for complicated examples.
|
||||
assert paths('sys.path, other = ["a"], 2') == set()
|
||||
|
||||
|
||||
# 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])))
|
||||
|
||||
|
||||
@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 = [
|
||||
pjoin('/path', 'from', 'egg-link'),
|
||||
pjoin(site_pkgs, '.', 'relative', 'egg-link', 'path'),
|
||||
site_pkgs,
|
||||
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
|
||||
Binary file not shown.
Binary file not shown.
Loading…
Add table
Add a link
Reference in a new issue