forked from VimPlug/jedi
Merge branch 'dev' of git://github.com/davidhalter/jedi
This commit is contained in:
@@ -94,6 +94,28 @@ a4
|
||||
b4
|
||||
|
||||
|
||||
# -----------------
|
||||
# multiple assignments
|
||||
# -----------------
|
||||
a = b = 1
|
||||
#? int()
|
||||
a
|
||||
#? int()
|
||||
b
|
||||
|
||||
(a, b) = (c, (e, f)) = ('2', (3, 4))
|
||||
#? str()
|
||||
a
|
||||
#? tuple()
|
||||
b
|
||||
#? str()
|
||||
c
|
||||
#? int()
|
||||
e
|
||||
#? int()
|
||||
f
|
||||
|
||||
|
||||
# -----------------
|
||||
# unnessecary braces
|
||||
# -----------------
|
||||
|
||||
@@ -3,7 +3,13 @@ import textwrap
|
||||
import pytest
|
||||
|
||||
from jedi import api
|
||||
import jedi
|
||||
|
||||
def test_is_keyword():
|
||||
results = jedi.Script('import ', 1, 1, None).goto_definitions()
|
||||
assert len(results) == 1 and results[0].is_keyword == True
|
||||
results = jedi.Script('str', 1, 1, None).goto_definitions()
|
||||
assert len(results) == 1 and results[0].is_keyword == False
|
||||
|
||||
def make_definitions():
|
||||
"""
|
||||
|
||||
75
test/test_defined_names.py
Normal file
75
test/test_defined_names.py
Normal file
@@ -0,0 +1,75 @@
|
||||
"""
|
||||
Tests for `api.defined_names`.
|
||||
"""
|
||||
|
||||
import textwrap
|
||||
|
||||
from jedi import api
|
||||
from .base import TestBase
|
||||
|
||||
|
||||
class TestDefinedNames(TestBase):
|
||||
|
||||
def assert_definition_names(self, definitions, names):
|
||||
self.assertEqual([d.name for d in definitions], names)
|
||||
|
||||
def check_defined_names(self, source, names):
|
||||
definitions = api.defined_names(textwrap.dedent(source))
|
||||
self.assert_definition_names(definitions, names)
|
||||
return definitions
|
||||
|
||||
def test_get_definitions_flat(self):
|
||||
self.check_defined_names("""
|
||||
import module
|
||||
class Class:
|
||||
pass
|
||||
def func():
|
||||
pass
|
||||
data = None
|
||||
""", ['module', 'Class', 'func', 'data'])
|
||||
|
||||
def test_dotted_assignment(self):
|
||||
self.check_defined_names("""
|
||||
x = Class()
|
||||
x.y.z = None
|
||||
""", ['x'])
|
||||
|
||||
def test_multiple_assignment(self):
|
||||
self.check_defined_names("""
|
||||
x = y = None
|
||||
""", ['x', 'y'])
|
||||
|
||||
def test_multiple_imports(self):
|
||||
self.check_defined_names("""
|
||||
from module import a, b
|
||||
from another_module import *
|
||||
""", ['a', 'b'])
|
||||
|
||||
def test_nested_definitions(self):
|
||||
definitions = self.check_defined_names("""
|
||||
class Class:
|
||||
def f():
|
||||
pass
|
||||
def g():
|
||||
pass
|
||||
""", ['Class'])
|
||||
subdefinitions = definitions[0].defined_names()
|
||||
self.assert_definition_names(subdefinitions, ['f', 'g'])
|
||||
self.assertEqual([d.full_name for d in subdefinitions],
|
||||
['Class.f', 'Class.g'])
|
||||
|
||||
def test_nested_class(self):
|
||||
definitions = self.check_defined_names("""
|
||||
class L1:
|
||||
class L2:
|
||||
class L3:
|
||||
def f(): pass
|
||||
def f(): pass
|
||||
def f(): pass
|
||||
def f(): pass
|
||||
""", ['L1', 'f'])
|
||||
subdefs = definitions[0].defined_names()
|
||||
subsubdefs = subdefs[0].defined_names()
|
||||
self.assert_definition_names(subdefs, ['L2', 'f'])
|
||||
self.assert_definition_names(subsubdefs, ['L3', 'f'])
|
||||
self.assert_definition_names(subsubdefs[0].defined_names(), ['f'])
|
||||
93
test/test_full_name.py
Normal file
93
test/test_full_name.py
Normal file
@@ -0,0 +1,93 @@
|
||||
"""
|
||||
Tests for :attr:`.BaseDefinition.full_name`.
|
||||
|
||||
There are three kinds of test:
|
||||
|
||||
#. Test classes derived from :class:`MixinTestFullName`.
|
||||
Child class defines :meth:`.get_definitions` to alter how
|
||||
the api definition instance is created.
|
||||
|
||||
#. :class:`TestFullDefinedName` is to test combination of
|
||||
:attr:`.full_name` and :func:`.defined_names`.
|
||||
|
||||
#. Misc single-function tests.
|
||||
|
||||
"""
|
||||
|
||||
import textwrap
|
||||
|
||||
import jedi
|
||||
from jedi import api_classes
|
||||
from .base import TestBase
|
||||
|
||||
|
||||
class MixinTestFullName(object):
|
||||
|
||||
def get_definitions(self, source):
|
||||
"""
|
||||
Get definition objects of the variable at the end of `source`.
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def check(self, source, desired):
|
||||
definitions = self.get_definitions(textwrap.dedent(source))
|
||||
self.assertEqual(definitions[0].full_name, desired)
|
||||
|
||||
def test_os_path_join(self):
|
||||
self.check('import os; os.path.join', 'os.path.join')
|
||||
|
||||
def test_builtin(self):
|
||||
self.check('type', 'type')
|
||||
|
||||
def test_from_import(self):
|
||||
self.check('from os import path', 'os.path')
|
||||
|
||||
|
||||
class TestFullNameWithGotoDefinitions(MixinTestFullName, TestBase):
|
||||
|
||||
get_definitions = TestBase.goto_definitions
|
||||
|
||||
def test_tuple_mapping(self):
|
||||
self.check("""
|
||||
import re
|
||||
any_re = re.compile('.*')
|
||||
any_re""", 're.RegexObject')
|
||||
|
||||
|
||||
class TestFullNameWithCompletions(MixinTestFullName, TestBase):
|
||||
get_definitions = TestBase.completions
|
||||
|
||||
|
||||
class TestFullDefinedName(TestBase):
|
||||
|
||||
"""
|
||||
Test combination of :attr:`.full_name` and :func:`.defined_names`.
|
||||
"""
|
||||
|
||||
def check(self, source, desired):
|
||||
definitions = jedi.defined_names(textwrap.dedent(source))
|
||||
full_names = [d.full_name for d in definitions]
|
||||
self.assertEqual(full_names, desired)
|
||||
|
||||
def test_local_names(self):
|
||||
self.check("""
|
||||
def f(): pass
|
||||
class C: pass
|
||||
""", ['f', 'C'])
|
||||
|
||||
def test_imports(self):
|
||||
self.check("""
|
||||
import os
|
||||
from os import path
|
||||
from os.path import join
|
||||
from os import path as opath
|
||||
""", ['os', 'os.path', 'os.path.join', 'os.path'])
|
||||
|
||||
|
||||
def test_keyword_full_name_should_be_none():
|
||||
"""issue #94"""
|
||||
# Using `from jedi.keywords import Keyword` here does NOT work
|
||||
# in Python 3. This is due to the import hack jedi using.
|
||||
Keyword = api_classes.keywords.Keyword
|
||||
d = api_classes.Definition(Keyword('(', (0, 0)))
|
||||
assert d.full_name is None
|
||||
@@ -14,9 +14,8 @@ import textwrap
|
||||
from .base import TestBase, unittest, cwd_at
|
||||
|
||||
import jedi
|
||||
from jedi._compatibility import utf8, unicode
|
||||
from jedi._compatibility import utf8, unicode, is_py33
|
||||
from jedi import api, parsing, common
|
||||
api_classes = api.api_classes
|
||||
|
||||
#jedi.set_debug_function(jedi.debug.print_to_stdout)
|
||||
|
||||
@@ -314,14 +313,29 @@ class TestRegression(TestBase):
|
||||
types = [o.type for o in objs]
|
||||
assert 'import' not in types and 'class' in types
|
||||
|
||||
def test_keyword_definition_doc(self):
|
||||
def test_keyword(self):
|
||||
""" github jedi-vim issue #44 """
|
||||
defs = self.goto_definitions("print")
|
||||
assert [d.doc for d in defs]
|
||||
|
||||
defs = self.goto_definitions("import")
|
||||
assert len(defs) == 1
|
||||
assert [d.doc for d in defs]
|
||||
assert len(defs) == 1 and [1 for d in defs if d.doc]
|
||||
# unrelated to #44
|
||||
defs = self.goto_assignments("import")
|
||||
assert len(defs) == 0
|
||||
completions = self.completions("import", (1,1))
|
||||
assert len(completions) == 0
|
||||
with common.ignored(jedi.NotFoundError): # TODO shouldn't throw that.
|
||||
defs = self.goto_definitions("assert")
|
||||
assert len(defs) == 1
|
||||
|
||||
def test_goto_assignments_keyword(self):
|
||||
"""
|
||||
Bug: goto assignments on ``in`` used to raise AttributeError::
|
||||
|
||||
'unicode' object has no attribute 'generate_call_path'
|
||||
"""
|
||||
self.goto_assignments('in')
|
||||
|
||||
def test_goto_following_on_imports(self):
|
||||
s = "import multiprocessing.dummy; multiprocessing.dummy"
|
||||
@@ -377,10 +391,47 @@ class TestRegression(TestBase):
|
||||
# jedi issue #150
|
||||
s = "x()\nx( )\nx( )\nx ( )"
|
||||
parser = parsing.Parser(s)
|
||||
for i, s in enumerate(parser.scope.statements, 3):
|
||||
for i, s in enumerate(parser.module.statements, 3):
|
||||
for c in s.get_commands():
|
||||
self.assertEqual(c.execution.end_pos[1], i)
|
||||
|
||||
def check_definition_by_marker(self, source, after_cursor, names):
|
||||
r"""
|
||||
Find definitions specified by `after_cursor` and check what found
|
||||
|
||||
For example, for the following configuration, you can pass
|
||||
``after_cursor = 'y)'``.::
|
||||
|
||||
function(
|
||||
x, y)
|
||||
\
|
||||
`- You want cursor to be here
|
||||
"""
|
||||
source = textwrap.dedent(source)
|
||||
for (i, line) in enumerate(source.splitlines()):
|
||||
if after_cursor in line:
|
||||
break
|
||||
column = len(line) - len(after_cursor)
|
||||
defs = self.goto_definitions(source, (i + 1, column))
|
||||
self.assertEqual([d.name for d in defs], names)
|
||||
|
||||
def test_backslash_continuation(self):
|
||||
"""
|
||||
Test that ModuleWithCursor.get_path_until_cursor handles continuation
|
||||
"""
|
||||
self.check_definition_by_marker(r"""
|
||||
x = 0
|
||||
a = \
|
||||
[1, 2, 3, 4, 5, 6, 7, 8, 9, x] # <-- here
|
||||
""", '] # <-- here', ['int'])
|
||||
|
||||
def test_backslash_continuation_and_bracket(self):
|
||||
self.check_definition_by_marker(r"""
|
||||
x = 0
|
||||
a = \
|
||||
[1, 2, 3, 4, 5, 6, 7, 8, 9, (x)] # <-- here
|
||||
""", '(x)] # <-- here', [None])
|
||||
|
||||
|
||||
class TestDocstring(TestBase):
|
||||
|
||||
@@ -410,28 +461,6 @@ class TestDocstring(TestBase):
|
||||
|
||||
|
||||
class TestFeature(TestBase):
|
||||
def test_full_name(self):
|
||||
""" feature request #61"""
|
||||
assert self.completions('import os; os.path.join')[0].full_name \
|
||||
== 'os.path.join'
|
||||
|
||||
def test_keyword_full_name_should_be_none(self):
|
||||
"""issue #94"""
|
||||
# Using `from jedi.keywords import Keyword` here does NOT work
|
||||
# in Python 3. This is due to the import hack jedi using.
|
||||
Keyword = api_classes.keywords.Keyword
|
||||
d = api_classes.Definition(Keyword('(', (0, 0)))
|
||||
assert d.full_name is None
|
||||
|
||||
def test_full_name_builtin(self):
|
||||
self.assertEqual(self.completions('type')[0].full_name, 'type')
|
||||
|
||||
def test_full_name_tuple_mapping(self):
|
||||
s = """
|
||||
import re
|
||||
any_re = re.compile('.*')
|
||||
any_re"""
|
||||
self.assertEqual(self.goto_definitions(s)[0].full_name, 're.RegexObject')
|
||||
|
||||
def test_preload_modules(self):
|
||||
def check_loaded(*modules):
|
||||
@@ -453,81 +482,6 @@ class TestFeature(TestBase):
|
||||
|
||||
cache.parser_cache = temp_cache
|
||||
|
||||
def test_quick_completion(self):
|
||||
sources = [
|
||||
('import json; json.l', (1, 19)),
|
||||
('import json; json.l ', (1, 19)),
|
||||
('import json\njson.l', (2, 6)),
|
||||
('import json\njson.l ', (2, 6)),
|
||||
('import json\njson.l\n\n', (2, 6)),
|
||||
('import json\njson.l \n\n', (2, 6)),
|
||||
('import json\njson.l \n \n\n', (2, 6)),
|
||||
]
|
||||
for source, pos in sources:
|
||||
# Run quick_complete
|
||||
quick_completions = api._quick_complete(source)
|
||||
# Run real completion
|
||||
script = jedi.Script(source, pos[0], pos[1], '')
|
||||
real_completions = script.completions()
|
||||
# Compare results
|
||||
quick_values = [(c.full_name, c.line, c.column) for c in quick_completions]
|
||||
real_values = [(c.full_name, c.line, c.column) for c in real_completions]
|
||||
self.assertEqual(quick_values, real_values)
|
||||
|
||||
|
||||
class TestGetDefinitions(TestBase):
|
||||
|
||||
def test_get_definitions_flat(self):
|
||||
definitions = api.defined_names("""
|
||||
import module
|
||||
class Class:
|
||||
pass
|
||||
def func():
|
||||
pass
|
||||
data = None
|
||||
""")
|
||||
self.assertEqual([d.name for d in definitions],
|
||||
['module', 'Class', 'func', 'data'])
|
||||
|
||||
def test_dotted_assignment(self):
|
||||
definitions = api.defined_names("""
|
||||
x = Class()
|
||||
x.y.z = None
|
||||
""")
|
||||
self.assertEqual([d.name for d in definitions],
|
||||
['x'])
|
||||
|
||||
def test_multiple_assignment(self):
|
||||
definitions = api.defined_names("""
|
||||
x = y = None
|
||||
""")
|
||||
self.assertEqual([d.name for d in definitions],
|
||||
['x', 'y'])
|
||||
|
||||
def test_multiple_imports(self):
|
||||
definitions = api.defined_names("""
|
||||
from module import a, b
|
||||
from another_module import *
|
||||
""")
|
||||
self.assertEqual([d.name for d in definitions],
|
||||
['a', 'b'])
|
||||
|
||||
def test_nested_definitions(self):
|
||||
definitions = api.defined_names("""
|
||||
class Class:
|
||||
def f():
|
||||
pass
|
||||
def g():
|
||||
pass
|
||||
""")
|
||||
self.assertEqual([d.name for d in definitions],
|
||||
['Class'])
|
||||
subdefinitions = definitions[0].defined_names()
|
||||
self.assertEqual([d.name for d in subdefinitions],
|
||||
['f', 'g'])
|
||||
self.assertEqual([d.full_name for d in subdefinitions],
|
||||
['Class.f', 'Class.g'])
|
||||
|
||||
|
||||
class TestSpeed(TestBase):
|
||||
def _check_speed(time_per_run, number=4, run_warm=True):
|
||||
@@ -562,6 +516,44 @@ class TestSpeed(TestBase):
|
||||
#print(jedi.imports.imports_processed)
|
||||
|
||||
|
||||
class TestInterpreterAPI(unittest.TestCase):
|
||||
|
||||
def check_interpreter_complete(self, source, namespace, completions,
|
||||
**kwds):
|
||||
script = api.Interpreter(source, [namespace], **kwds)
|
||||
cs = script.complete()
|
||||
actual = [c.word for c in cs]
|
||||
self.assertEqual(sorted(actual), sorted(completions))
|
||||
|
||||
def test_complete_raw_function(self):
|
||||
from os.path import join
|
||||
self.check_interpreter_complete('join().up',
|
||||
locals(),
|
||||
['upper'])
|
||||
|
||||
def test_complete_raw_function_different_name(self):
|
||||
from os.path import join as pjoin
|
||||
self.check_interpreter_complete('pjoin().up',
|
||||
locals(),
|
||||
['upper'])
|
||||
|
||||
def test_complete_raw_module(self):
|
||||
import os
|
||||
self.check_interpreter_complete('os.path.join().up',
|
||||
locals(),
|
||||
['upper'])
|
||||
|
||||
def test_complete_raw_instance(self):
|
||||
import datetime
|
||||
dt = datetime.datetime(2013, 1, 1)
|
||||
completions = ['time', 'timetz', 'timetuple']
|
||||
if is_py33:
|
||||
completions += ['timestamp']
|
||||
self.check_interpreter_complete('(dt - dt).ti',
|
||||
locals(),
|
||||
completions)
|
||||
|
||||
|
||||
def test_settings_module():
|
||||
"""
|
||||
jedi.settings and jedi.cache.settings must be the same module.
|
||||
|
||||
Reference in New Issue
Block a user