Merge branch 'api', fixes #1166

This commit is contained in:
Dave Halter committed 2019-12-20 20:05:10 +01:00
commit 66a36c3b94
74 files changed
+859 -779

No files matched your search

+7 -2
View File
@@ -3,10 +3,15 @@
Changelog Changelog
--------- ---------
0.16.0 (2020--)
+++++++++++++++++++
- ``BaseDefinition.goto_assignments`` renamed to ``BaseDefinition.goto``
0.15.2 (2019-12-20) 0.15.2 (2019-12-20)
+++++++++++++++++++ +++++++++++++++++++
- Call signatures are now detected a lot better - Signatures are now detected a lot better
- Add fuzzy completions with ``Script(...).completions(fuzzy=True)`` - Add fuzzy completions with ``Script(...).completions(fuzzy=True)``
- Files bigger than one MB (about 20kLOC) get cropped to avoid getting - Files bigger than one MB (about 20kLOC) get cropped to avoid getting
stuck completely. stuck completely.
@@ -33,7 +38,7 @@ New APIs:
- ``Definition.get_signatures() -> List[Signature]``. Signatures are similar to - ``Definition.get_signatures() -> List[Signature]``. Signatures are similar to
``CallSignature``. ``Definition.params`` is therefore deprecated. ``CallSignature``. ``Definition.params`` is therefore deprecated.
- ``Signature.to_string()`` to format call signatures. - ``Signature.to_string()`` to format signatures.
- ``Signature.params -> List[ParamDefinition]``, ParamDefinition has the - ``Signature.params -> List[ParamDefinition]``, ParamDefinition has the
following additional attributes ``infer_default()``, ``infer_annotation()``, following additional attributes ``infer_default()``, ``infer_annotation()``,
``to_string()``, and ``kind``. ``to_string()``, and ``kind``.
+7 -6
View File
@@ -32,7 +32,7 @@ Jedi has a focus on autocompletion and goto functionality. Jedi is fast and is
very well tested. It understands Python and stubs on a deep level. very well tested. It understands Python and stubs on a deep level.
Jedi has support for different goto functions. It's possible to search for Jedi has support for different goto functions. It's possible to search for
usages and list names in a Python file to get information about them. references and list names in a Python file to get information about them.
Jedi uses a very simple API to connect with IDE's. There's a reference Jedi uses a very simple API to connect with IDE's. There's a reference
implementation as a `VIM-Plugin <https://github.com/davidhalter/jedi-vim>`_, implementation as a `VIM-Plugin <https://github.com/davidhalter/jedi-vim>`_,
@@ -128,9 +128,9 @@ Autocompletion / Goto / Pydoc
Please check the API for a good explanation. There are the following commands: Please check the API for a good explanation. There are the following commands:
- ``jedi.Script.goto_assignments`` - ``jedi.Script.goto``
- ``jedi.Script.completions`` - ``jedi.Script.complete``
- ``jedi.Script.usages`` - ``jedi.Script.find_references``
The returned objects are very powerful and really all you might need. The returned objects are very powerful and really all you might need.
@@ -149,8 +149,9 @@ This means that in Python you can enable tab completion in a `REPL
Static Analysis Static Analysis
------------------------ ------------------------
To do all forms of static analysis, please try to use ``jedi.names``. It will To do all forms of static analysis, please try to use
return a list of names that you can use to infer types and so on. ``jedi.Script(...).names``. It will return a list of names that you can use to
infer types and so on.
Refactoring Refactoring
+3 -3
View File
@@ -106,8 +106,8 @@ def Script(environment):
@pytest.fixture(scope='session') @pytest.fixture(scope='session')
def names(environment): def names(Script):
return partial(jedi.names, environment=environment) return lambda code, **kwargs: Script(code).names(**kwargs)
@pytest.fixture(scope='session') @pytest.fixture(scope='session')
@@ -118,7 +118,7 @@ def has_typing(environment):
return True return True
script = jedi.Script('import typing', environment=environment) script = jedi.Script('import typing', environment=environment)
return bool(script.goto_definitions()) return bool(script.infer())
@pytest.fixture(scope='session') @pytest.fixture(scope='session')
+16 -19
View File
@@ -29,9 +29,8 @@ API Documentation
The API consists of a few different parts: The API consists of a few different parts:
- The main starting points for completions/goto: :class:`.Script` and :class:`.Interpreter` - The main starting points for complete/goto: :class:`.Script` and :class:`.Interpreter`
- Helpful functions: :func:`.names`, :func:`.preload_module` and - Helpful functions: :func:`.preload_module` and :func:`.set_debug_function`
:func:`.set_debug_function`
- :ref:`API Result Classes <api-classes>` - :ref:`API Result Classes <api-classes>`
- :ref:`Python Versions/Virtualenv Support <environments>` with functions like - :ref:`Python Versions/Virtualenv Support <environments>` with functions like
:func:`.find_system_environments` and :func:`.find_virtualenvs` :func:`.find_system_environments` and :func:`.find_virtualenvs`
@@ -47,7 +46,6 @@ Static Analysis Interface
:members: :members:
.. autoclass:: jedi.Interpreter .. autoclass:: jedi.Interpreter
:members: :members:
.. autofunction:: jedi.names
.. autofunction:: jedi.preload_module .. autofunction:: jedi.preload_module
.. autofunction:: jedi.set_debug_function .. autofunction:: jedi.set_debug_function
@@ -76,10 +74,10 @@ Completions:
>>> import jedi >>> import jedi
>>> source = '''import json; json.l''' >>> source = '''import json; json.l'''
>>> script = jedi.Script(source, 1, 19, '') >>> script = jedi.Script(source, path='')
>>> script >>> script
<jedi.api.Script object at 0x2121b10> <jedi.api.Script object at 0x2121b10>
>>> completions = script.completions() >>> completions = script.complete(1, 19)
>>> completions >>> completions
[<Completion: load>, <Completion: loads>] [<Completion: load>, <Completion: loads>]
>>> completions[1] >>> completions[1]
@@ -102,15 +100,15 @@ Definitions / Goto:
... inception = my_list[2] ... inception = my_list[2]
... ...
... inception()''' ... inception()'''
>>> script = jedi.Script(source, 8, 1, '') >>> script = jedi.Script(source, path='')
>>> >>>
>>> script.goto_assignments() >>> script.goto(8, 1)
[<Definition inception=my_list[2]>] [<Definition inception=my_list[2]>]
>>> >>>
>>> script.goto_definitions() >>> script.infer(8, 1)
[<Definition def my_func>] [<Definition def my_func>]
Related names: References:
.. sourcecode:: python .. sourcecode:: python
@@ -120,13 +118,12 @@ Related names:
... x = 4 ... x = 4
... else: ... else:
... del x''' ... del x'''
>>> script = jedi.Script(source, 5, 8, '') >>> script = jedi.Script(source, '')
>>> rns = script.related_names() >>> rns = script.find_references(5, 8)
>>> rns >>> rns
[<RelatedName x@3,4>, <RelatedName x@1,0>] [<Definition full_name='__main__.x', description='x = 3'>,
>>> rns[0].start_pos <Definition full_name='__main__.x', description='x'>]
(3, 4) >>> rns[1].line
>>> rns[0].is_keyword 5
False >>> rns[0].column
>>> rns[0].text 8
'x'
+1 -1
View File
@@ -6,7 +6,7 @@ Features and Caveats
Jedi obviously supports autocompletion. It's also possible to get it working in Jedi obviously supports autocompletion. It's also possible to get it working in
(:ref:`your REPL (IPython, etc.) <repl-completion>`). (:ref:`your REPL (IPython, etc.) <repl-completion>`).
Static analysis is also possible by using the command ``jedi.names``. Static analysis is also possible by using ``jedi.Script(...).names``.
Jedi would in theory support refactoring, but we have never publicized it, Jedi would in theory support refactoring, but we have never publicized it,
because it's not production ready. If you're interested in helping out here, because it's not production ready. If you're interested in helping out here,
+4 -4
View File
@@ -4,7 +4,7 @@ Jedi has a focus on autocompletion and goto functionality. Jedi is fast and is
very well tested. It understands Python and stubs on a deep level. very well tested. It understands Python and stubs on a deep level.
Jedi has support for different goto functions. It's possible to search for Jedi has support for different goto functions. It's possible to search for
usages and list names in a Python file to get information about them. references and list names in a Python file to get information about them.
Jedi uses a very simple API to connect with IDE's. There's a reference Jedi uses a very simple API to connect with IDE's. There's a reference
implementation as a `VIM-Plugin <https://github.com/davidhalter/jedi-vim>`_, implementation as a `VIM-Plugin <https://github.com/davidhalter/jedi-vim>`_,
@@ -18,10 +18,10 @@ Here's a simple example of the autocompletion feature:
>>> source = ''' >>> source = '''
... import json ... import json
... json.lo''' ... json.lo'''
>>> script = jedi.Script(source, 3, len('json.lo'), 'example.py') >>> script = jedi.Script(source, path='example.py')
>>> script >>> script
<Script: 'example.py' ...> <Script: 'example.py' ...>
>>> completions = script.completions() >>> completions = script.complete(3, len('json.lo'))
>>> completions >>> completions
[<Completion: load>, <Completion: loads>] [<Completion: load>, <Completion: loads>]
>>> print(completions[0].complete) >>> print(completions[0].complete)
@@ -33,7 +33,7 @@ As you see Jedi is pretty simple and allows you to concentrate on writing a
good text editor, while still having very good IDE features for Python. good text editor, while still having very good IDE features for Python.
""" """
__version__ = '0.15.2' __version__ = '0.16.0'
from jedi.api import Script, Interpreter, set_debug_function, \ from jedi.api import Script, Interpreter, set_debug_function, \
preload_module, names preload_module, names
+116 -92
View File
@@ -25,12 +25,13 @@ from jedi.file_io import KnownContentFileIO
from jedi.api import classes from jedi.api import classes
from jedi.api import interpreter from jedi.api import interpreter
from jedi.api import helpers from jedi.api import helpers
from jedi.api.helpers import validate_line_column
from jedi.api.completion import Completion from jedi.api.completion import Completion
from jedi.api.environment import InterpreterEnvironment from jedi.api.environment import InterpreterEnvironment
from jedi.api.project import get_default_project, Project from jedi.api.project import get_default_project, Project
from jedi.inference import InferenceState from jedi.inference import InferenceState
from jedi.inference import imports from jedi.inference import imports
from jedi.inference import usages from jedi.inference.references import find_references
from jedi.inference.arguments import try_iter_content from jedi.inference.arguments import try_iter_content
from jedi.inference.helpers import get_module_names, infer_call_of_leaf from jedi.inference.helpers import get_module_names, infer_call_of_leaf
from jedi.inference.sys_path import transform_path_to_dotted from jedi.inference.sys_path import transform_path_to_dotted
@@ -68,9 +69,9 @@ class Script(object):
:param source: The source code of the current file, separated by newlines. :param source: The source code of the current file, separated by newlines.
:type source: str :type source: str
:param line: The line to perform actions on (starting with 1). :param line: Deprecated, please use it directly on e.g. `.complete`
:type line: int :type line: int
:param column: The column of the cursor (starting with 0). :param column: Deprecated, please use it directly on e.g. `.complete`
:type column: int :type column: int
:param path: The path of the file in the file system, or ``''`` if :param path: The path of the file in the file system, or ``''`` if
it hasn't been saved yet. it hasn't been saved yet.
@@ -126,22 +127,6 @@ class Script(object):
debug.speed('parsed') debug.speed('parsed')
self._code_lines = parso.split_lines(source, keepends=True) self._code_lines = parso.split_lines(source, keepends=True)
self._code = source self._code = source
line = max(len(self._code_lines), 1) if line is None else line
if not (0 < line <= len(self._code_lines)):
raise ValueError('`line` parameter is not in a valid range.')
line_string = self._code_lines[line - 1]
line_len = len(line_string)
if line_string.endswith('\r\n'):
line_len -= 1
if line_string.endswith('\n'):
line_len -= 1
column = line_len if column is None else column
if not (0 <= column <= line_len):
raise ValueError('`column` parameter (%d) is not in a valid range '
'(0-%d) for line %d (%r).' % (
column, line_len, line, line_string))
self._pos = line, column self._pos = line, column
cache.clear_time_caches() cache.clear_time_caches()
@@ -201,27 +186,38 @@ class Script(object):
self._inference_state.environment, self._inference_state.environment,
) )
def completions(self, fuzzy=False): @validate_line_column
def complete(self, line=None, column=None, **kwargs):
""" """
Return :class:`classes.Completion` objects. Those objects contain Return :class:`classes.Completion` objects. Those objects contain
information about the completions, more than just names. information about the completions, more than just names.
:return: Completion objects, sorted by name and __ comes last. :param fuzzy: Default False. Will return fuzzy completions, which means
that e.g. ``ooa`` will match ``foobar``.
:return: Completion objects, sorted by name and ``__`` comes last.
:rtype: list of :class:`classes.Completion` :rtype: list of :class:`classes.Completion`
""" """
with debug.increase_indent_cm('completions'): return self._complete(line, column, **kwargs)
def _complete(self, line, column, fuzzy=False): # Python 2...
with debug.increase_indent_cm('complete'):
completion = Completion( completion = Completion(
self._inference_state, self._get_module_context(), self._code_lines, self._inference_state, self._get_module_context(), self._code_lines,
self._pos, self.call_signatures (line, column), self.find_signatures
) )
return completion.completions(fuzzy) return completion.complete(fuzzy)
def goto_definitions(self, **kwargs): def completions(self, fuzzy=False):
# Deprecated, will be removed.
return self.complete(*self._pos, fuzzy=fuzzy)
@validate_line_column
def infer(self, line=None, column=None, **kwargs):
""" """
Return the definitions of a the path under the cursor. goto function! Return the definitions of a the path under the cursor. goto function!
This follows complicated paths and returns the end, not the first This follows complicated paths and returns the end, not the first
definition. The big difference between :meth:`goto_assignments` and definition. The big difference between :meth:`goto` and
:meth:`goto_definitions` is that :meth:`goto_assignments` doesn't :meth:`infer` is that :meth:`goto` doesn't
follow imports and statements. Multiple objects may be returned, follow imports and statements. Multiple objects may be returned,
because Python itself is a dynamic language, which means depending on because Python itself is a dynamic language, which means depending on
an option you can have two different versions of a function. an option you can have two different versions of a function.
@@ -231,19 +227,24 @@ class Script(object):
inference call. inference call.
:rtype: list of :class:`classes.Definition` :rtype: list of :class:`classes.Definition`
""" """
with debug.increase_indent_cm('goto_definitions'): with debug.increase_indent_cm('infer'):
return self._goto_definitions(**kwargs) return self._infer(line, column, **kwargs)
def _goto_definitions(self, only_stubs=False, prefer_stubs=False): def goto_definitions(self, **kwargs):
leaf = self._module_node.get_name_of_position(self._pos) # Deprecated, will be removed.
return self.infer(*self._pos, **kwargs)
def _infer(self, line, column, only_stubs=False, prefer_stubs=False):
pos = line, column
leaf = self._module_node.get_name_of_position(pos)
if leaf is None: if leaf is None:
leaf = self._module_node.get_leaf_for_position(self._pos) leaf = self._module_node.get_leaf_for_position(pos)
if leaf is None or leaf.type == 'string': if leaf is None or leaf.type == 'string':
return [] return []
context = self._get_module_context().create_context(leaf) context = self._get_module_context().create_context(leaf)
values = helpers.infer_goto_definition(self._inference_state, context, leaf) values = helpers.infer(self._inference_state, context, leaf)
values = convert_values( values = convert_values(
values, values,
only_stubs=only_stubs, only_stubs=only_stubs,
@@ -257,6 +258,14 @@ class Script(object):
return helpers.sorted_definitions(set(defs)) return helpers.sorted_definitions(set(defs))
def goto_assignments(self, follow_imports=False, follow_builtin_imports=False, **kwargs): def goto_assignments(self, follow_imports=False, follow_builtin_imports=False, **kwargs):
# Deprecated, will be removed.
return self.goto(*self._pos,
follow_imports=follow_imports,
follow_builtin_imports=follow_builtin_imports,
**kwargs)
@validate_line_column
def goto(self, line=None, column=None, **kwargs):
""" """
Return the first definition found, while optionally following imports. Return the first definition found, while optionally following imports.
Multiple objects may be returned, because Python itself is a Multiple objects may be returned, because Python itself is a
@@ -273,11 +282,11 @@ class Script(object):
:param prefer_stubs: Prefer stubs to Python objects for this goto call. :param prefer_stubs: Prefer stubs to Python objects for this goto call.
:rtype: list of :class:`classes.Definition` :rtype: list of :class:`classes.Definition`
""" """
with debug.increase_indent_cm('goto_assignments'): with debug.increase_indent_cm('goto'):
return self._goto_assignments(follow_imports, follow_builtin_imports, **kwargs) return self._goto(line, column, **kwargs)
def _goto_assignments(self, follow_imports, follow_builtin_imports, def _goto(self, line, column, follow_imports=False, follow_builtin_imports=False,
only_stubs=False, prefer_stubs=False): only_stubs=False, prefer_stubs=False):
def filter_follow_imports(names): def filter_follow_imports(names):
for name in names: for name in names:
if name.is_import(): if name.is_import():
@@ -296,11 +305,11 @@ class Script(object):
else: else:
yield name yield name
tree_name = self._module_node.get_name_of_position(self._pos) tree_name = self._module_node.get_name_of_position((line, column))
if tree_name is None: if tree_name is None:
# Without a name we really just want to jump to the result e.g. # Without a name we really just want to jump to the result e.g.
# executed by `foo()`, if we the cursor is after `)`. # executed by `foo()`, if we the cursor is after `)`.
return self.goto_definitions(only_stubs=only_stubs, prefer_stubs=prefer_stubs) return self.infer(line, column, only_stubs=only_stubs, prefer_stubs=prefer_stubs)
name = self._get_module_context().create_name(tree_name) name = self._get_module_context().create_name(tree_name)
names = list(name.goto()) names = list(name.goto())
@@ -315,42 +324,43 @@ class Script(object):
defs = [classes.Definition(self._inference_state, d) for d in set(names)] defs = [classes.Definition(self._inference_state, d) for d in set(names)]
return helpers.sorted_definitions(defs) return helpers.sorted_definitions(defs)
def usages(self, additional_module_paths=(), **kwargs): def usages(self, **kwargs):
# Deprecated, will be removed.
return self.find_references(*self._pos, **kwargs)
@validate_line_column
def find_references(self, line=None, column=None, **kwargs):
""" """
Return :class:`classes.Definition` objects, which contain all Return :class:`classes.Definition` objects, which contain all
names that point to the definition of the name under the cursor. This names that point to the definition of the name under the cursor. This
is very useful for refactoring (renaming), or to show all usages of a is very useful for refactoring (renaming), or to show all references of
variable. a variable.
.. todo:: Implement additional_module_paths :param include_builtins: Default True, checks if a reference is a
builtin (e.g. ``sys``) and in that case does not return it.
:param additional_module_paths: Deprecated, never ever worked.
:param include_builtins: Default True, checks if a usage is a builtin
(e.g. ``sys``) and in that case does not return it.
:rtype: list of :class:`classes.Definition` :rtype: list of :class:`classes.Definition`
""" """
if additional_module_paths:
warnings.warn(
"Deprecated since version 0.12.0. This never even worked, just ignore it.",
DeprecationWarning,
stacklevel=2
)
def _usages(include_builtins=True): def _references(include_builtins=True):
tree_name = self._module_node.get_name_of_position(self._pos) tree_name = self._module_node.get_name_of_position((line, column))
if tree_name is None: if tree_name is None:
# Must be syntax # Must be syntax
return [] return []
names = usages.usages(self._get_module_context(), tree_name) names = find_references(self._get_module_context(), tree_name)
definitions = [classes.Definition(self._inference_state, n) for n in names] definitions = [classes.Definition(self._inference_state, n) for n in names]
if not include_builtins: if not include_builtins:
definitions = [d for d in definitions if not d.in_builtin_module()] definitions = [d for d in definitions if not d.in_builtin_module()]
return helpers.sorted_definitions(definitions) return helpers.sorted_definitions(definitions)
return _usages(**kwargs) return _references(**kwargs)
def call_signatures(self): def call_signatures(self):
# Deprecated, will be removed.
return self.find_signatures(*self._pos)
@validate_line_column
def find_signatures(self, line=None, column=None):
""" """
Return the function object of the call you're currently in. Return the function object of the call you're currently in.
@@ -364,25 +374,26 @@ class Script(object):
This would return an empty list.. This would return an empty list..
:rtype: list of :class:`classes.CallSignature` :rtype: list of :class:`classes.Signature`
""" """
call_details = helpers.get_call_signature_details(self._module_node, self._pos) pos = line, column
call_details = helpers.get_signature_details(self._module_node, pos)
if call_details is None: if call_details is None:
return [] return []
context = self._get_module_context().create_context(call_details.bracket_leaf) context = self._get_module_context().create_context(call_details.bracket_leaf)
definitions = helpers.cache_call_signatures( definitions = helpers.cache_signatures(
self._inference_state, self._inference_state,
context, context,
call_details.bracket_leaf, call_details.bracket_leaf,
self._code_lines, self._code_lines,
self._pos pos
) )
debug.speed('func_call followed') debug.speed('func_call followed')
# TODO here we use stubs instead of the actual values. We should use # TODO here we use stubs instead of the actual values. We should use
# the signatures from stubs, but the actual values, probably?! # the signatures from stubs, but the actual values, probably?!
return [classes.CallSignature(self._inference_state, signature, call_details) return [classes.Signature(self._inference_state, signature, call_details)
for signature in definitions.get_signatures()] for signature in definitions.get_signatures()]
def _analysis(self): def _analysis(self):
@@ -408,7 +419,7 @@ class Script(object):
unpack_tuple_to_dict(context, types, testlist) unpack_tuple_to_dict(context, types, testlist)
else: else:
if node.type == 'name': if node.type == 'name':
defs = self._inference_state.goto_definitions(context, node) defs = self._inference_state.infer(context, node)
else: else:
defs = infer_call_of_leaf(context, node) defs = infer_call_of_leaf(context, node)
try_iter_content(defs) try_iter_content(defs)
@@ -419,6 +430,36 @@ class Script(object):
finally: finally:
self._inference_state.is_analysis = False self._inference_state.is_analysis = False
def names(self, **kwargs):
"""
Returns a list of `Definition` objects, containing name parts.
This means you can call ``Definition.goto()`` and get the
reference of a name.
:param all_scopes: If True lists the names of all scopes instead of only
the module namespace.
:param definitions: If True lists the names that have been defined by a
class, function or a statement (``a = b`` returns ``a``).
:param references: If True lists all the names that are not listed by
``definitions=True``. E.g. ``a = b`` returns ``b``.
"""
return self._names(**kwargs) # Python 2...
def _names(self, all_scopes=False, definitions=True, references=False):
def def_ref_filter(_def):
is_def = _def._name.tree_name.is_definition()
return definitions and is_def or references and not is_def
# Set line/column to a random position, because they don't matter.
module_context = self._get_module_context()
defs = [
classes.Definition(
self._inference_state,
module_context.create_name(name)
) for name in get_module_names(self._module_node, all_scopes)
]
return sorted(filter(def_ref_filter, defs), key=lambda x: (x.line, x.column))
class Interpreter(Script): class Interpreter(Script):
""" """
@@ -432,7 +473,7 @@ class Interpreter(Script):
>>> from os.path import join >>> from os.path import join
>>> namespace = locals() >>> namespace = locals()
>>> script = Interpreter('join("").up', [namespace]) >>> script = Interpreter('join("").up', [namespace])
>>> print(script.completions()[0].name) >>> print(script.complete()[0].name)
upper upper
""" """
_allow_descriptor_getattr_default = True _allow_descriptor_getattr_default = True
@@ -484,34 +525,17 @@ class Interpreter(Script):
def names(source=None, path=None, encoding='utf-8', all_scopes=False, def names(source=None, path=None, encoding='utf-8', all_scopes=False,
definitions=True, references=False, environment=None): definitions=True, references=False, environment=None):
""" warnings.warn(
Returns a list of `Definition` objects, containing name parts. "Deprecated since version 0.16.0. Use Script(...).names instead.",
This means you can call ``Definition.goto_assignments()`` and get the DeprecationWarning,
reference of a name. stacklevel=2
The parameters are the same as in :py:class:`Script`, except or the )
following ones:
:param all_scopes: If True lists the names of all scopes instead of only return Script(source, path=path, encoding=encoding).names(
the module namespace. all_scopes=all_scopes,
:param definitions: If True lists the names that have been defined by a definitions=definitions,
class, function or a statement (``a = b`` returns ``a``). references=references,
:param references: If True lists all the names that are not listed by )
``definitions=True``. E.g. ``a = b`` returns ``b``.
"""
def def_ref_filter(_def):
is_def = _def._name.tree_name.is_definition()
return definitions and is_def or references and not is_def
# Set line/column to a random position, because they don't matter.
script = Script(source, line=1, column=0, path=path, encoding=encoding, environment=environment)
module_context = script._get_module_context()
defs = [
classes.Definition(
script._inference_state,
module_context.create_name(name)
) for name in get_module_names(script._module_node, all_scopes)
]
return sorted(filter(def_ref_filter, defs), key=lambda x: (x.line, x.column))
def preload_module(*modules): def preload_module(*modules):
@@ -523,7 +547,7 @@ def preload_module(*modules):
""" """
for m in modules: for m in modules:
s = "import %s as x; x." % m s = "import %s as x; x." % m
Script(s, 1, len(s), None).completions() Script(s, path=None).complete(1, len(s))
def set_debug_function(func_cb=debug.print_to_stdout, warnings=True, def set_debug_function(func_cb=debug.print_to_stdout, warnings=True,
+35 -24
View File
@@ -104,7 +104,7 @@ class BaseDefinition(object):
Here is an example of the value of this attribute. Let's consider Here is an example of the value of this attribute. Let's consider
the following source. As what is in ``variable`` is unambiguous the following source. As what is in ``variable`` is unambiguous
to Jedi, :meth:`jedi.Script.goto_definitions` should return a list of to Jedi, :meth:`jedi.Script.infer` should return a list of
definition for ``sys``, ``f``, ``C`` and ``x``. definition for ``sys``, ``f``, ``C`` and ``x``.
>>> from jedi._compatibility import no_unicode_pprint >>> from jedi._compatibility import no_unicode_pprint
@@ -127,7 +127,7 @@ class BaseDefinition(object):
... variable''' ... variable'''
>>> script = Script(source) >>> script = Script(source)
>>> defs = script.goto_definitions() >>> defs = script.infer()
Before showing what is in ``defs``, let's sort it by :attr:`line` Before showing what is in ``defs``, let's sort it by :attr:`line`
so that it is easy to relate the result to the source code. so that it is easy to relate the result to the source code.
@@ -177,7 +177,7 @@ class BaseDefinition(object):
>>> from jedi import Script >>> from jedi import Script
>>> source = 'import json' >>> source = 'import json'
>>> script = Script(source, path='example.py') >>> script = Script(source, path='example.py')
>>> d = script.goto_definitions()[0] >>> d = script.infer()[0]
>>> print(d.module_name) # doctest: +ELLIPSIS >>> print(d.module_name) # doctest: +ELLIPSIS
json json
""" """
@@ -217,18 +217,18 @@ class BaseDefinition(object):
... def f(a, b=1): ... def f(a, b=1):
... "Document for function f." ... "Document for function f."
... ''' ... '''
>>> script = Script(source, 1, len('def f'), 'example.py') >>> script = Script(source, path='example.py')
>>> doc = script.goto_definitions()[0].docstring() >>> doc = script.infer(1, len('def f'))[0].docstring()
>>> print(doc) >>> print(doc)
f(a, b=1) f(a, b=1)
<BLANKLINE> <BLANKLINE>
Document for function f. Document for function f.
Notice that useful extra information is added to the actual Notice that useful extra information is added to the actual
docstring. For function, it is call signature. If you need docstring. For function, it is signature. If you need
actual docstring, use ``raw=True`` instead. actual docstring, use ``raw=True`` instead.
>>> print(script.goto_definitions()[0].docstring(raw=True)) >>> print(script.infer(1, len('def f'))[0].docstring(raw=True))
Document for function f. Document for function f.
:param fast: Don't follow imports that are only one level deep like :param fast: Don't follow imports that are only one level deep like
@@ -259,8 +259,8 @@ class BaseDefinition(object):
>>> source = ''' >>> source = '''
... import os ... import os
... os.path.join''' ... os.path.join'''
>>> script = Script(source, 3, len('os.path.join'), 'example.py') >>> script = Script(source, path='example.py')
>>> print(script.goto_definitions()[0].full_name) >>> print(script.infer(3, len('os.path.join'))[0].full_name)
os.path.join os.path.join
Notice that it returns ``'os.path.join'`` instead of (for example) Notice that it returns ``'os.path.join'`` instead of (for example)
@@ -289,11 +289,19 @@ class BaseDefinition(object):
return self._name.get_root_context().is_stub() return self._name.get_root_context().is_stub()
def goto_assignments(self, **kwargs): # Python 2... def goto(self, **kwargs):
with debug.increase_indent_cm('goto for %s' % self._name): with debug.increase_indent_cm('goto for %s' % self._name):
return self._goto_assignments(**kwargs) return self._goto(**kwargs)
def _goto_assignments(self, only_stubs=False, prefer_stubs=False): def goto_assignments(self, **kwargs): # Python 2...
warnings.warn(
"Deprecated since version 0.16.0. Use .goto.",
DeprecationWarning,
stacklevel=2
)
return self.goto(**kwargs)
def _goto(self, only_stubs=False, prefer_stubs=False):
assert not (only_stubs and prefer_stubs) assert not (only_stubs and prefer_stubs)
if not self._name.is_value_name: if not self._name.is_value_name:
@@ -397,7 +405,10 @@ class BaseDefinition(object):
return ''.join(lines[start_index:index + after + 1]) return ''.join(lines[start_index:index + after + 1])
def get_signatures(self): def get_signatures(self):
return [Signature(self._inference_state, s) for s in self._name.infer().get_signatures()] return [
BaseSignature(self._inference_state, s)
for s in self._name.infer().get_signatures()
]
def execute(self): def execute(self):
return _values_to_definitions(self._name.infer().execute_with_values()) return _values_to_definitions(self._name.infer().execute_with_values())
@@ -405,7 +416,7 @@ class BaseDefinition(object):
class Completion(BaseDefinition): class Completion(BaseDefinition):
""" """
`Completion` objects are returned from :meth:`api.Script.completions`. They `Completion` objects are returned from :meth:`api.Script.complete`. They
provide additional information about a completion. provide additional information about a completion.
""" """
def __init__(self, inference_state, name, stack, like_name_length, is_fuzzy): def __init__(self, inference_state, name, stack, like_name_length, is_fuzzy):
@@ -514,8 +525,8 @@ class Completion(BaseDefinition):
class Definition(BaseDefinition): class Definition(BaseDefinition):
""" """
*Definition* objects are returned from :meth:`api.Script.goto_assignments` *Definition* objects are returned from :meth:`api.Script.goto`
or :meth:`api.Script.goto_definitions`. or :meth:`api.Script.infer`.
""" """
def __init__(self, inference_state, definition): def __init__(self, inference_state, definition):
super(Definition, self).__init__(inference_state, definition) super(Definition, self).__init__(inference_state, definition)
@@ -538,8 +549,8 @@ class Definition(BaseDefinition):
... pass ... pass
... ...
... variable = f if random.choice([0,1]) else C''' ... variable = f if random.choice([0,1]) else C'''
>>> script = Script(source, column=3) # line is maximum by default >>> script = Script(source) # line is maximum by default
>>> defs = script.goto_definitions() >>> defs = script.infer(column=3)
>>> defs = sorted(defs, key=lambda d: d.line) >>> defs = sorted(defs, key=lambda d: d.line)
>>> no_unicode_pprint(defs) # doctest: +NORMALIZE_WHITESPACE >>> no_unicode_pprint(defs) # doctest: +NORMALIZE_WHITESPACE
[<Definition full_name='__main__.f', description='def f'>, [<Definition full_name='__main__.f', description='def f'>,
@@ -620,14 +631,14 @@ class Definition(BaseDefinition):
return hash((self._name.start_pos, self.module_path, self.name, self._inference_state)) return hash((self._name.start_pos, self.module_path, self.name, self._inference_state))
class Signature(Definition): class BaseSignature(Definition):
""" """
`Signature` objects is the return value of `Script.function_definition`. `BaseSignature` objects is the return value of `Script.function_definition`.
It knows what functions you are currently in. e.g. `isinstance(` would It knows what functions you are currently in. e.g. `isinstance(` would
return the `isinstance` function. without `(` it would return nothing. return the `isinstance` function. without `(` it would return nothing.
""" """
def __init__(self, inference_state, signature): def __init__(self, inference_state, signature):
super(Signature, self).__init__(inference_state, signature.name) super(BaseSignature, self).__init__(inference_state, signature.name)
self._signature = signature self._signature = signature
@property @property
@@ -642,15 +653,15 @@ class Signature(Definition):
return self._signature.to_string() return self._signature.to_string()
class CallSignature(Signature): class Signature(BaseSignature):
""" """
`CallSignature` objects is the return value of `Script.call_signatures`. `Signature` objects is the return value of `Script.find_signatures`.
It knows what functions you are currently in. e.g. `isinstance(` would It knows what functions you are currently in. e.g. `isinstance(` would
return the `isinstance` function with its params. Without `(` it would return the `isinstance` function with its params. Without `(` it would
return nothing. return nothing.
""" """
def __init__(self, inference_state, signature, call_details): def __init__(self, inference_state, signature, call_details):
super(CallSignature, self).__init__(inference_state, signature) super(Signature, self).__init__(inference_state, signature)
self._call_details = call_details self._call_details = call_details
self._signature = signature self._signature = signature
+22 -25
View File
@@ -10,7 +10,7 @@ from jedi import settings
from jedi.api import classes from jedi.api import classes
from jedi.api import helpers from jedi.api import helpers
from jedi.api import keywords from jedi.api import keywords
from jedi.api.file_name import file_name_completions from jedi.api.file_name import complete_file_name
from jedi.inference import imports from jedi.inference import imports
from jedi.inference.helpers import infer_call_of_leaf, parse_dotted_names from jedi.inference.helpers import infer_call_of_leaf, parse_dotted_names
from jedi.inference.context import get_global_filters from jedi.inference.context import get_global_filters
@@ -18,9 +18,9 @@ from jedi.inference.gradual.conversion import convert_values
from jedi.parser_utils import cut_value_at_position from jedi.parser_utils import cut_value_at_position
def get_call_signature_param_names(call_signatures): def get_signature_param_names(signatures):
# add named params # add named params
for call_sig in call_signatures: for call_sig in signatures:
for p in call_sig.params: for p in call_sig.params:
# Allow protected access, because it's a public API. # Allow protected access, because it's a public API.
if p._name.get_kind() in (Parameter.POSITIONAL_OR_KEYWORD, if p._name.get_kind() in (Parameter.POSITIONAL_OR_KEYWORD,
@@ -74,7 +74,7 @@ def get_flow_scope_node(module_node, position):
class Completion: class Completion:
def __init__(self, inference_state, module_context, code_lines, position, def __init__(self, inference_state, module_context, code_lines, position,
call_signatures_callback, fuzzy=False): signatures_callback, fuzzy=False):
self._inference_state = inference_state self._inference_state = inference_state
self._module_context = module_context self._module_context = module_context
self._module_node = module_context.tree_node self._module_node = module_context.tree_node
@@ -86,27 +86,24 @@ class Completion:
# everything. We want the start of the name we're on. # everything. We want the start of the name we're on.
self._original_position = position self._original_position = position
self._position = position[0], position[1] - len(self._like_name) self._position = position[0], position[1] - len(self._like_name)
self._call_signatures_callback = call_signatures_callback self._signatures_callback = signatures_callback
self._fuzzy = fuzzy self._fuzzy = fuzzy
def completions(self, fuzzy=False, **kwargs): def complete(self, fuzzy):
return self._completions(fuzzy, **kwargs)
def _completions(self, fuzzy):
leaf = self._module_node.get_leaf_for_position(self._position, include_prefixes=True) leaf = self._module_node.get_leaf_for_position(self._position, include_prefixes=True)
string, start_leaf = _extract_string_while_in_string(leaf, self._position) string, start_leaf = _extract_string_while_in_string(leaf, self._position)
if string is not None: if string is not None:
completions = list(file_name_completions( completions = list(complete_file_name(
self._inference_state, self._module_context, start_leaf, string, self._inference_state, self._module_context, start_leaf, string,
self._like_name, self._call_signatures_callback, self._like_name, self._signatures_callback,
self._code_lines, self._original_position, self._code_lines, self._original_position,
fuzzy fuzzy
)) ))
if completions: if completions:
return completions return completions
completion_names = self._get_value_completions(leaf) completion_names = self._complete_python(leaf)
completions = filter_names(self._inference_state, completion_names, completions = filter_names(self._inference_state, completion_names,
self.stack, self._like_name, fuzzy) self.stack, self._like_name, fuzzy)
@@ -115,7 +112,7 @@ class Completion:
x.name.startswith('_'), x.name.startswith('_'),
x.name.lower())) x.name.lower()))
def _get_value_completions(self, leaf): def _complete_python(self, leaf):
""" """
Analyzes the value that a completion is made in and decides what to Analyzes the value that a completion is made in and decides what to
return. return.
@@ -145,7 +142,7 @@ class Completion:
return [] return []
# If we don't have a value, just use global completion. # If we don't have a value, just use global completion.
return self._global_completions() return self._complete_global_scope()
allowed_transitions = \ allowed_transitions = \
list(stack._allowed_transition_names_and_token_types()) list(stack._allowed_transition_names_and_token_types())
@@ -185,7 +182,7 @@ class Completion:
completion_names = [] completion_names = []
current_line = self._code_lines[self._position[0] - 1][:self._position[1]] current_line = self._code_lines[self._position[0] - 1][:self._position[1]]
if not current_line or current_line[-1] in ' \t.;': if not current_line or current_line[-1] in ' \t.;':
completion_names += self._get_keyword_completion_names(allowed_transitions) completion_names += self._complete_keywords(allowed_transitions)
if any(t in allowed_transitions for t in (PythonTokenTypes.NAME, if any(t in allowed_transitions for t in (PythonTokenTypes.NAME,
PythonTokenTypes.INDENT)): PythonTokenTypes.INDENT)):
@@ -203,7 +200,7 @@ class Completion:
if nodes and nodes[-1] in ('as', 'def', 'class'): if nodes and nodes[-1] in ('as', 'def', 'class'):
# No completions for ``with x as foo`` and ``import x as foo``. # No completions for ``with x as foo`` and ``import x as foo``.
# Also true for defining names as a class or function. # Also true for defining names as a class or function.
return list(self._get_class_value_completions(is_function=True)) return list(self._complete_inherited(is_function=True))
elif "import_stmt" in nonterminals: elif "import_stmt" in nonterminals:
level, names = parse_dotted_names(nodes, "import_from" in nonterminals) level, names = parse_dotted_names(nodes, "import_from" in nonterminals)
@@ -215,10 +212,10 @@ class Completion:
) )
elif nonterminals[-1] in ('trailer', 'dotted_name') and nodes[-1] == '.': elif nonterminals[-1] in ('trailer', 'dotted_name') and nodes[-1] == '.':
dot = self._module_node.get_leaf_for_position(self._position) dot = self._module_node.get_leaf_for_position(self._position)
completion_names += self._trailer_completions(dot.get_previous_leaf()) completion_names += self._complete_trailer(dot.get_previous_leaf())
else: else:
completion_names += self._global_completions() completion_names += self._complete_global_scope()
completion_names += self._get_class_value_completions(is_function=False) completion_names += self._complete_inherited(is_function=False)
# Apparently this looks like it's good enough to filter most cases # Apparently this looks like it's good enough to filter most cases
# so that signature completions don't randomly appear. # so that signature completions don't randomly appear.
@@ -229,17 +226,17 @@ class Completion:
# 3. Decorators are very primitive and have an optional `(` with # 3. Decorators are very primitive and have an optional `(` with
# optional arglist in them. # optional arglist in them.
if nodes[-1] in ['(', ','] and nonterminals[-1] in ('trailer', 'arglist', 'decorator'): if nodes[-1] in ['(', ','] and nonterminals[-1] in ('trailer', 'arglist', 'decorator'):
call_signatures = self._call_signatures_callback() signatures = self._signatures_callback(*self._position)
completion_names += get_call_signature_param_names(call_signatures) completion_names += get_signature_param_names(signatures)
return completion_names return completion_names
def _get_keyword_completion_names(self, allowed_transitions): def _complete_keywords(self, allowed_transitions):
for k in allowed_transitions: for k in allowed_transitions:
if isinstance(k, str) and k.isalpha(): if isinstance(k, str) and k.isalpha():
yield keywords.KeywordName(self._inference_state, k) yield keywords.KeywordName(self._inference_state, k)
def _global_completions(self): def _complete_global_scope(self):
context = get_user_context(self._module_context, self._position) context = get_user_context(self._module_context, self._position)
debug.dbg('global completion scope: %s', context) debug.dbg('global completion scope: %s', context)
flow_scope_node = get_flow_scope_node(self._module_node, self._position) flow_scope_node = get_flow_scope_node(self._module_node, self._position)
@@ -253,7 +250,7 @@ class Completion:
completion_names += filter.values() completion_names += filter.values()
return completion_names return completion_names
def _trailer_completions(self, previous_leaf): def _complete_trailer(self, previous_leaf):
user_value = get_user_context(self._module_context, self._position) user_value = get_user_context(self._module_context, self._position)
inferred_context = self._module_context.create_context(previous_leaf) inferred_context = self._module_context.create_context(previous_leaf)
values = infer_call_of_leaf(inferred_context, previous_leaf) values = infer_call_of_leaf(inferred_context, previous_leaf)
@@ -275,7 +272,7 @@ class Completion:
i = imports.Importer(self._inference_state, names, self._module_context, level) i = imports.Importer(self._inference_state, names, self._module_context, level)
return i.completion_names(self._inference_state, only_modules=only_modules) return i.completion_names(self._inference_state, only_modules=only_modules)
def _get_class_value_completions(self, is_function=True): def _complete_inherited(self, is_function=True):
""" """
Autocomplete inherited methods when overriding in child class. Autocomplete inherited methods when overriding in child class.
""" """
+3 -3
View File
@@ -8,8 +8,8 @@ from jedi.inference.helpers import get_str_or_none
from jedi.parser_utils import get_string_quote from jedi.parser_utils import get_string_quote
def file_name_completions(inference_state, module_context, start_leaf, string, def complete_file_name(inference_state, module_context, start_leaf, string,
like_name, call_signatures_callback, code_lines, position, fuzzy): like_name, signatures_callback, code_lines, position, fuzzy):
# First we want to find out what can actually be changed as a name. # First we want to find out what can actually be changed as a name.
like_name_length = len(os.path.basename(string) + like_name) like_name_length = len(os.path.basename(string) + like_name)
@@ -23,7 +23,7 @@ def file_name_completions(inference_state, module_context, start_leaf, string,
must_start_with = os.path.basename(string) + like_name must_start_with = os.path.basename(string) + like_name
string = os.path.dirname(string) string = os.path.dirname(string)
sigs = call_signatures_callback() sigs = signatures_callback(*position)
is_in_os_path_join = sigs and all(s.full_name == 'os.path.join' for s in sigs) is_in_os_path_join = sigs and all(s.full_name == 'os.path.join' for s in sigs)
if is_in_os_path_join: if is_in_os_path_join:
to_be_added = _add_os_path_join(module_context, start_leaf, sigs[0].bracket_start) to_be_added = _add_os_path_join(module_context, start_leaf, sigs[0].bracket_start)
+35 -13
View File
@@ -4,6 +4,7 @@ Helpers for the API
import re import re
from collections import namedtuple from collections import namedtuple
from textwrap import dedent from textwrap import dedent
from functools import wraps
from parso.python.parser import Parser from parso.python.parser import Parser
from parso.python import tree from parso.python import tree
@@ -13,7 +14,7 @@ from jedi.inference.base_value import NO_VALUES
from jedi.inference.syntax_tree import infer_atom from jedi.inference.syntax_tree import infer_atom
from jedi.inference.helpers import infer_call_of_leaf from jedi.inference.helpers import infer_call_of_leaf
from jedi.inference.compiled import get_string_value_set from jedi.inference.compiled import get_string_value_set
from jedi.cache import call_signature_time_cache from jedi.cache import signature_time_cache
CompletionParts = namedtuple('CompletionParts', ['path', 'has_dot', 'name']) CompletionParts = namedtuple('CompletionParts', ['path', 'has_dot', 'name'])
@@ -149,11 +150,9 @@ def get_stack_at_position(grammar, code_lines, leaf, pos):
) )
def infer_goto_definition(inference_state, context, leaf): def infer(inference_state, context, leaf):
if leaf.type == 'name': if leaf.type == 'name':
# In case of a name we can just use goto_definition which does all the return inference_state.infer(context, leaf)
# magic itself.
return inference_state.goto_definitions(context, leaf)
parent = leaf.parent parent = leaf.parent
definitions = NO_VALUES definitions = NO_VALUES
@@ -327,7 +326,7 @@ def _get_index_and_key(nodes, position):
return nodes_before.count(','), key_str return nodes_before.count(','), key_str
def _get_call_signature_details_from_error_node(node, additional_children, position): def _get_signature_details_from_error_node(node, additional_children, position):
for index, element in reversed(list(enumerate(node.children))): for index, element in reversed(list(enumerate(node.children))):
# `index > 0` means that it's a trailer and not an atom. # `index > 0` means that it's a trailer and not an atom.
if element == '(' and element.end_pos <= position and index > 0: if element == '(' and element.end_pos <= position and index > 0:
@@ -341,7 +340,7 @@ def _get_call_signature_details_from_error_node(node, additional_children, posit
return CallDetails(element, children + additional_children, position) return CallDetails(element, children + additional_children, position)
def get_call_signature_details(module, position): def get_signature_details(module, position):
leaf = module.get_leaf_for_position(position, include_prefixes=True) leaf = module.get_leaf_for_position(position, include_prefixes=True)
# It's easier to deal with the previous token than the next one in this # It's easier to deal with the previous token than the next one in this
# case. # case.
@@ -356,15 +355,15 @@ def get_call_signature_details(module, position):
node = leaf.parent node = leaf.parent
while node is not None: while node is not None:
if node.type in ('funcdef', 'classdef'): if node.type in ('funcdef', 'classdef'):
# Don't show call signatures if there's stuff before it that just # Don't show signatures if there's stuff before it that just
# makes it feel strange to have a call signature. # makes it feel strange to have a signature.
return None return None
additional_children = [] additional_children = []
for n in reversed(node.children): for n in reversed(node.children):
if n.start_pos < position: if n.start_pos < position:
if n.type == 'error_node': if n.type == 'error_node':
result = _get_call_signature_details_from_error_node( result = _get_signature_details_from_error_node(
n, additional_children, position n, additional_children, position
) )
if result is not None: if result is not None:
@@ -391,8 +390,8 @@ def get_call_signature_details(module, position):
return None return None
@call_signature_time_cache("call_signatures_validity") @signature_time_cache("call_signatures_validity")
def cache_call_signatures(inference_state, context, bracket_leaf, code_lines, user_pos): def cache_signatures(inference_state, context, bracket_leaf, code_lines, user_pos):
"""This function calculates the cache key.""" """This function calculates the cache key."""
line_index = user_pos[0] - 1 line_index = user_pos[0] - 1
@@ -406,8 +405,31 @@ def cache_call_signatures(inference_state, context, bracket_leaf, code_lines, us
yield None # Don't cache! yield None # Don't cache!
else: else:
yield (module_path, before_bracket, bracket_leaf.start_pos) yield (module_path, before_bracket, bracket_leaf.start_pos)
yield infer_goto_definition( yield infer(
inference_state, inference_state,
context, context,
bracket_leaf.get_previous_leaf(), bracket_leaf.get_previous_leaf(),
) )
def validate_line_column(func):
@wraps(func)
def wrapper(self, line=None, column=None, *args, **kwargs):
line = max(len(self._code_lines), 1) if line is None else line
if not (0 < line <= len(self._code_lines)):
raise ValueError('`line` parameter is not in a valid range.')
line_string = self._code_lines[line - 1]
line_len = len(line_string)
if line_string.endswith('\r\n'):
line_len -= 1
if line_string.endswith('\n'):
line_len -= 1
column = line_len if column is None else column
if not (0 <= column <= line_len):
raise ValueError('`column` parameter (%d) is not in a valid range '
'(0-%d) for line %d (%r).' % (
column, line_len, line, line_string))
return func(self, line, column, *args, **kwargs)
return wrapper
+1 -1
View File
@@ -75,7 +75,7 @@ def clear_time_caches(delete_all=False):
del tc[key] del tc[key]
def call_signature_time_cache(time_add_setting): def signature_time_cache(time_add_setting):
""" """
This decorator works as follows: Call it with a setting and after that This decorator works as follows: Call it with a setting and after that
use the function with a callable that returns the key. use the function with a callable that returns the key.
+1 -1
View File
@@ -143,7 +143,7 @@ class InferenceState(object):
"""Convenience function""" """Convenience function"""
return self.project._get_sys_path(self, environment=self.environment, **kwargs) return self.project._get_sys_path(self, environment=self.environment, **kwargs)
def goto_definitions(self, context, name): def infer(self, context, name):
def_ = name.get_definition(import_name_always=True) def_ = name.get_definition(import_name_always=True)
if def_ is not None: if def_ is not None:
type_ = def_.type type_ = def_.type
+2 -2
View File
@@ -74,7 +74,7 @@ def dynamic_param_lookup(function_value, param_index):
path = function_value.get_root_context().py__file__() path = function_value.get_root_context().py__file__()
if path is not None and is_stdlib_path(path): if path is not None and is_stdlib_path(path):
# We don't want to search for usages in the stdlib. Usually people # We don't want to search for references in the stdlib. Usually people
# don't work with it (except if you are a core maintainer, sorry). # don't work with it (except if you are a core maintainer, sorry).
# This makes everything slower. Just disable it and run the tests, # This makes everything slower. Just disable it and run the tests,
# you will see the slowdown, especially in 3.6. # you will see the slowdown, especially in 3.6.
@@ -186,7 +186,7 @@ def _check_name_for_execution(inference_state, context, compare_node, name, trai
args = InstanceArguments(value.instance, args) args = InstanceArguments(value.instance, args)
return args return args
for value in inference_state.goto_definitions(context, name): for value in inference_state.infer(context, name):
value_node = value.tree_node value_node = value.tree_node
if compare_node == value_node: if compare_node == value_node:
yield create_args(value) yield create_args(value)
@@ -32,13 +32,13 @@ def _find_names(module_context, tree_name):
return _dictionarize(_resolve_names(found_names)) return _dictionarize(_resolve_names(found_names))
def usages(module_context, tree_name): def find_references(module_context, tree_name):
search_name = tree_name.value search_name = tree_name.value
found_names = _find_names(module_context, tree_name) found_names = _find_names(module_context, tree_name)
module_contexts = set(d.get_root_context() for d in found_names.values()) module_contexts = set(d.get_root_context() for d in found_names.values())
module_contexts = set(m for m in module_contexts if not m.is_compiled()) module_contexts = set(m for m in module_contexts if not m.is_compiled())
non_matching_usage_maps = {} non_matching_reference_maps = {}
inf = module_context.inference_state inf = module_context.inference_state
potential_modules = imports.get_module_contexts_containing_name( potential_modules = imports.get_module_contexts_containing_name(
inf, module_contexts, search_name inf, module_contexts, search_name
@@ -49,15 +49,15 @@ def usages(module_context, tree_name):
if any(tree_name in found_names for tree_name in new): if any(tree_name in found_names for tree_name in new):
found_names.update(new) found_names.update(new)
for tree_name in new: for tree_name in new:
for dct in non_matching_usage_maps.get(tree_name, []): for dct in non_matching_reference_maps.get(tree_name, []):
# A usage that was previously searched for matches with # A reference that was previously searched for matches
# a now found name. Merge. # with a now found name. Merge.
found_names.update(dct) found_names.update(dct)
try: try:
del non_matching_usage_maps[tree_name] del non_matching_reference_maps[tree_name]
except KeyError: except KeyError:
pass pass
else: else:
for name in new: for name in new:
non_matching_usage_maps.setdefault(name, []).append(new) non_matching_reference_maps.setdefault(name, []).append(new)
return found_names.values() return found_names.values()
+1 -1
View File
@@ -107,7 +107,7 @@ class TreeSignature(AbstractSignature):
for executed_param_name in executed_param_names) for executed_param_name in executed_param_names)
if debug.enable_notice: if debug.enable_notice:
tree_node = self._function_value.tree_node tree_node = self._function_value.tree_node
signature = parser_utils.get_call_signature(tree_node) signature = parser_utils.get_signature(tree_node)
if matches: if matches:
debug.dbg("Overloading match: %s@%s (%s)", debug.dbg("Overloading match: %s@%s (%s)",
signature, tree_node.start_pos[0], arguments, color='BLUE') signature, tree_node.start_pos[0], arguments, color='BLUE')
+1 -1
View File
@@ -108,7 +108,7 @@ def infer_node(context, element):
str_element_names = [e.value for e in element_names] str_element_names = [e.value for e in element_names]
if any(i.value in str_element_names for i in if_names): if any(i.value in str_element_names for i in if_names):
for if_name in if_names: for if_name in if_names:
definitions = context.inference_state.goto_definitions(context, if_name) definitions = context.inference_state.infer(context, if_name)
# Every name that has multiple different definitions # Every name that has multiple different definitions
# causes the complexity to rise. The complexity should # causes the complexity to rise. The complexity should
# never fall below 1. # never fall below 1.
+3 -3
View File
@@ -127,10 +127,10 @@ def safe_literal_eval(value):
return '' return ''
def get_call_signature(funcdef, width=72, call_string=None, def get_signature(funcdef, width=72, call_string=None,
omit_first_param=False, omit_return_annotation=False): omit_first_param=False, omit_return_annotation=False):
""" """
Generate call signature of this function. Generate a string signature of a function.
:param width: Fold lines if a line is longer than this value. :param width: Fold lines if a line is longer than this value.
:type width: int :type width: int
+4 -4
View File
@@ -57,7 +57,7 @@ def rename(script, new_name):
:param script: The source Script object. :param script: The source Script object.
:return: list of changed lines/changed files :return: list of changed lines/changed files
""" """
return Refactoring(_rename(script.usages(), new_name)) return Refactoring(_rename(script.find_references(), new_name))
def _rename(names, replace_str): def _rename(names, replace_str):
@@ -166,11 +166,11 @@ def inline(script):
dct = {} dct = {}
definitions = script.goto_assignments() definitions = script.goto()
assert len(definitions) == 1 assert len(definitions) == 1
stmt = definitions[0]._definition stmt = definitions[0]._definition
usages = script.usages() references = script.find_references()
inlines = [r for r in usages inlines = [r for r in references
if not stmt.start_pos <= (r.line, r.column) <= stmt.end_pos] if not stmt.start_pos <= (r.line, r.column) <= stmt.end_pos]
inlines = sorted(inlines, key=lambda x: (x.module_path, x.line, x.column), inlines = sorted(inlines, key=lambda x: (x.module_path, x.line, x.column),
reverse=True) reverse=True)
+1 -1
View File
@@ -83,7 +83,7 @@ def setup_readline(namespace_module=__main__, fuzzy=False):
logging.debug("Start REPL completion: " + repr(text)) logging.debug("Start REPL completion: " + repr(text))
interpreter = Interpreter(text, [namespace_module.__dict__]) interpreter = Interpreter(text, [namespace_module.__dict__])
completions = interpreter.completions(fuzzy=fuzzy) completions = interpreter.complete(fuzzy=fuzzy)
logging.debug("REPL completions: %s", completions) logging.debug("REPL completions: %s", completions)
self.matches = [ self.matches = [
+2 -2
View File
@@ -45,9 +45,9 @@ def run(code, index, infer=False):
start = time.time() start = time.time()
script = jedi.Script(code) script = jedi.Script(code)
if infer: if infer:
result = script.goto_definitions() result = script.infer()
else: else:
result = script.completions() result = script.complete()
print('Used %ss for the %sth run.' % (time.time() - start, index + 1)) print('Used %ss for the %sth run.' % (time.time() - start, index + 1))
return result return result
+1 -1
View File
@@ -45,7 +45,7 @@ def run():
print('Process Memory before: %skB' % process_memory()) print('Process Memory before: %skB' % process_memory())
# After this the module should be cached. # After this the module should be cached.
# Need to invent a path so that it's really cached. # Need to invent a path so that it's really cached.
jedi.Script(wx_core, path='foobar.py').completions() jedi.Script(wx_core, path='foobar.py').complete()
gc.collect() # make sure that it's all fair and the gc did its job. gc.collect() # make sure that it's all fair and the gc did its job.
print('Process Memory after: %skB' % process_memory()) print('Process Memory after: %skB' % process_memory())
+3 -5
View File
@@ -95,9 +95,7 @@ class TestCase(object):
args = json.load(f) args = json.load(f)
return cls(*args) return cls(*args)
operations = [ operations = ['complete', 'goto', 'infer', 'find_references', 'find_signatures']
'completions', 'goto_assignments', 'goto_definitions', 'usages',
'call_signatures']
@classmethod @classmethod
def generate(cls, file_path): def generate(cls, file_path):
@@ -123,12 +121,12 @@ class TestCase(object):
def run(self, debugger, record=None, print_result=False): def run(self, debugger, record=None, print_result=False):
try: try:
with open(self.path) as f: with open(self.path) as f:
self.script = jedi.Script(f.read(), self.line, self.column, self.path) self.script = jedi.Script(f.read(), path=self.path)
kwargs = {} kwargs = {}
if self.operation == 'goto_assignments': if self.operation == 'goto_assignments':
kwargs['follow_imports'] = random.choice([False, True]) kwargs['follow_imports'] = random.choice([False, True])
self.objects = getattr(self.script, self.operation)(**kwargs) self.objects = getattr(self.script, self.operation)(self.line, self.column, **kwargs)
if print_result: if print_result:
print("{path}: Line {line} column {column}".format(**self.__dict__)) print("{path}: Line {line} column {column}".format(**self.__dict__))
self.show_location(self.line, self.column) self.show_location(self.line, self.column)
+6 -6
View File
@@ -1,29 +1,29 @@
def test_keyword_doc(Script): def test_keyword_doc(Script):
r = list(Script("or", 1, 1).goto_definitions()) r = list(Script("or").infer(1, 1))
assert len(r) == 1 assert len(r) == 1
assert len(r[0].doc) > 100 assert len(r[0].doc) > 100
r = list(Script("asfdasfd", 1, 1).goto_definitions()) r = list(Script("asfdasfd").infer(1, 1))
assert len(r) == 0 assert len(r) == 0
k = Script("fro").completions()[0] k = Script("fro").complete()[0]
imp_start = '\nThe ``import' imp_start = '\nThe ``import'
assert k.raw_doc.startswith(imp_start) assert k.raw_doc.startswith(imp_start)
assert k.doc.startswith(imp_start) assert k.doc.startswith(imp_start)
def test_blablabla(Script): def test_blablabla(Script):
defs = Script("import").goto_definitions() defs = Script("import").infer()
assert len(defs) == 1 and [1 for d in defs if d.doc] assert len(defs) == 1 and [1 for d in defs if d.doc]
# unrelated to #44 # unrelated to #44
def test_operator_doc(Script): def test_operator_doc(Script):
r = list(Script("a == b", 1, 3).goto_definitions()) r = list(Script("a == b").infer(1, 3))
assert len(r) == 1 assert len(r) == 1
assert len(r[0].doc) > 100 assert len(r[0].doc) > 100
def test_lambda(Script): def test_lambda(Script):
defs = Script('lambda x: x', column=0).goto_definitions() defs = Script('lambda x: x').infer(column=0)
assert [d.type for d in defs] == ['keyword'] assert [d.type for d in defs] == ['keyword']
+1 -1
View File
@@ -1,4 +1,4 @@
# goto_assignments command tests are different in syntax # goto command tests are different in syntax
definition = 3 definition = 3
#! 0 ['a = definition'] #! 0 ['a = definition']
+1 -1
View File
@@ -1,7 +1,7 @@
from jedi import functions, inference, parsing from jedi import functions, inference, parsing
el = functions.completions()[0] el = functions.complete()[0]
#? ['description'] #? ['description']
el.description el.description
+1 -1
View File
@@ -1,5 +1,5 @@
""" """
Renaming tests. This means search for usages. Renaming tests. This means search for references.
I always leave a little bit of space to add room for additions, because the I always leave a little bit of space to add room for additions, because the
results always contain position informations. results always contain position informations.
""" """
+1 -1
View File
@@ -1,6 +1,6 @@
""" """
Test coverage for renaming is mostly being done by testing Test coverage for renaming is mostly being done by testing
`Script.usages`. `Script.find_references`.
""" """
# --- simple # --- simple
+34 -38
View File
@@ -10,9 +10,9 @@ tests.
There are different kind of tests: There are different kind of tests:
- completions / goto_definitions ``#?`` - completions / inference ``#?``
- goto_assignments: ``#!`` - goto: ``#!``
- usages: ``#<`` - references: ``#<``
How to run tests? How to run tests?
+++++++++++++++++ +++++++++++++++++
@@ -26,7 +26,7 @@ multiple Python versions.
Integration test cases are located in ``test/completion`` directory Integration test cases are located in ``test/completion`` directory
and each test case is indicated by either the comment ``#?`` (completions / and each test case is indicated by either the comment ``#?`` (completions /
definitions), ``#!`` (assignments), or ``#<`` (usages). inference), ``#!`` (goto), or ``#<`` (references).
There is also support for third party libraries. In a normal test run they are There is also support for third party libraries. In a normal test run they are
not being executed, you have to provide a ``--thirdparty`` option. not being executed, you have to provide a ``--thirdparty`` option.
@@ -76,17 +76,17 @@ For example::
Because it follows ``a.rea`` and a is an ``int``, which has a ``real`` Because it follows ``a.rea`` and a is an ``int``, which has a ``real``
property. property.
Goto Definitions Inference
++++++++++++++++ +++++++++
Definition tests use the same symbols like completion tests. This is Inference tests use the same symbols like completion tests. This is
possible because the completion tests are defined with a list:: possible because the completion tests are defined with a list::
#? int() #? int()
ab = 3; ab ab = 3; ab
Goto Assignments Goto
++++++++++++++++ ++++
Tests look like this:: Tests look like this::
@@ -100,8 +100,8 @@ describes the position of the test (otherwise it's just the end of line)::
#! 2 ['abc=1'] #! 2 ['abc=1']
abc abc
Usages References
++++++ ++++++++++
Tests look like this:: Tests look like this::
@@ -131,9 +131,9 @@ from jedi.inference.analysis import Warning
TEST_COMPLETIONS = 0 TEST_COMPLETIONS = 0
TEST_DEFINITIONS = 1 TEST_INFERENCE = 1
TEST_ASSIGNMENTS = 2 TEST_GOTO = 2
TEST_USAGES = 3 TEST_REFERENCES = 3
grammar36 = parso.load_grammar(version='3.6') grammar36 = parso.load_grammar(version='3.6')
@@ -195,28 +195,25 @@ class IntegrationTestCase(BaseTestCase):
self.line_nr_test, self.line.rstrip()) self.line_nr_test, self.line.rstrip())
def script(self, environment): def script(self, environment):
return jedi.Script( return jedi.Script(self.source, path=self.path, environment=environment)
self.source, self.line_nr, self.column, self.path,
environment=environment
)
def run(self, compare_cb, environment=None): def run(self, compare_cb, environment=None):
testers = { testers = {
TEST_COMPLETIONS: self.run_completion, TEST_COMPLETIONS: self.run_completion,
TEST_DEFINITIONS: self.run_goto_definitions, TEST_INFERENCE: self.run_inference,
TEST_ASSIGNMENTS: self.run_goto_assignments, TEST_GOTO: self.run_goto,
TEST_USAGES: self.run_usages, TEST_REFERENCES: self.run_find_references,
} }
return testers[self.test_type](compare_cb, environment) return testers[self.test_type](compare_cb, environment)
def run_completion(self, compare_cb, environment): def run_completion(self, compare_cb, environment):
completions = self.script(environment).completions() completions = self.script(environment).complete(self.line_nr, self.column)
#import cProfile; cProfile.run('script.completions()') # import cProfile; cProfile.run('...')
comp_str = {c.name for c in completions} comp_str = {c.name for c in completions}
return compare_cb(self, comp_str, set(literal_eval(self.correct))) return compare_cb(self, comp_str, set(literal_eval(self.correct)))
def run_goto_definitions(self, compare_cb, environment): def run_inference(self, compare_cb, environment):
script = self.script(environment) script = self.script(environment)
inference_state = script._inference_state inference_state = script._inference_state
@@ -233,9 +230,6 @@ class IntegrationTestCase(BaseTestCase):
node = parser.get_root_node() node = parser.get_root_node()
module_context = script._get_module_context() module_context = script._get_module_context()
user_context = get_user_context(module_context, (self.line_nr, 0)) user_context = get_user_context(module_context, (self.line_nr, 0))
# TODO needed?
#if user_context._value.api_type == 'function':
# user_context = user_context.get_function_execution()
node.parent = user_context.tree_node node.parent = user_context.tree_node
results = convert_values(user_context.infer_node(node)) results = convert_values(user_context.infer_node(node))
if not results: if not results:
@@ -250,17 +244,17 @@ class IntegrationTestCase(BaseTestCase):
return should return should
should = definition(self.correct, self.start, script.path) should = definition(self.correct, self.start, script.path)
result = script.goto_definitions() result = script.infer(self.line_nr, self.column)
is_str = set(comparison(r) for r in result) is_str = set(comparison(r) for r in result)
return compare_cb(self, is_str, should) return compare_cb(self, is_str, should)
def run_goto_assignments(self, compare_cb, environment): def run_goto(self, compare_cb, environment):
result = self.script(environment).goto_assignments() result = self.script(environment).goto(self.line_nr, self.column)
comp_str = str(sorted(str(r.description) for r in result)) comp_str = str(sorted(str(r.description) for r in result))
return compare_cb(self, comp_str, self.correct) return compare_cb(self, comp_str, self.correct)
def run_usages(self, compare_cb, environment): def run_find_references(self, compare_cb, environment):
result = self.script(environment).usages() result = self.script(environment).find_references(self.line_nr, self.column)
self.correct = self.correct.strip() self.correct = self.correct.strip()
compare = sorted( compare = sorted(
(re.sub(r'^test\.completion\.', '', r.module_name), r.line, r.column) (re.sub(r'^test\.completion\.', '', r.module_name), r.line, r.column)
@@ -287,7 +281,7 @@ class IntegrationTestCase(BaseTestCase):
class StaticAnalysisCase(BaseTestCase): class StaticAnalysisCase(BaseTestCase):
""" """
Static Analysis cases lie in the static_analysis folder. Static Analysis cases lie in the static_analysis folder.
The tests also start with `#!`, like the goto_definition tests. The tests also start with `#!`, like the inference tests.
""" """
def __init__(self, path): def __init__(self, path):
self._path = path self._path = path
@@ -311,12 +305,14 @@ class StaticAnalysisCase(BaseTestCase):
return cases return cases
def run(self, compare_cb, environment): def run(self, compare_cb, environment):
def typ_str(inst):
return 'warning ' if isinstance(inst, Warning) else ''
analysis = jedi.Script( analysis = jedi.Script(
self._source, self._source,
path=self._path, path=self._path,
environment=environment, environment=environment,
)._analysis() )._analysis()
typ_str = lambda inst: 'warning ' if isinstance(inst, Warning) else ''
analysis = [(r.line, r.column, typ_str(r) + r.name) analysis = [(r.line, r.column, typ_str(r) + r.name)
for r in analysis] for r in analysis]
compare_cb(self, analysis, self.collect_comparison()) compare_cb(self, analysis, self.collect_comparison())
@@ -354,19 +350,19 @@ def collect_file_tests(path, lines, lines_to_execute):
else: else:
column = len(line) - 1 # -1 for the \n column = len(line) - 1 # -1 for the \n
if test_type == '!': if test_type == '!':
yield makecase(TEST_ASSIGNMENTS) yield makecase(TEST_GOTO)
elif test_type == '<': elif test_type == '<':
yield makecase(TEST_USAGES) yield makecase(TEST_REFERENCES)
elif correct.startswith('['): elif correct.startswith('['):
yield makecase(TEST_COMPLETIONS) yield makecase(TEST_COMPLETIONS)
else: else:
yield makecase(TEST_DEFINITIONS) yield makecase(TEST_INFERENCE)
correct = None correct = None
else: else:
skip_version_info = skip_python_version(line) or skip_version_info skip_version_info = skip_python_version(line) or skip_version_info
try: try:
r = re.search(r'(?:^|(?<=\s))#([?!<])\s*([^\n]*)', line) r = re.search(r'(?:^|(?<=\s))#([?!<])\s*([^\n]*)', line)
# test_type is ? for completion and ! for goto_assignments # test_type is ? for completion and ! for goto
test_type = r.group(1) test_type = r.group(1)
correct = r.group(2) correct = r.group(2)
# Quick hack to make everything work (not quite a bloody unicorn hack though). # Quick hack to make everything work (not quite a bloody unicorn hack though).
@@ -1,4 +1,4 @@
""" """
An import tree, for testing usages. An import tree, for testing references.
""" """
+59 -51
View File
@@ -56,29 +56,29 @@ def test_line_number_errors(Script):
s = 'hello' s = 'hello'
# lines # lines
with raises(ValueError): with raises(ValueError):
Script(s, 2, 0) Script(s).complete(2, 0)
with raises(ValueError): with raises(ValueError):
Script(s, 0, 0) Script(s).complete(0, 0)
# columns # columns
with raises(ValueError): with raises(ValueError):
Script(s, 1, len(s) + 1) Script(s).infer(1, len(s) + 1)
with raises(ValueError): with raises(ValueError):
Script(s, 1, -1) Script(s).goto(1, -1)
# ok # ok
Script(s, 1, 0) Script(s).find_signatures(1, 0)
Script(s, 1, len(s)) Script(s).find_references(1, len(s))
def _check_number(Script, source, result='float'): def _check_number(Script, source, result='float'):
completions = Script(source).completions() completions = Script(source).complete()
assert completions[0].parent().name == result assert completions[0].parent().name == result
def test_completion_on_number_literals(Script): def test_completion_on_number_literals(Script):
# No completions on an int literal (is a float). # No completions on an int literal (is a float).
assert [c.name for c in Script('1. ').completions()] \ assert [c.name for c in Script('1. ').complete()] \
== ['and', 'if', 'in', 'is', 'not', 'or'] == ['and', 'if', 'in', 'is', 'not', 'or']
# Multiple points after an int literal basically mean that there's a float # Multiple points after an int literal basically mean that there's a float
@@ -90,27 +90,27 @@ def test_completion_on_number_literals(Script):
_check_number(Script, '1.e14.') _check_number(Script, '1.e14.')
_check_number(Script, '1.e-3.') _check_number(Script, '1.e-3.')
_check_number(Script, '9e3.') _check_number(Script, '9e3.')
assert Script('1.e3..').completions() == [] assert Script('1.e3..').complete() == []
assert Script('1.e-13..').completions() == [] assert Script('1.e-13..').complete() == []
def test_completion_on_hex_literals(Script): def test_completion_on_hex_literals(Script):
assert Script('0x1..').completions() == [] assert Script('0x1..').complete() == []
_check_number(Script, '0x1.', 'int') # hexdecimal _check_number(Script, '0x1.', 'int') # hexdecimal
# Completing binary literals doesn't work if they are not actually binary # Completing binary literals doesn't work if they are not actually binary
# (invalid statements). # (invalid statements).
assert Script('0b2.b').completions() == [] assert Script('0b2.b').complete() == []
_check_number(Script, '0b1.', 'int') # binary _check_number(Script, '0b1.', 'int') # binary
_check_number(Script, '0x2e.', 'int') _check_number(Script, '0x2e.', 'int')
_check_number(Script, '0xE7.', 'int') _check_number(Script, '0xE7.', 'int')
_check_number(Script, '0xEa.', 'int') _check_number(Script, '0xEa.', 'int')
# theoretically, but people can just check for syntax errors: # theoretically, but people can just check for syntax errors:
assert Script('0x.').completions() == [] assert Script('0x.').complete() == []
def test_completion_on_complex_literals(Script): def test_completion_on_complex_literals(Script):
assert Script('1j..').completions() == [] assert Script('1j..').complete() == []
_check_number(Script, '1j.', 'complex') _check_number(Script, '1j.', 'complex')
_check_number(Script, '44.j.', 'complex') _check_number(Script, '44.j.', 'complex')
_check_number(Script, '4.0j.', 'complex') _check_number(Script, '4.0j.', 'complex')
@@ -118,24 +118,24 @@ def test_completion_on_complex_literals(Script):
# which a keyword like or is allowed. Good times, haha! # which a keyword like or is allowed. Good times, haha!
# However this has been disabled again, because it apparently annoyed # However this has been disabled again, because it apparently annoyed
# users. So no completion after j without a space :) # users. So no completion after j without a space :)
assert not Script('4j').completions() assert not Script('4j').complete()
assert ({c.name for c in Script('4j ').completions()} == assert ({c.name for c in Script('4j ').complete()} ==
{'if', 'and', 'in', 'is', 'not', 'or'}) {'if', 'and', 'in', 'is', 'not', 'or'})
def test_goto_assignments_on_non_name(Script, environment): def test_goto_non_name(Script, environment):
assert Script('for').goto_assignments() == [] assert Script('for').goto() == []
assert Script('assert').goto_assignments() == [] assert Script('assert').goto() == []
assert Script('True').goto_assignments() == [] assert Script('True').goto() == []
def test_goto_definitions_on_non_name(Script): def test_infer_on_non_name(Script):
assert Script('import x', column=0).goto_definitions() == [] assert Script('import x').infer(column=0) == []
def test_goto_definitions_on_generator(Script): def test_infer_on_generator(Script):
def_, = Script('def x(): yield 1\ny=x()\ny').goto_definitions() def_, = Script('def x(): yield 1\ny=x()\ny').infer()
assert def_.name == 'Generator' assert def_.name == 'Generator'
@@ -159,17 +159,17 @@ def test_goto_definition_not_multiple(Script):
else: else:
a = A(1) a = A(1)
a''') a''')
assert len(Script(s).goto_definitions()) == 1 assert len(Script(s).infer()) == 1
def test_usage_description(Script): def test_reference_description(Script):
descs = [u.description for u in Script("foo = ''; foo").usages()] descs = [u.description for u in Script("foo = ''; foo").find_references()]
assert set(descs) == {"foo = ''", 'foo'} assert set(descs) == {"foo = ''", 'foo'}
def test_get_line_code(Script): def test_get_line_code(Script):
def get_line_code(source, line=None, **kwargs): def get_line_code(source, line=None, **kwargs):
return Script(source, line=line).completions()[0].get_line_code(**kwargs) return Script(source).complete(line=line)[0].get_line_code(**kwargs)
# On builtin # On builtin
assert get_line_code('abs') == 'def abs(__n: SupportsAbs[_T]) -> _T: ...\n' assert get_line_code('abs') == 'def abs(__n: SupportsAbs[_T]) -> _T: ...\n'
@@ -191,49 +191,49 @@ def test_get_line_code(Script):
def test_get_line_code_on_builtin(Script, disable_typeshed): def test_get_line_code_on_builtin(Script, disable_typeshed):
abs_ = Script('abs').completions()[0] abs_ = Script('abs').complete()[0]
assert abs_.name == 'abs' assert abs_.name == 'abs'
assert abs_.get_line_code() == '' assert abs_.get_line_code() == ''
assert abs_.line is None assert abs_.line is None
def test_goto_assignments_follow_imports(Script): def test_goto_follow_imports(Script):
code = dedent(""" code = dedent("""
import inspect import inspect
inspect.isfunction""") inspect.isfunction""")
definition, = Script(code, column=0).goto_assignments(follow_imports=True) definition, = Script(code).goto(column=0, follow_imports=True)
assert 'inspect.py' in definition.module_path assert 'inspect.py' in definition.module_path
assert (definition.line, definition.column) == (1, 0) assert (definition.line, definition.column) == (1, 0)
definition, = Script(code).goto_assignments(follow_imports=True) definition, = Script(code).goto(follow_imports=True)
assert 'inspect.py' in definition.module_path assert 'inspect.py' in definition.module_path
assert (definition.line, definition.column) > (1, 0) assert (definition.line, definition.column) > (1, 0)
code = '''def param(p): pass\nparam(1)''' code = '''def param(p): pass\nparam(1)'''
start_pos = 1, len('def param(') start_pos = 1, len('def param(')
script = Script(code, *start_pos) script = Script(code)
definition, = script.goto_assignments(follow_imports=True) definition, = script.goto(*start_pos, follow_imports=True)
assert (definition.line, definition.column) == start_pos assert (definition.line, definition.column) == start_pos
assert definition.name == 'p' assert definition.name == 'p'
result, = definition.goto_assignments() result, = definition.goto()
assert result.name == 'p' assert result.name == 'p'
result, = definition.infer() result, = definition.infer()
assert result.name == 'int' assert result.name == 'int'
result, = result.infer() result, = result.infer()
assert result.name == 'int' assert result.name == 'int'
definition, = script.goto_assignments() definition, = script.goto(*start_pos)
assert (definition.line, definition.column) == start_pos assert (definition.line, definition.column) == start_pos
d, = Script('a = 1\na').goto_assignments(follow_imports=True) d, = Script('a = 1\na').goto(follow_imports=True)
assert d.name == 'a' assert d.name == 'a'
def test_goto_module(Script): def test_goto_module(Script):
def check(line, expected, follow_imports=False): def check(line, expected, follow_imports=False):
script = Script(path=path, line=line) script = Script(path=path)
module, = script.goto_assignments(follow_imports=follow_imports) module, = script.goto(line=line, follow_imports=follow_imports)
assert module.module_path == expected assert module.module_path == expected
base_path = os.path.join(os.path.dirname(__file__), 'simple_import') base_path = os.path.join(os.path.dirname(__file__), 'simple_import')
@@ -264,7 +264,7 @@ def test_goto_definition_cursor(Script):
should2 = 8, 10 should2 = 8, 10
def get_def(pos): def get_def(pos):
return [d.description for d in Script(s, *pos).goto_definitions()] return [d.description for d in Script(s).infer(*pos)]
in_name = get_def(in_name) in_name = get_def(in_name)
under_score = get_def(under_score) under_score = get_def(under_score)
@@ -290,7 +290,7 @@ def test_no_statement_parent(Script):
pass pass
variable = f if random.choice([0, 1]) else C""") variable = f if random.choice([0, 1]) else C""")
defs = Script(source, column=3).goto_definitions() defs = Script(source).infer(column=3)
defs = sorted(defs, key=lambda d: d.line) defs = sorted(defs, key=lambda d: d.line)
assert [d.description for d in defs] == ['def f', 'class C'] assert [d.description for d in defs] == ['def f', 'class C']
@@ -303,27 +303,27 @@ def test_backslash_continuation_and_bracket(Script):
lines = code.splitlines() lines = code.splitlines()
column = lines[-1].index('(') column = lines[-1].index('(')
def_, = Script(code, line=len(lines), column=column).goto_definitions() def_, = Script(code).infer(line=len(lines), column=column)
assert def_.name == 'int' assert def_.name == 'int'
def test_goto_follow_builtin_imports(Script): def test_goto_follow_builtin_imports(Script):
s = Script('import sys; sys') s = Script('import sys; sys')
d, = s.goto_assignments(follow_imports=True) d, = s.goto(follow_imports=True)
assert d.in_builtin_module() is True assert d.in_builtin_module() is True
d, = s.goto_assignments(follow_imports=True, follow_builtin_imports=True) d, = s.goto(follow_imports=True, follow_builtin_imports=True)
assert d.in_builtin_module() is True assert d.in_builtin_module() is True
def test_docstrings_for_completions(Script): def test_docstrings_for_completions(Script):
for c in Script('').completions(): for c in Script('').complete():
assert isinstance(c.docstring(), (str, unicode)) assert isinstance(c.docstring(), (str, unicode))
def test_fuzzy_completion(Script): def test_fuzzy_completion(Script):
script = Script('string = "hello"\nstring.upper') script = Script('string = "hello"\nstring.upper')
assert ['isupper', assert ['isupper',
'upper'] == [comp.name for comp in script.completions(fuzzy=True)] 'upper'] == [comp.name for comp in script.complete(fuzzy=True)]
def test_math_fuzzy_completion(Script, environment): def test_math_fuzzy_completion(Script, environment):
@@ -331,7 +331,7 @@ def test_math_fuzzy_completion(Script, environment):
expected = ['copysign', 'log', 'log10', 'log1p'] expected = ['copysign', 'log', 'log10', 'log1p']
if environment.version_info.major >= 3: if environment.version_info.major >= 3:
expected.append('log2') expected.append('log2')
completions = script.completions(fuzzy=True) completions = script.complete(fuzzy=True)
assert expected == [comp.name for comp in completions] assert expected == [comp.name for comp in completions]
for c in completions: for c in completions:
assert c.complete is None assert c.complete is None
@@ -341,7 +341,7 @@ def test_file_fuzzy_completion(Script):
path = os.path.join(test_dir, 'completion') path = os.path.join(test_dir, 'completion')
script = Script('"{}/ep08_i'.format(path)) script = Script('"{}/ep08_i'.format(path))
assert ['pep0484_basic.py"', 'pep0484_typing.py"'] \ assert ['pep0484_basic.py"', 'pep0484_typing.py"'] \
== [comp.name for comp in script.completions(fuzzy=True)] == [comp.name for comp in script.complete(fuzzy=True)]
@pytest.mark.parametrize( @pytest.mark.parametrize(
@@ -355,6 +355,14 @@ def test_file_fuzzy_completion(Script):
] ]
) )
def test_goto_on_string(Script, code, column): def test_goto_on_string(Script, code, column):
script = Script(code, column=column) script = Script(code)
assert not script.goto_definitions() assert not script.infer(column=column)
assert not script.goto_assignments() assert not script.goto(column=column)
def test_multi_goto(Script):
script = Script('x = 1\ny = 1.0\nx\ny')
x, = script.goto(line=3)
y, = script.goto(line=4)
assert x.line == 1
assert y.line == 2
@@ -6,14 +6,14 @@ from ..helpers import cwd_at
def test_import_empty(Script): def test_import_empty(Script):
""" github #340, return the full word. """ """ github #340, return the full word. """
completion = Script("import ").completions()[0] completion = Script("import ").complete()[0]
definition = completion.infer()[0] definition = completion.infer()[0]
assert definition assert definition
def check_follow_definition_types(Script, source): def check_follow_definition_types(Script, source):
# nested import # nested import
completions = Script(source, path='some_path.py').completions() completions = Script(source, path='some_path.py').complete()
defs = chain.from_iterable(c.infer() for c in completions) defs = chain.from_iterable(c.infer() for c in completions)
return [d.type for d in defs] return [d.type for d in defs]
@@ -27,7 +27,7 @@ def test_follow_import_incomplete(Script, environment):
assert datetime == ['module'] assert datetime == ['module']
# empty `from * import` parts # empty `from * import` parts
itert = jedi.Script("from itertools import ").completions() itert = jedi.Script("from itertools import ").complete()
definitions = [d for d in itert if d.name == 'chain'] definitions = [d for d in itert if d.name == 'chain']
assert len(definitions) == 1 assert len(definitions) == 1
assert [d.type for d in definitions[0].infer()] == ['class'] assert [d.type for d in definitions[0].infer()] == ['class']
+52 -52
View File
@@ -6,12 +6,12 @@ import pytest
from ..helpers import TestCase from ..helpers import TestCase
from jedi import cache from jedi import cache
from jedi.parser_utils import get_call_signature from jedi.parser_utils import get_signature
from jedi import Interpreter from jedi import Interpreter
def assert_signature(Script, source, expected_name, expected_index=0, line=None, column=None): def assert_signature(Script, source, expected_name, expected_index=0, line=None, column=None):
signatures = Script(source, line, column).call_signatures() signatures = Script(source).find_signatures(line, column)
assert len(signatures) <= 1 assert len(signatures) <= 1
@@ -28,7 +28,7 @@ def test_valid_call(Script):
assert_signature(Script, 'bool()', 'bool', column=5) assert_signature(Script, 'bool()', 'bool', column=5)
class TestCallSignatures(TestCase): class TestSignatures(TestCase):
@pytest.fixture(autouse=True) @pytest.fixture(autouse=True)
def init(self, Script): def init(self, Script):
self.Script = Script self.Script = Script
@@ -96,12 +96,12 @@ class TestCallSignatures(TestCase):
def test_with(Script): def test_with(Script):
# jedi-vim #9 # jedi-vim #9
sigs = Script("with open(").call_signatures() sigs = Script("with open(").find_signatures()
assert sigs assert sigs
assert all(sig.name == 'open' for sig in sigs) assert all(sig.name == 'open' for sig in sigs)
def test_call_signatures_empty_parentheses_pre_space(Script): def test_find_signatures_empty_parentheses_pre_space(Script):
s = dedent("""\ s = dedent("""\
def f(a, b): def f(a, b):
pass pass
@@ -118,10 +118,10 @@ def test_multiple_signatures(Script):
def f(a, b): def f(a, b):
pass pass
f(""") f(""")
assert len(Script(s).call_signatures()) == 2 assert len(Script(s).find_signatures()) == 2
def test_call_signatures_whitespace(Script): def test_find_signatures_whitespace(Script):
s = dedent("""\ s = dedent("""\
abs( abs(
def x(): def x():
@@ -148,7 +148,7 @@ def test_decorator_in_class(Script):
C().test(""") C().test(""")
signatures = Script(s).call_signatures() signatures = Script(s).find_signatures()
assert len(signatures) == 1 assert len(signatures) == 1
x = [p.description for p in signatures[0].params] x = [p.description for p in signatures[0].params]
assert x == ['param *args'] assert x == ['param *args']
@@ -176,14 +176,14 @@ def test_brackets_in_string_literals(Script):
def test_function_definitions_should_break(Script): def test_function_definitions_should_break(Script):
""" """
Function definitions (and other tokens that cannot exist within call Function definitions (and other tokens that cannot exist within call
signatures) should break and not be able to return a call signature. signatures) should break and not be able to return a signature.
""" """
assert_signature(Script, 'abs(\ndef x', 'abs', 0) assert_signature(Script, 'abs(\ndef x', 'abs', 0)
assert not Script('abs(\ndef x(): pass').call_signatures() assert not Script('abs(\ndef x(): pass').find_signatures()
def test_flow_call(Script): def test_flow_call(Script):
assert not Script('if (1').call_signatures() assert not Script('if (1').find_signatures()
def test_chained_calls(Script): def test_chained_calls(Script):
@@ -209,11 +209,11 @@ def test_return(Script):
assert_signature(Script, source, 'join', 0, column=len(" return '.'.join(")) assert_signature(Script, source, 'join', 0, column=len(" return '.'.join("))
def test_call_signature_on_module(Script): def test_find_signature_on_module(Script):
"""github issue #240""" """github issue #240"""
s = 'import datetime; datetime(' s = 'import datetime; datetime('
# just don't throw an exception (if numpy doesn't exist, just ignore it) # just don't throw an exception (if numpy doesn't exist, just ignore it)
assert Script(s).call_signatures() == [] assert Script(s).find_signatures() == []
def test_complex(Script, environment): def test_complex(Script, environment):
@@ -234,7 +234,7 @@ def test_complex(Script, environment):
re.compile( re.compile(
return it * 2 return it * 2
""" """
sig1, sig2 = sorted(Script(s, line=4, column=27).call_signatures(), key=lambda s: s.line) sig1, sig2 = sorted(Script(s).find_signatures(line=4, column=27), key=lambda s: s.line)
assert sig1.name == sig2.name == 'compile' assert sig1.name == sig2.name == 'compile'
assert sig1.index == sig2.index == 0 assert sig1.index == sig2.index == 0
func1, = sig1._name.infer() func1, = sig1._name.infer()
@@ -243,14 +243,14 @@ def test_complex(Script, environment):
if environment.version_info.major == 3: if environment.version_info.major == 3:
# Do these checks just for Python 3, I'm too lazy to deal with this # Do these checks just for Python 3, I'm too lazy to deal with this
# legacy stuff. ~ dave. # legacy stuff. ~ dave.
assert get_call_signature(func1.tree_node) \ assert get_signature(func1.tree_node) \
== 'compile(pattern: AnyStr, flags: _FlagsType = ...) -> Pattern[AnyStr]' == 'compile(pattern: AnyStr, flags: _FlagsType = ...) -> Pattern[AnyStr]'
assert get_call_signature(func2.tree_node) \ assert get_signature(func2.tree_node) \
== 'compile(pattern: Pattern[AnyStr], flags: _FlagsType = ...) ->\nPattern[AnyStr]' == 'compile(pattern: Pattern[AnyStr], flags: _FlagsType = ...) ->\nPattern[AnyStr]'
# jedi-vim #70 # jedi-vim #70
s = """def foo(""" s = """def foo("""
assert Script(s).call_signatures() == [] assert Script(s).find_signatures() == []
# jedi-vim #116 # jedi-vim #116
s = """import itertools; test = getattr(itertools, 'chain'); test(""" s = """import itertools; test = getattr(itertools, 'chain'); test("""
@@ -258,13 +258,13 @@ def test_complex(Script, environment):
def _params(Script, source, line=None, column=None): def _params(Script, source, line=None, column=None):
signatures = Script(source, line, column).call_signatures() signatures = Script(source, line, column).find_signatures()
assert len(signatures) == 1 assert len(signatures) == 1
return signatures[0].params return signatures[0].params
def test_int_params(Script): def test_int_params(Script):
sig1, sig2 = Script('int(').call_signatures() sig1, sig2 = Script('int(').find_signatures()
# int is defined as: `int(x[, base])` # int is defined as: `int(x[, base])`
assert len(sig1.params) == 1 assert len(sig1.params) == 1
assert sig1.params[0].name == 'x' assert sig1.params[0].name == 'x'
@@ -275,13 +275,13 @@ def test_int_params(Script):
def test_pow_params(Script): def test_pow_params(Script):
# See Github #1357. # See Github #1357.
for sig in Script('pow(').call_signatures(): for sig in Script('pow(').find_signatures():
param_names = [p.name for p in sig.params] param_names = [p.name for p in sig.params]
assert param_names in (['x', 'y'], ['x', 'y', 'z']) assert param_names in (['x', 'y'], ['x', 'y', 'z'])
def test_param_name(Script): def test_param_name(Script):
sigs = Script('open(something,').call_signatures() sigs = Script('open(something,').find_signatures()
for sig in sigs: for sig in sigs:
# All of the signatures (in Python the function is overloaded), # All of the signatures (in Python the function is overloaded),
# contain the same param names. # contain the same param names.
@@ -304,19 +304,19 @@ def test_builtins(Script):
def test_signature_is_definition(Script): def test_signature_is_definition(Script):
""" """
Through inheritance, a call signature is a sub class of Definition. Through inheritance, a signature is a sub class of Definition.
Check if the attributes match. Check if the attributes match.
""" """
s = """class Spam(): pass\nSpam""" s = """class Spam(): pass\nSpam"""
signature = Script(s + '(').call_signatures()[0] signature = Script(s + '(').find_signatures()[0]
definition = Script(s + '(', column=0).goto_definitions()[0] definition = Script(s + '(').infer(column=0)[0]
signature.line == 1 signature.line == 1
signature.column == 6 signature.column == 6
# Now compare all the attributes that a CallSignature must also have. # Now compare all the attributes that a Signature must also have.
for attr_name in dir(definition): for attr_name in dir(definition):
dont_scan = ['defined_names', 'parent', 'goto_assignments', 'infer', dont_scan = ['defined_names', 'parent', 'goto_assignments', 'infer',
'params', 'get_signatures', 'execute'] 'params', 'get_signatures', 'execute', 'goto']
if attr_name.startswith('_') or attr_name in dont_scan: if attr_name.startswith('_') or attr_name in dont_scan:
continue continue
@@ -330,15 +330,15 @@ def test_signature_is_definition(Script):
def test_no_signature(Script): def test_no_signature(Script):
# str doesn't have a __call__ method # str doesn't have a __call__ method
assert Script('str()(').call_signatures() == [] assert Script('str()(').find_signatures() == []
s = dedent("""\ s = dedent("""\
class X(): class X():
pass pass
X()(""") X()(""")
assert Script(s).call_signatures() == [] assert Script(s).find_signatures() == []
assert len(Script(s, column=2).call_signatures()) == 1 assert len(Script(s).find_signatures(column=2)) == 1
assert Script('').call_signatures() == [] assert Script('').find_signatures() == []
def test_dict_literal_in_incomplete_call(Script): def test_dict_literal_in_incomplete_call(Script):
@@ -354,24 +354,24 @@ def test_dict_literal_in_incomplete_call(Script):
c = Foo() c = Foo()
""" """
script = Script(dedent(source), line=4, column=15) script = Script(dedent(source))
assert script.call_signatures() assert script.find_signatures(line=4, column=15)
def test_completion_interference(Script): def test_completion_interference(Script):
"""Seems to cause problems, see also #396.""" """Seems to cause problems, see also #396."""
cache.parser_cache.pop(None, None) cache.parser_cache.pop(None, None)
assert Script('open(').call_signatures() assert Script('open(').find_signatures()
# complete something usual, before doing the same call_signatures again. # complete something usual, before doing the same find_signatures again.
assert Script('from datetime import ').completions() assert Script('from datetime import ').complete()
assert Script('open(').call_signatures() assert Script('open(').find_signatures()
def test_keyword_argument_index(Script, environment): def test_keyword_argument_index(Script, environment):
def get(source, column=None): def get(source, column=None):
return Script(source, column=column).call_signatures()[0] return Script(source).find_signatures(column=column)[0]
# The signature of sorted changed from 2 to 3. # The signature of sorted changed from 2 to 3.
py2_offset = int(environment.version_info.major == 2) py2_offset = int(environment.version_info.major == 2)
@@ -509,7 +509,7 @@ def test_signature_index(skip_python2, Script, environment, code, call, expected
if environment.version_info < (3, 8): if environment.version_info < (3, 8):
code = code.replace('/,', '') code = code.replace('/,', '')
sig, = Script(code + '\n' + call + ending, column=len(call)).call_signatures() sig, = Script(code + '\n' + call + ending).find_signatures(column=len(call))
index = sig.index index = sig.index
assert expected_index == index assert expected_index == index
@@ -547,14 +547,14 @@ def test_arg_defaults(Script, environment, code):
yield Interpreter(code + '2(', namespaces=[executed_locals]) yield Interpreter(code + '2(', namespaces=[executed_locals])
for script in iter_scripts(): for script in iter_scripts():
signatures = script.call_signatures() signatures = script.find_signatures()
assert signatures[0].params[0].description in ('param arg="bla"', "param arg='bla'") assert signatures[0].params[0].description in ('param arg="bla"', "param arg='bla'")
assert signatures[0].params[1].description == 'param arg1=1' assert signatures[0].params[1].description == 'param arg1=1'
def test_bracket_start(Script): def test_bracket_start(Script):
def bracket_start(src): def bracket_start(src):
signatures = Script(src).call_signatures() signatures = Script(src).find_signatures()
assert len(signatures) == 1 assert len(signatures) == 1
return signatures[0].bracket_start return signatures[0].bracket_start
@@ -564,7 +564,7 @@ def test_bracket_start(Script):
def test_different_caller(Script): def test_different_caller(Script):
""" """
It's possible to not use names, but another function result or an array It's possible to not use names, but another function result or an array
index and then get the call signature of it. index and then get the signature of it.
""" """
assert_signature(Script, '[abs][0](', 'abs', 0) assert_signature(Script, '[abs][0](', 'abs', 0)
@@ -579,14 +579,14 @@ def test_in_function(Script):
class X(): class X():
@property @property
def func(''') def func(''')
assert not Script(code).call_signatures() assert not Script(code).find_signatures()
def test_lambda_params(Script): def test_lambda_params(Script):
code = dedent('''\ code = dedent('''\
my_lambda = lambda x: x+1 my_lambda = lambda x: x+1
my_lambda(1)''') my_lambda(1)''')
sig, = Script(code, column=11).call_signatures() sig, = Script(code).find_signatures(column=11)
assert sig.index == 0 assert sig.index == 0
assert sig.name == '<lambda>' assert sig.name == '<lambda>'
assert [p.name for p in sig.params] == ['x'] assert [p.name for p in sig.params] == ['x']
@@ -601,19 +601,19 @@ class X():
def test_class_creation(Script): def test_class_creation(Script):
sig, = Script(CLASS_CODE + 'X(').call_signatures() sig, = Script(CLASS_CODE + 'X(').find_signatures()
assert sig.index == 0 assert sig.index == 0
assert sig.name == 'X' assert sig.name == 'X'
assert [p.name for p in sig.params] == ['foo', 'bar'] assert [p.name for p in sig.params] == ['foo', 'bar']
def test_call_init_on_class(Script): def test_call_init_on_class(Script):
sig, = Script(CLASS_CODE + 'X.__init__(').call_signatures() sig, = Script(CLASS_CODE + 'X.__init__(').find_signatures()
assert [p.name for p in sig.params] == ['self', 'foo', 'bar'] assert [p.name for p in sig.params] == ['self', 'foo', 'bar']
def test_call_init_on_instance(Script): def test_call_init_on_instance(Script):
sig, = Script(CLASS_CODE + 'X().__init__(').call_signatures() sig, = Script(CLASS_CODE + 'X().__init__(').find_signatures()
assert [p.name for p in sig.params] == ['foo', 'bar'] assert [p.name for p in sig.params] == ['foo', 'bar']
@@ -623,14 +623,14 @@ def test_call_magic_method(Script):
def __call__(self, baz): def __call__(self, baz):
pass pass
''') ''')
sig, = Script(code + 'X()(').call_signatures() sig, = Script(code + 'X()(').find_signatures()
assert sig.index == 0 assert sig.index == 0
assert sig.name == 'X' assert sig.name == 'X'
assert [p.name for p in sig.params] == ['baz'] assert [p.name for p in sig.params] == ['baz']
sig, = Script(code + 'X.__call__(').call_signatures() sig, = Script(code + 'X.__call__(').find_signatures()
assert [p.name for p in sig.params] == ['self', 'baz'] assert [p.name for p in sig.params] == ['self', 'baz']
sig, = Script(code + 'X().__call__(').call_signatures() sig, = Script(code + 'X().__call__(').find_signatures()
assert [p.name for p in sig.params] == ['baz'] assert [p.name for p in sig.params] == ['baz']
@@ -642,9 +642,9 @@ def test_cursor_after_signature(Script, column):
foo() # _ foo() # _
""") """)
script = Script(source, 4, column) script = Script(source)
assert not script.call_signatures() assert not script.find_signatures(4, column)
@pytest.mark.parametrize( @pytest.mark.parametrize(
@@ -661,7 +661,7 @@ def test_cursor_after_signature(Script, column):
] ]
) )
def test_base_signatures(Script, code, line, column, name, index): def test_base_signatures(Script, code, line, column, name, index):
sig, = Script(code, line=line, column=column).call_signatures() sig, = Script(code).find_signatures(line=line, column=column)
assert sig.name == name assert sig.name == name
assert sig.index == index assert sig.index == index
+56 -56
View File
@@ -14,7 +14,7 @@ from ..helpers import get_example_dir
def test_is_keyword(Script): def test_is_keyword(Script):
results = Script('str', 1, 1, None).goto_definitions() results = Script('str', path=None).infer(1, 1)
assert len(results) == 1 and results[0].is_keyword is False assert len(results) == 1 and results[0].is_keyword is False
@@ -48,15 +48,15 @@ def test_basedefinition_type(Script, names):
source += dedent(""" source += dedent("""
variable = sys or C or x or f or g or g() or h""") variable = sys or C or x or f or g or g() or h""")
lines = source.splitlines() lines = source.splitlines()
script = Script(source, len(lines), len('variable'), None) script = Script(source, path=None)
definitions += script.goto_definitions() definitions += script.infer(len(lines), len('variable'))
script2 = Script(source, 4, len('class C'), None) script2 = Script(source, path=None)
definitions += script2.usages() definitions += script2.find_references(4, len('class C'))
source_param = "def f(a): return a" source_param = "def f(a): return a"
script_param = Script(source_param, 1, len(source_param), None) script_param = Script(source_param, path=None)
definitions += script_param.goto_assignments() definitions += script_param.goto(1, len(source_param))
return definitions return definitions
@@ -88,15 +88,15 @@ def test_basedefinition_type(Script, names):
) )
def test_basedefinition_type_import(Script, src, expected_result, column): def test_basedefinition_type_import(Script, src, expected_result, column):
types = {t.type for t in Script(src, column=column).completions()} types = {t.type for t in Script(src).complete(column=column)}
assert types == {expected_result} assert types == {expected_result}
def test_function_call_signature_in_doc(Script): def test_function_signature_in_doc(Script):
defs = Script(""" defs = Script("""
def f(x, y=1, z='a'): def f(x, y=1, z='a'):
pass pass
f""").goto_definitions() f""").infer()
doc = defs[0].docstring() doc = defs[0].docstring()
assert "f(x, y=1, z='a')" in str(doc) assert "f(x, y=1, z='a')" in str(doc)
@@ -107,18 +107,18 @@ def test_param_docstring(names):
assert param.docstring() == '' assert param.docstring() == ''
def test_class_call_signature(Script): def test_class_signature(Script):
defs = Script(""" defs = Script("""
class Foo: class Foo:
def __init__(self, x, y=1, z='a'): def __init__(self, x, y=1, z='a'):
pass pass
Foo""").goto_definitions() Foo""").infer()
doc = defs[0].docstring() doc = defs[0].docstring()
assert doc == "Foo(x, y=1, z='a')" assert doc == "Foo(x, y=1, z='a')"
def test_position_none_if_builtin(Script): def test_position_none_if_builtin(Script):
gotos = Script('import sys; sys.path').goto_assignments() gotos = Script('import sys; sys.path').goto()
assert gotos[0].in_builtin_module() assert gotos[0].in_builtin_module()
assert gotos[0].line is not None assert gotos[0].line is not None
assert gotos[0].column is not None assert gotos[0].column is not None
@@ -129,10 +129,10 @@ def test_completion_docstring(Script, jedi_path):
Jedi should follow imports in certain conditions Jedi should follow imports in certain conditions
""" """
def docstr(src, result): def docstr(src, result):
c = Script(src, sys_path=[jedi_path]).completions()[0] c = Script(src, sys_path=[jedi_path]).complete()[0]
assert c.docstring(raw=True, fast=False) == cleandoc(result) assert c.docstring(raw=True, fast=False) == cleandoc(result)
c = Script('import jedi\njed', sys_path=[jedi_path]).completions()[0] c = Script('import jedi\njed', sys_path=[jedi_path]).complete()[0]
assert c.docstring(fast=False) == cleandoc(jedi_doc) assert c.docstring(fast=False) == cleandoc(jedi_doc)
docstr('import jedi\njedi.Scr', cleandoc(jedi.Script.__doc__)) docstr('import jedi\njedi.Scr', cleandoc(jedi.Script.__doc__))
@@ -174,12 +174,12 @@ def test_completion_docstring(Script, jedi_path):
def test_completion_params(Script): def test_completion_params(Script):
c = Script('import string; string.capwords').completions()[0] c = Script('import string; string.capwords').complete()[0]
assert [p.name for p in c.params] == ['s', 'sep'] assert [p.name for p in c.params] == ['s', 'sep']
def test_functions_should_have_params(Script): def test_functions_should_have_params(Script):
for c in Script('bool.').completions(): for c in Script('bool.').complete():
if c.type == 'function': if c.type == 'function':
assert isinstance(c.params, list) assert isinstance(c.params, list)
@@ -189,7 +189,7 @@ def test_hashlib_params(Script, environment):
pytest.skip() pytest.skip()
script = Script(source='from hashlib import sha256') script = Script(source='from hashlib import sha256')
c, = script.completions() c, = script.complete()
assert [p.name for p in c.params] == ['arg'] assert [p.name for p in c.params] == ['arg']
@@ -204,10 +204,10 @@ def test_signature_params(Script):
pass pass
foo''') foo''')
check(Script(s).goto_definitions()) check(Script(s).infer())
check(Script(s).goto_assignments()) check(Script(s).goto())
check(Script(s + '\nbar=foo\nbar').goto_assignments()) check(Script(s + '\nbar=foo\nbar').goto())
def test_param_endings(Script): def test_param_endings(Script):
@@ -215,7 +215,7 @@ def test_param_endings(Script):
Params should be represented without the comma and whitespace they have Params should be represented without the comma and whitespace they have
around them. around them.
""" """
sig = Script('def x(a, b=5, c=""): pass\n x(').call_signatures()[0] sig = Script('def x(a, b=5, c=""): pass\n x(').find_signatures()[0]
assert [p.description for p in sig.params] == ['param a', 'param b=5', 'param c=""'] assert [p.description for p in sig.params] == ['param a', 'param b=5', 'param c=""']
@@ -253,7 +253,7 @@ def test_is_definition_import(names, code, expected):
def test_parent(Script): def test_parent(Script):
def _parent(source, line=None, column=None): def _parent(source, line=None, column=None):
def_, = Script(dedent(source), line, column).goto_assignments() def_, = Script(dedent(source)).goto(line, column)
return def_.parent() return def_.parent()
parent = _parent('foo=1\nfoo') parent = _parent('foo=1\nfoo')
@@ -270,7 +270,7 @@ def test_parent(Script):
def test_parent_on_function(Script): def test_parent_on_function(Script):
code = 'def spam():\n pass' code = 'def spam():\n pass'
def_, = Script(code, line=1, column=len('def spam')).goto_assignments() def_, = Script(code).goto(line=1, column=len('def spam'))
parent = def_.parent() parent = def_.parent()
assert parent.name == '' assert parent.name == ''
assert parent.type == 'module' assert parent.type == 'module'
@@ -280,20 +280,20 @@ def test_parent_on_completion(Script):
parent = Script(dedent('''\ parent = Script(dedent('''\
class Foo(): class Foo():
def bar(): pass def bar(): pass
Foo().bar''')).completions()[0].parent() Foo().bar''')).complete()[0].parent()
assert parent.name == 'Foo' assert parent.name == 'Foo'
assert parent.type == 'class' assert parent.type == 'class'
parent = Script('str.join').completions()[0].parent() parent = Script('str.join').complete()[0].parent()
assert parent.name == 'str' assert parent.name == 'str'
assert parent.type == 'class' assert parent.type == 'class'
def test_parent_on_comprehension(): def test_parent_on_comprehension(Script):
ns = jedi.names('''\ ns = Script('''\
def spam(): def spam():
return [i for i in range(5)] return [i for i in range(5)]
''', all_scopes=True) ''').names(all_scopes=True)
assert [name.name for name in ns] == ['spam', 'i'] assert [name.name for name in ns] == ['spam', 'i']
@@ -304,17 +304,17 @@ def test_parent_on_comprehension():
def test_type(Script): def test_type(Script):
for c in Script('a = [str()]; a[0].').completions(): for c in Script('a = [str()]; a[0].').complete():
if c.name == '__class__' and False: # TODO fix. if c.name == '__class__' and False: # TODO fix.
assert c.type == 'class' assert c.type == 'class'
else: else:
assert c.type in ('function', 'statement') assert c.type in ('function', 'statement')
for c in Script('list.').completions(): for c in Script('list.').complete():
assert c.type assert c.type
# Github issue #397, type should never raise an error. # Github issue #397, type should never raise an error.
for c in Script('import os; os.path.').completions(): for c in Script('import os; os.path.').complete():
assert c.type assert c.type
@@ -322,36 +322,36 @@ def test_type_II(Script):
""" """
GitHub Issue #833, `keyword`s are seen as `module`s GitHub Issue #833, `keyword`s are seen as `module`s
""" """
for c in Script('f').completions(): for c in Script('f').complete():
if c.name == 'for': if c.name == 'for':
assert c.type == 'keyword' assert c.type == 'keyword'
""" """
This tests the BaseDefinition.goto_assignments function, not the jedi This tests the BaseDefinition.goto function, not the jedi
function. They are not really different in functionality, but really function. They are not really different in functionality, but really
different as an implementation. different as an implementation.
""" """
def test_goto_assignment_repetition(names): def test_goto_repetition(names):
defs = names('a = 1; a', references=True, definitions=False) defs = names('a = 1; a', references=True, definitions=False)
# Repeat on the same variable. Shouldn't change once we're on a # Repeat on the same variable. Shouldn't change once we're on a
# definition. # definition.
for _ in range(3): for _ in range(3):
assert len(defs) == 1 assert len(defs) == 1
ass = defs[0].goto_assignments() ass = defs[0].goto()
assert ass[0].description == 'a = 1' assert ass[0].description == 'a = 1'
def test_goto_assignments_named_params(names): def test_goto_named_params(names):
src = """\ src = """\
def foo(a=1, bar=2): def foo(a=1, bar=2):
pass pass
foo(bar=1) foo(bar=1)
""" """
bar = names(dedent(src), references=True)[-1] bar = names(dedent(src), references=True)[-1]
param = bar.goto_assignments()[0] param = bar.goto()[0]
assert (param.line, param.column) == (1, 13) assert (param.line, param.column) == (1, 13)
assert param.type == 'param' assert param.type == 'param'
@@ -360,46 +360,46 @@ def test_class_call(names):
src = 'from threading import Thread; Thread(group=1)' src = 'from threading import Thread; Thread(group=1)'
n = names(src, references=True)[-1] n = names(src, references=True)[-1]
assert n.name == 'group' assert n.name == 'group'
param_def = n.goto_assignments()[0] param_def = n.goto()[0]
assert param_def.name == 'group' assert param_def.name == 'group'
assert param_def.type == 'param' assert param_def.type == 'param'
def test_parentheses(names): def test_parentheses(names):
n = names('("").upper', references=True)[-1] n = names('("").upper', references=True)[-1]
assert n.goto_assignments()[0].name == 'upper' assert n.goto()[0].name == 'upper'
def test_import(names): def test_import(names):
nms = names('from json import load', references=True) nms = names('from json import load', references=True)
assert nms[0].name == 'json' assert nms[0].name == 'json'
assert nms[0].type == 'module' assert nms[0].type == 'module'
n = nms[0].goto_assignments()[0] n = nms[0].goto()[0]
assert n.name == 'json' assert n.name == 'json'
assert n.type == 'module' assert n.type == 'module'
assert nms[1].name == 'load' assert nms[1].name == 'load'
assert nms[1].type == 'function' assert nms[1].type == 'function'
n = nms[1].goto_assignments()[0] n = nms[1].goto()[0]
assert n.name == 'load' assert n.name == 'load'
assert n.type == 'function' assert n.type == 'function'
nms = names('import os; os.path', references=True) nms = names('import os; os.path', references=True)
assert nms[0].name == 'os' assert nms[0].name == 'os'
assert nms[0].type == 'module' assert nms[0].type == 'module'
n = nms[0].goto_assignments()[0] n = nms[0].goto()[0]
assert n.name == 'os' assert n.name == 'os'
assert n.type == 'module' assert n.type == 'module'
n = nms[2].goto_assignments()[0] n = nms[2].goto()[0]
assert n.name == 'path' assert n.name == 'path'
assert n.type == 'module' assert n.type == 'module'
nms = names('import os.path', references=True) nms = names('import os.path', references=True)
n = nms[0].goto_assignments()[0] n = nms[0].goto()[0]
assert n.name == 'os' assert n.name == 'os'
assert n.type == 'module' assert n.type == 'module'
n = nms[1].goto_assignments()[0] n = nms[1].goto()[0]
# This is very special, normally the name doesn't chance, but since # This is very special, normally the name doesn't chance, but since
# os.path is a sys.modules hack, it does. # os.path is a sys.modules hack, it does.
assert n.name in ('macpath', 'ntpath', 'posixpath', 'os2emxpath') assert n.name in ('macpath', 'ntpath', 'posixpath', 'os2emxpath')
@@ -411,7 +411,7 @@ def test_import_alias(names):
assert nms[0].name == 'json' assert nms[0].name == 'json'
assert nms[0].type == 'module' assert nms[0].type == 'module'
assert nms[0]._name.tree_name.parent.type == 'dotted_as_name' assert nms[0]._name.tree_name.parent.type == 'dotted_as_name'
n = nms[0].goto_assignments()[0] n = nms[0].goto()[0]
assert n.name == 'json' assert n.name == 'json'
assert n.type == 'module' assert n.type == 'module'
assert n._name._value.tree_node.type == 'file_input' assert n._name._value.tree_node.type == 'file_input'
@@ -419,7 +419,7 @@ def test_import_alias(names):
assert nms[1].name == 'foo' assert nms[1].name == 'foo'
assert nms[1].type == 'module' assert nms[1].type == 'module'
assert nms[1]._name.tree_name.parent.type == 'dotted_as_name' assert nms[1]._name.tree_name.parent.type == 'dotted_as_name'
ass = nms[1].goto_assignments() ass = nms[1].goto()
assert len(ass) == 1 assert len(ass) == 1
assert ass[0].name == 'json' assert ass[0].name == 'json'
assert ass[0].type == 'module' assert ass[0].type == 'module'
@@ -432,7 +432,7 @@ def test_added_equals_to_params(Script):
def foo(bar, baz): def foo(bar, baz):
pass pass
""") """)
results = Script(source + rest_source).completions() results = Script(source + rest_source).complete()
assert len(results) == 1 assert len(results) == 1
return results[0] return results[0]
@@ -451,7 +451,7 @@ def test_builtin_module_with_path(Script):
a path or not. It shouldn't have a module_path, because that is just a path or not. It shouldn't have a module_path, because that is just
confusing. confusing.
""" """
semlock, = Script('from _multiprocessing import SemLock').goto_definitions() semlock, = Script('from _multiprocessing import SemLock').infer()
assert isinstance(semlock._name, CompiledValueName) assert isinstance(semlock._name, CompiledValueName)
assert semlock.module_path is None assert semlock.module_path is None
assert semlock.in_builtin_module() is True assert semlock.in_builtin_module() is True
@@ -468,7 +468,7 @@ def test_builtin_module_with_path(Script):
] ]
) )
def test_execute(Script, code, description): def test_execute(Script, code, description):
definition, = Script(code).goto_assignments() definition, = Script(code).goto()
definitions = definition.execute() definitions = definition.execute()
if description is None: if description is None:
assert not definitions assert not definitions
@@ -477,7 +477,7 @@ def test_execute(Script, code, description):
assert d.description == description assert d.description == description
@pytest.mark.parametrize('goto_assignment', [False, True, None]) @pytest.mark.parametrize('goto', [False, True, None])
@pytest.mark.parametrize( @pytest.mark.parametrize(
'code, name, file_name', [ 'code, name, file_name', [
('from pkg import Foo; Foo.foo', 'foo', '__init__.py'), ('from pkg import Foo; Foo.foo', 'foo', '__init__.py'),
@@ -485,15 +485,15 @@ def test_execute(Script, code, description):
('from pkg import Foo; Foo.bar', 'bar', 'module.py'), ('from pkg import Foo; Foo.bar', 'bar', 'module.py'),
('from pkg import Foo; Foo().bar', 'bar', 'module.py'), ('from pkg import Foo; Foo().bar', 'bar', 'module.py'),
]) ])
def test_inheritance_module_path(Script, goto_assignment, code, name, file_name): def test_inheritance_module_path(Script, goto, code, name, file_name):
base_path = os.path.join(get_example_dir('inheritance'), 'pkg') base_path = os.path.join(get_example_dir('inheritance'), 'pkg')
whatever_path = os.path.join(base_path, 'NOT_EXISTING.py') whatever_path = os.path.join(base_path, 'NOT_EXISTING.py')
script = Script(code, path=whatever_path) script = Script(code, path=whatever_path)
if goto_assignment is None: if goto is None:
func, = script.goto_definitions() func, = script.infer()
else: else:
func, = script.goto_assignments(follow_imports=goto_assignment) func, = script.goto(follow_imports=goto)
assert func.type == 'function' assert func.type == 'function'
assert func.name == name assert func.name == name
assert func.module_path == os.path.join(base_path, file_name) assert func.module_path == os.path.join(base_path, file_name)
+24 -24
View File
@@ -4,14 +4,16 @@ import sys
from textwrap import dedent from textwrap import dedent
import pytest import pytest
from ..helpers import root_dir from ..helpers import root_dir
from jedi.api.helpers import start_match, fuzzy_match
def test_in_whitespace(Script): def test_in_whitespace(Script):
code = dedent(''' code = dedent('''
def x(): def x():
pass''') pass''')
assert len(Script(code, column=2).completions()) > 20 assert len(Script(code).complete(column=2)) > 20
def test_empty_init(Script): def test_empty_init(Script):
@@ -19,7 +21,7 @@ def test_empty_init(Script):
code = dedent('''\ code = dedent('''\
class X(object): pass class X(object): pass
X(''') X(''')
assert Script(code).completions() assert Script(code).complete()
def test_in_empty_space(Script): def test_in_empty_space(Script):
@@ -28,7 +30,7 @@ def test_in_empty_space(Script):
def __init__(self): def __init__(self):
hello hello
''') ''')
comps = Script(code, 3, 7).completions() comps = Script(code).complete(3, 7)
self, = [c for c in comps if c.name == 'self'] self, = [c for c in comps if c.name == 'self']
assert self.name == 'self' assert self.name == 'self'
def_, = self.infer() def_, = self.infer()
@@ -41,13 +43,13 @@ def test_indent_value(Script):
complete. complete.
""" """
code = 'if 1:\nisinstanc' code = 'if 1:\nisinstanc'
comp, = Script(code).completions() comp, = Script(code).complete()
assert comp.name == 'isinstance' assert comp.name == 'isinstance'
def test_keyword_value(Script): def test_keyword_value(Script):
def get_names(*args, **kwargs): def get_names(*args, **kwargs):
return [d.name for d in Script(*args, **kwargs).completions()] return [d.name for d in Script(*args, **kwargs).complete()]
names = get_names('if 1:\n pass\n') names = get_names('if 1:\n pass\n')
assert 'if' in names assert 'if' in names
@@ -56,7 +58,7 @@ def test_keyword_value(Script):
def test_os_nowait(Script): def test_os_nowait(Script):
""" github issue #45 """ """ github issue #45 """
s = Script("import os; os.P_").completions() s = Script("import os; os.P_").complete()
assert 'P_NOWAIT' in [i.name for i in s] assert 'P_NOWAIT' in [i.name for i in s]
@@ -64,7 +66,7 @@ def test_points_in_completion(Script):
"""At some point, points were inserted into the completions, this """At some point, points were inserted into the completions, this
caused problems, sometimes. caused problems, sometimes.
""" """
c = Script("if IndentationErr").completions() c = Script("if IndentationErr").complete()
assert c[0].name == 'IndentationError' assert c[0].name == 'IndentationError'
assert c[0].complete == 'or' assert c[0].complete == 'or'
@@ -80,9 +82,8 @@ def test_loading_unicode_files_with_bad_global_charset(Script, monkeypatch, tmpd
with open(filename1, "wb") as f: with open(filename1, "wb") as f:
f.write(data) f.write(data)
s = Script("from test1 import foo\nfoo.", s = Script("from test1 import foo\nfoo.", path=filename2)
line=2, column=4, path=filename2) s.complete(line=2, column=4)
s.completions()
def test_fake_subnodes(Script): def test_fake_subnodes(Script):
@@ -100,7 +101,7 @@ def test_fake_subnodes(Script):
return c return c
limit = None limit = None
for i in range(2): for i in range(2):
completions = Script('').completions() completions = Script('').complete()
c = get_str_completion(completions) c = get_str_completion(completions)
str_value, = c._name.infer() str_value, = c._name.infer()
n = len(str_value.tree_node.children[-1].children) n = len(str_value.tree_node.children[-1].children)
@@ -116,17 +117,17 @@ def test_generator(Script):
s = "def abc():\n" \ s = "def abc():\n" \
" yield 1\n" \ " yield 1\n" \
"abc()." "abc()."
assert Script(s).completions() assert Script(s).complete()
def test_in_comment(Script): def test_in_comment(Script):
assert Script(" # Comment").completions() assert Script(" # Comment").complete()
# TODO this is a bit ugly, that the behaviors in comments are different. # TODO this is a bit ugly, that the behaviors in comments are different.
assert not Script("max_attr_value = int(2) # Cast to int for spe").completions() assert not Script("max_attr_value = int(2) # Cast to int for spe").complete()
def test_in_comment_before_string(Script): def test_in_comment_before_string(Script):
assert not Script(" # Foo\n'asdf'", line=1).completions() assert not Script(" # Foo\n'asdf'").complete(line=1)
def test_async(Script, environment): def test_async(Script, environment):
@@ -137,16 +138,15 @@ def test_async(Script, environment):
foo = 3 foo = 3
async def x(): async def x():
hey = 3 hey = 3
ho''' ho''')
) comps = Script(code).complete(column=4)
comps = Script(code, column=4).completions()
names = [c.name for c in comps] names = [c.name for c in comps]
assert 'foo' in names assert 'foo' in names
assert 'hey' in names assert 'hey' in names
def test_with_stmt_error_recovery(Script): def test_with_stmt_error_recovery(Script):
assert Script('with open('') as foo: foo.\na', line=1).completions() assert Script('with open('') as foo: foo.\na').complete(line=1)
@pytest.mark.parametrize( @pytest.mark.parametrize(
@@ -161,7 +161,7 @@ def test_with_stmt_error_recovery(Script):
) )
) )
def test_keyword_completion(Script, code, has_keywords): def test_keyword_completion(Script, code, has_keywords):
assert has_keywords == any(x.is_keyword for x in Script(code).completions()) assert has_keywords == any(x.is_keyword for x in Script(code).complete())
f1 = join(root_dir, 'example.py') f1 = join(root_dir, 'example.py')
@@ -187,7 +187,7 @@ current_dirname = os.path.basename(dirname(dirname(dirname(__file__))))
('test%sexample.py' % se, 'r"test%scomp"' % s, 5, ['t' + s]), ('test%sexample.py' % se, 'r"test%scomp"' % s, 5, ['t' + s]),
('test%sexample.py' % se, 'r"test%scomp"' % s, 11, ['letion' + s]), ('test%sexample.py' % se, 'r"test%scomp"' % s, 11, ['letion' + s]),
('test%sexample.py' % se, '"%s"' % join('test', 'completion', 'basi'), 21, ['c.py']), ('test%sexample.py' % se, '"%s"' % join('test', 'completion', 'basi'), 21, ['c.py']),
('example.py', 'rb"'+ join('..', current_dirname, 'tes'), None, ['t' + s]), ('example.py', 'rb"' + join('..', current_dirname, 'tes'), None, ['t' + s]),
# Absolute paths # Absolute paths
(None, '"' + join(root_dir, 'test', 'test_ca'), None, ['che.py"']), (None, '"' + join(root_dir, 'test', 'test_ca'), None, ['che.py"']),
@@ -266,17 +266,17 @@ def test_file_path_completions(Script, file, code, column, expected):
line = None line = None
if isinstance(column, tuple): if isinstance(column, tuple):
line, column = column line, column = column
comps = Script(code, path=file, line=line, column=column).completions() comps = Script(code, path=file).complete(line=line, column=column)
if expected == "A LOT": if expected == "A LOT":
assert len(comps) > 100 # This is basically global completions. assert len(comps) > 100 # This is basically global completions.
else: else:
assert [c.complete for c in comps] == expected assert [c.complete for c in comps] == expected
from jedi.api.helpers import start_match, fuzzy_match
def test_start_match(): def test_start_match():
assert start_match('Condition', 'C') assert start_match('Condition', 'C')
def test_fuzzy_match(): def test_fuzzy_match():
assert fuzzy_match('Condition', 'i') assert fuzzy_match('Condition', 'i')
assert not fuzzy_match('Condition', 'p') assert not fuzzy_match('Condition', 'p')
+3 -3
View File
@@ -139,12 +139,12 @@ def test_follow_imports(names):
def test_names_twice(names): def test_names_twice(names):
source = dedent(''' code = dedent('''
def lol(): def lol():
pass pass
''') ''')
defs = names(source=source) defs = names(code)
assert defs[0].defined_names() == [] assert defs[0].defined_names() == []
@@ -166,4 +166,4 @@ def test_no_error(names):
assert a.name == 'a' assert a.name == 'a'
assert b.name == 'b' assert b.name == 'b'
assert a20.name == 'a' assert a20.name == 'a'
assert a20.goto_assignments() == [a20] assert a20.goto() == [a20]
+4 -4
View File
@@ -66,13 +66,13 @@ def test_error_in_environment(inference_state, Script, environment):
with pytest.raises(jedi.InternalError): with pytest.raises(jedi.InternalError):
inference_state.compiled_subprocess._test_raise_error(KeyboardInterrupt) inference_state.compiled_subprocess._test_raise_error(KeyboardInterrupt)
# Jedi should still work. # Jedi should still work.
def_, = Script('str').goto_definitions() def_, = Script('str').infer()
assert def_.name == 'str' assert def_.name == 'str'
def test_stdout_in_subprocess(inference_state, Script): def test_stdout_in_subprocess(inference_state, Script):
inference_state.compiled_subprocess._test_print(stdout='.') inference_state.compiled_subprocess._test_print(stdout='.')
Script('1').goto_definitions() Script('1').infer()
def test_killed_subprocess(inference_state, Script, environment): def test_killed_subprocess(inference_state, Script, environment):
@@ -83,9 +83,9 @@ def test_killed_subprocess(inference_state, Script, environment):
# Since the process was terminated (and nobody knows about it) the first # Since the process was terminated (and nobody knows about it) the first
# Jedi call fails. # Jedi call fails.
with pytest.raises(jedi.InternalError): with pytest.raises(jedi.InternalError):
Script('str').goto_definitions() Script('str').infer()
def_, = Script('str').goto_definitions() def_, = Script('str').infer()
# Jedi should now work again. # Jedi should now work again.
assert def_.name == 'str' assert def_.name == 'str'
+10 -9
View File
@@ -31,7 +31,7 @@ class MixinTestFullName(object):
def check(self, source, desired): def check(self, source, desired):
script = self.Script(textwrap.dedent(source)) script = self.Script(textwrap.dedent(source))
definitions = getattr(script, type(self).operation)() definitions = getattr(script, self.operation)()
for d in definitions: for d in definitions:
self.assertEqual(d.full_name, desired) self.assertEqual(d.full_name, desired)
@@ -43,7 +43,7 @@ class MixinTestFullName(object):
class TestFullNameWithGotoDefinitions(MixinTestFullName, TestCase): class TestFullNameWithGotoDefinitions(MixinTestFullName, TestCase):
operation = 'goto_definitions' operation = 'infer'
def test_tuple_mapping(self): def test_tuple_mapping(self):
if self.environment.version_info.major == 2: if self.environment.version_info.major == 2:
@@ -59,7 +59,7 @@ class TestFullNameWithGotoDefinitions(MixinTestFullName, TestCase):
class TestFullNameWithCompletions(MixinTestFullName, TestCase): class TestFullNameWithCompletions(MixinTestFullName, TestCase):
operation = 'completions' operation = 'complete'
class TestFullDefinedName(TestCase): class TestFullDefinedName(TestCase):
@@ -71,7 +71,8 @@ class TestFullDefinedName(TestCase):
self.environment = environment self.environment = environment
def check(self, source, desired): def check(self, source, desired):
definitions = jedi.names(textwrap.dedent(source), environment=self.environment) script = jedi.Script(textwrap.dedent(source), environment=self.environment)
definitions = script.names()
full_names = [d.full_name for d in definitions] full_names = [d.full_name for d in definitions]
self.assertEqual(full_names, desired) self.assertEqual(full_names, desired)
@@ -96,19 +97,19 @@ def test_sub_module(Script, jedi_path):
path. path.
""" """
sys_path = [jedi_path] sys_path = [jedi_path]
defs = Script('from jedi.api import classes; classes', sys_path=sys_path).goto_definitions() defs = Script('from jedi.api import classes; classes', sys_path=sys_path).infer()
assert [d.full_name for d in defs] == ['jedi.api.classes'] assert [d.full_name for d in defs] == ['jedi.api.classes']
defs = Script('import jedi.api; jedi.api', sys_path=sys_path).goto_definitions() defs = Script('import jedi.api; jedi.api', sys_path=sys_path).infer()
assert [d.full_name for d in defs] == ['jedi.api'] assert [d.full_name for d in defs] == ['jedi.api']
def test_os_path(Script): def test_os_path(Script):
d, = Script('from os.path import join').completions() d, = Script('from os.path import join').complete()
assert d.full_name == 'os.path.join' assert d.full_name == 'os.path.join'
d, = Script('import os.p').completions() d, = Script('import os.p').complete()
assert d.full_name == 'os.path' assert d.full_name == 'os.path'
def test_os_issues(Script): def test_os_issues(Script):
"""Issue #873""" """Issue #873"""
assert [c.name for c in Script('import os\nos.nt''').completions()] == ['nt'] assert [c.name for c in Script('import os\nos.nt''').complete()] == ['nt']
+23 -23
View File
@@ -26,7 +26,7 @@ class _GlobalNameSpace:
def get_completion(source, namespace): def get_completion(source, namespace):
i = jedi.Interpreter(source, [namespace]) i = jedi.Interpreter(source, [namespace])
completions = i.completions() completions = i.complete()
assert len(completions) == 1 assert len(completions) == 1
return completions[0] return completions[0]
@@ -111,7 +111,7 @@ def test_side_effect_completion():
def _assert_interpreter_complete(source, namespace, completions, def _assert_interpreter_complete(source, namespace, completions,
**kwds): **kwds):
script = jedi.Interpreter(source, [namespace], **kwds) script = jedi.Interpreter(source, [namespace], **kwds)
cs = script.completions() cs = script.complete()
actual = [c.name for c in cs] actual = [c.name for c in cs]
assert sorted(actual) == sorted(completions) assert sorted(actual) == sorted(completions)
@@ -298,7 +298,7 @@ def test_property_content():
return 1 return 1
foo = Foo3() foo = Foo3()
def_, = jedi.Interpreter('foo.bar', [locals()]).goto_definitions() def_, = jedi.Interpreter('foo.bar', [locals()]).infer()
assert def_.name == 'int' assert def_.name == 'int'
@@ -310,7 +310,7 @@ def test_param_completion():
lambd = lambda xyz: 3 lambd = lambda xyz: 3
_assert_interpreter_complete('foo(bar', locals(), ['bar']) _assert_interpreter_complete('foo(bar', locals(), ['bar'])
assert bool(jedi.Interpreter('lambd(xyz', [locals()]).completions()) == is_py3 assert bool(jedi.Interpreter('lambd(xyz', [locals()]).complete()) == is_py3
def test_endless_yield(): def test_endless_yield():
@@ -325,7 +325,7 @@ def test_completion_params():
foo = lambda a, b=3: None foo = lambda a, b=3: None
script = jedi.Interpreter('foo', [locals()]) script = jedi.Interpreter('foo', [locals()])
c, = script.completions() c, = script.complete()
assert [p.name for p in c.params] == ['a', 'b'] assert [p.name for p in c.params] == ['a', 'b']
assert c.params[0].infer() == [] assert c.params[0].infer() == []
t, = c.params[1].infer() t, = c.params[1].infer()
@@ -339,13 +339,13 @@ def test_completion_param_annotations():
code = 'def foo(a: 1, b: str, c: int = 1.0) -> bytes: pass' code = 'def foo(a: 1, b: str, c: int = 1.0) -> bytes: pass'
exec_(code, locals()) exec_(code, locals())
script = jedi.Interpreter('foo', [locals()]) script = jedi.Interpreter('foo', [locals()])
c, = script.completions() c, = script.complete()
a, b, c = c.params a, b, c = c.params
assert a.infer() == [] assert a.infer() == []
assert [d.name for d in b.infer()] == ['str'] assert [d.name for d in b.infer()] == ['str']
assert {d.name for d in c.infer()} == {'int', 'float'} assert {d.name for d in c.infer()} == {'int', 'float'}
d, = jedi.Interpreter('foo()', [locals()]).goto_definitions() d, = jedi.Interpreter('foo()', [locals()]).infer()
assert d.name == 'bytes' assert d.name == 'bytes'
@@ -354,7 +354,7 @@ def test_keyword_argument():
def f(some_keyword_argument): def f(some_keyword_argument):
pass pass
c, = jedi.Interpreter("f(some_keyw", [{'f': f}]).completions() c, = jedi.Interpreter("f(some_keyw", [{'f': f}]).complete()
assert c.name == 'some_keyword_argument' assert c.name == 'some_keyword_argument'
assert c.complete == 'ord_argument=' assert c.complete == 'ord_argument='
@@ -362,7 +362,7 @@ def test_keyword_argument():
if is_py3: if is_py3:
# Make it impossible for jedi to find the source of the function. # Make it impossible for jedi to find the source of the function.
f.__name__ = 'xSOMETHING' f.__name__ = 'xSOMETHING'
c, = jedi.Interpreter("x(some_keyw", [{'x': f}]).completions() c, = jedi.Interpreter("x(some_keyw", [{'x': f}]).complete()
assert c.name == 'some_keyword_argument' assert c.name == 'some_keyword_argument'
@@ -376,12 +376,12 @@ def test_more_complex_instances():
return Something() return Something()
#script = jedi.Interpreter('Base().wow().foo', [locals()]) #script = jedi.Interpreter('Base().wow().foo', [locals()])
#c, = script.completions() #c, = script.complete()
#assert c.name == 'foo' #assert c.name == 'foo'
x = Base() x = Base()
script = jedi.Interpreter('x.wow().foo', [locals()]) script = jedi.Interpreter('x.wow().foo', [locals()])
c, = script.completions() c, = script.complete()
assert c.name == 'foo' assert c.name == 'foo'
@@ -397,7 +397,7 @@ def test_repr_execution_issue():
er = ErrorRepr() er = ErrorRepr()
script = jedi.Interpreter('er', [locals()]) script = jedi.Interpreter('er', [locals()])
d, = script.goto_definitions() d, = script.infer()
assert d.name == 'ErrorRepr' assert d.name == 'ErrorRepr'
assert d.type == 'instance' assert d.type == 'instance'
@@ -419,7 +419,7 @@ def test_dir_magic_method(allow_unsafe_getattr):
return ['foo', 'bar'] + names return ['foo', 'bar'] + names
itp = jedi.Interpreter("ca.", [{'ca': CompleteAttrs()}]) itp = jedi.Interpreter("ca.", [{'ca': CompleteAttrs()}])
completions = itp.completions() completions = itp.complete()
names = [c.name for c in completions] names = [c.name for c in completions]
assert ('__dir__' in names) == is_py3 assert ('__dir__' in names) == is_py3
assert '__class__' in names assert '__class__' in names
@@ -447,19 +447,19 @@ def test_name_not_findable():
setattr(X, 'NOT_FINDABLE', X.hidden) setattr(X, 'NOT_FINDABLE', X.hidden)
assert jedi.Interpreter("X.NOT_FINDA", [locals()]).completions() assert jedi.Interpreter("X.NOT_FINDA", [locals()]).complete()
def test_stubs_working(): def test_stubs_working():
from multiprocessing import cpu_count from multiprocessing import cpu_count
defs = jedi.Interpreter("cpu_count()", [locals()]).goto_definitions() defs = jedi.Interpreter("cpu_count()", [locals()]).infer()
assert [d.name for d in defs] == ['int'] assert [d.name for d in defs] == ['int']
def test_sys_path_docstring(): # Was an issue in #1298 def test_sys_path_docstring(): # Was an issue in #1298
import jedi import jedi
s = jedi.Interpreter("from sys import path\npath", line=2, column=4, namespaces=[locals()]) s = jedi.Interpreter("from sys import path\npath", namespaces=[locals()])
s.completions()[0].docstring() s.complete(line=2, column=4)[0].docstring()
@pytest.mark.skipif(sys.version_info[0] == 2, reason="Ignore Python 2, because EOL") @pytest.mark.skipif(sys.version_info[0] == 2, reason="Ignore Python 2, because EOL")
@@ -504,7 +504,7 @@ def test_simple_completions(code, completions):
counter = collections.Counter(['asdf']) counter = collections.Counter(['asdf'])
string = '' string = ''
defs = jedi.Interpreter(code, [locals()]).completions() defs = jedi.Interpreter(code, [locals()]).complete()
assert [d.name for d in defs] == completions assert [d.name for d in defs] == completions
@@ -516,7 +516,7 @@ def test__wrapped__():
def syslogs_to_df(): def syslogs_to_df():
pass pass
c, = jedi.Interpreter('syslogs_to_df', [locals()]).completions() c, = jedi.Interpreter('syslogs_to_df', [locals()]).complete()
# Apparently the function starts on the line where the decorator starts. # Apparently the function starts on the line where the decorator starts.
assert c.line == syslogs_to_df.__wrapped__.__code__.co_firstlineno + 1 assert c.line == syslogs_to_df.__wrapped__.__code__.co_firstlineno + 1
@@ -525,7 +525,7 @@ def test__wrapped__():
@pytest.mark.parametrize('module_name', ['sys', 'time', 'unittest.mock']) @pytest.mark.parametrize('module_name', ['sys', 'time', 'unittest.mock'])
def test_core_module_completes(module_name): def test_core_module_completes(module_name):
module = import_module(module_name) module = import_module(module_name)
assert jedi.Interpreter('module.', [locals()]).completions() assert jedi.Interpreter('module.', [locals()]).complete()
@pytest.mark.skipif(sys.version_info[0] == 2, reason="Ignore Python 2, because EOL") @pytest.mark.skipif(sys.version_info[0] == 2, reason="Ignore Python 2, because EOL")
@@ -548,7 +548,7 @@ def test_partial_signatures(code, expected, index):
b = functools.partial(func, 1) b = functools.partial(func, 1)
c = functools.partial(func, 1, c=2) c = functools.partial(func, 1, c=2)
sig, = jedi.Interpreter(code, [locals()]).call_signatures() sig, = jedi.Interpreter(code, [locals()]).find_signatures()
assert sig.name == 'partial' assert sig.name == 'partial'
assert [p.name for p in sig.params] == expected assert [p.name for p in sig.params] == expected
assert index == sig.index assert index == sig.index
@@ -559,7 +559,7 @@ def test_type_var():
"""This was an issue before, see Github #1369""" """This was an issue before, see Github #1369"""
import typing import typing
x = typing.TypeVar('myvar') x = typing.TypeVar('myvar')
def_, = jedi.Interpreter('x', [locals()]).goto_definitions() def_, = jedi.Interpreter('x', [locals()]).infer()
assert def_.name == 'TypeVar' assert def_.name == 'TypeVar'
@@ -573,5 +573,5 @@ def test_param_annotation_completion(class_is_findable):
Foo.__name__ = 'asdf' Foo.__name__ = 'asdf'
code = 'def CallFoo(x: Foo):\n x.ba' code = 'def CallFoo(x: Foo):\n x.ba'
def_, = jedi.Interpreter(code, [locals()]).completions() def_, = jedi.Interpreter(code, [locals()]).complete()
assert def_.name == 'bar' assert def_.name == 'bar'
+10 -10
View File
@@ -5,38 +5,38 @@ Test of keywords and ``jedi.keywords``
import pytest import pytest
def test_goto_assignments_keyword(Script): def test_goto_keyword(Script):
""" """
Bug: goto assignments on ``in`` used to raise AttributeError:: Bug: goto assignments on ``in`` used to raise AttributeError::
'unicode' object has no attribute 'generate_call_path' 'unicode' object has no attribute 'generate_call_path'
""" """
Script('in').goto_assignments() Script('in').goto()
def test_keyword(Script, environment): def test_keyword(Script, environment):
""" github jedi-vim issue #44 """ """ github jedi-vim issue #44 """
defs = Script("print").goto_definitions() defs = Script("print").infer()
if environment.version_info.major < 3: if environment.version_info.major < 3:
assert defs == [] assert defs == []
else: else:
assert [d.docstring() for d in defs] assert [d.docstring() for d in defs]
assert Script("import").goto_assignments() == [] assert Script("import").goto() == []
completions = Script("import", 1, 1).completions() completions = Script("import").complete(1, 1)
assert len(completions) > 10 and 'if' in [c.name for c in completions] assert len(completions) > 10 and 'if' in [c.name for c in completions]
assert Script("assert").goto_definitions() == [] assert Script("assert").infer() == []
def test_keyword_attributes(Script): def test_keyword_attributes(Script):
def_, = Script('def').completions() def_, = Script('def').complete()
assert def_.name == 'def' assert def_.name == 'def'
assert def_.complete == '' assert def_.complete == ''
assert def_.is_keyword is True assert def_.is_keyword is True
assert def_.is_stub() is False assert def_.is_stub() is False
assert def_.goto_assignments(only_stubs=True) == [] assert def_.goto(only_stubs=True) == []
assert def_.goto_assignments() == [] assert def_.goto() == []
assert def_.infer() == [] assert def_.infer() == []
assert def_.parent() is None assert def_.parent() is None
assert def_.docstring() assert def_.docstring()
@@ -55,6 +55,6 @@ def test_none_keyword(Script, environment):
# Just don't care about Python 2 anymore, it's almost gone. # Just don't care about Python 2 anymore, it's almost gone.
pytest.skip() pytest.skip()
none, = Script('None').completions() none, = Script('None').complete()
assert not none.docstring() assert not none.docstring()
assert none.name == 'None' assert none.name == 'None'
+1 -1
View File
@@ -11,7 +11,7 @@ def test_django_default_project(Script):
"from app import models\nmodels.SomeMo", "from app import models\nmodels.SomeMo",
path=os.path.join(dir, 'models/x.py') path=os.path.join(dir, 'models/x.py')
) )
c, = script.completions() c, = script.complete()
assert c.name == "SomeModel" assert c.name == "SomeModel"
assert script._inference_state.project._django is True assert script._inference_state.project._django is True
+2 -2
View File
@@ -18,7 +18,7 @@ def test_add_dynamic_mods(Script):
src2 = 'from .. import setup; setup.r(1)' src2 = 'from .. import setup; setup.r(1)'
script = Script(src1, path='../setup.py') script = Script(src1, path='../setup.py')
imports.load_module(script._inference_state, os.path.abspath(fname), src2) imports.load_module(script._inference_state, os.path.abspath(fname), src2)
result = script.goto_definitions() result = script.infer()
assert len(result) == 1 assert len(result) == 1
assert result[0].description == 'class int' assert result[0].description == 'class int'
@@ -30,5 +30,5 @@ def test_add_bracket_after_function(monkeypatch, Script):
def foo(): def foo():
pass pass
foo''') foo''')
completions = script.completions() completions = script.complete()
assert completions[0].complete == '(' assert completions[0].complete == '('
+4 -4
View File
@@ -21,7 +21,7 @@ _tuple_code = 'from typing import Tuple\ndef f(x: Tuple[int]): ...\nf'
] ]
) )
def test_param_annotation(Script, code, expected_params, execute_annotation, skip_python2): def test_param_annotation(Script, code, expected_params, execute_annotation, skip_python2):
func, = Script(code).goto_assignments() func, = Script(code).goto()
sig, = func.get_signatures() sig, = func.get_signatures()
for p, expected in zip(sig.params, expected_params): for p, expected in zip(sig.params, expected_params):
annotations = p.infer_annotation(execute_annotation=execute_annotation) annotations = p.infer_annotation(execute_annotation=execute_annotation)
@@ -40,7 +40,7 @@ def test_param_annotation(Script, code, expected_params, execute_annotation, ski
] ]
) )
def test_param_default(Script, code, expected_params): def test_param_default(Script, code, expected_params):
func, = Script(code).goto_assignments() func, = Script(code).goto()
sig, = func.get_signatures() sig, = func.get_signatures()
for p, expected in zip(sig.params, expected_params): for p, expected in zip(sig.params, expected_params):
annotations = p.infer_default() annotations = p.infer_default()
@@ -62,7 +62,7 @@ def test_param_default(Script, code, expected_params):
] ]
) )
def test_param_kind_and_name(code, index, param_code, kind, Script, skip_python2): def test_param_kind_and_name(code, index, param_code, kind, Script, skip_python2):
func, = Script(code).goto_assignments() func, = Script(code).goto()
sig, = func.get_signatures() sig, = func.get_signatures()
param = sig.params[index] param = sig.params[index]
assert param.to_string() == param_code assert param.to_string() == param_code
@@ -70,5 +70,5 @@ def test_param_kind_and_name(code, index, param_code, kind, Script, skip_python2
def test_staticmethod(Script): def test_staticmethod(Script):
s, = Script('staticmethod(').call_signatures() s, = Script('staticmethod(').find_signatures()
assert s.to_string() == 'staticmethod(f: Callable[..., Any])' assert s.to_string() == 'staticmethod(f: Callable[..., Any])'
+12 -12
View File
@@ -8,18 +8,18 @@ from jedi._compatibility import u, unicode
def test_unicode_script(Script): def test_unicode_script(Script):
""" normally no unicode objects are being used. (<=2.7) """ """ normally no unicode objects are being used. (<=2.7) """
s = unicode("import datetime; datetime.timedelta") s = unicode("import datetime; datetime.timedelta")
completions = Script(s).completions() completions = Script(s).complete()
assert len(completions) assert len(completions)
assert type(completions[0].description) is unicode assert type(completions[0].description) is unicode
s = u("author='öä'; author") s = u("author='öä'; author")
completions = Script(s).completions() completions = Script(s).complete()
x = completions[0].description x = completions[0].description
assert type(x) is unicode assert type(x) is unicode
s = u("#-*- coding: iso-8859-1 -*-\nauthor='öä'; author") s = u("#-*- coding: iso-8859-1 -*-\nauthor='öä'; author")
s = s.encode('latin-1') s = s.encode('latin-1')
completions = Script(s).completions() completions = Script(s).complete()
assert type(completions[0].description) is unicode assert type(completions[0].description) is unicode
@@ -27,11 +27,11 @@ def test_unicode_attribute(Script):
""" github jedi-vim issue #94 """ """ github jedi-vim issue #94 """
s1 = u('#-*- coding: utf-8 -*-\nclass Person():\n' s1 = u('#-*- coding: utf-8 -*-\nclass Person():\n'
' name = "e"\n\nPerson().name.') ' name = "e"\n\nPerson().name.')
completions1 = Script(s1).completions() completions1 = Script(s1).complete()
assert 'strip' in [c.name for c in completions1] assert 'strip' in [c.name for c in completions1]
s2 = u('#-*- coding: utf-8 -*-\nclass Person():\n' s2 = u('#-*- coding: utf-8 -*-\nclass Person():\n'
' name = "é"\n\nPerson().name.') ' name = "é"\n\nPerson().name.')
completions2 = Script(s2).completions() completions2 = Script(s2).complete()
assert 'strip' in [c.name for c in completions2] assert 'strip' in [c.name for c in completions2]
@@ -44,24 +44,24 @@ def test_multibyte_script(Script):
except NameError: except NameError:
pass # python 3 has no unicode method pass # python 3 has no unicode method
else: else:
assert len(Script(s, 1, len(code)).completions()) assert len(Script(s).complete(1, len(code)))
def test_goto_definition_at_zero(Script): def test_goto_definition_at_zero(Script):
"""At zero usually sometimes raises unicode issues.""" """At zero usually sometimes raises unicode issues."""
assert Script("a", 1, 1).goto_definitions() == [] assert Script("a").infer(1, 1) == []
s = Script("str", 1, 1).goto_definitions() s = Script("str").infer(1, 1)
assert len(s) == 1 assert len(s) == 1
assert list(s)[0].description == 'class str' assert list(s)[0].description == 'class str'
assert Script("", 1, 0).goto_definitions() == [] assert Script("").infer(1, 0) == []
def test_complete_at_zero(Script): def test_complete_at_zero(Script):
s = Script("str", 1, 3).completions() s = Script("str").complete(1, 3)
assert len(s) == 1 assert len(s) == 1
assert list(s)[0].name == 'str' assert list(s)[0].name == 'str'
s = Script("", 1, 0).completions() s = Script("").complete(1, 0)
assert len(s) > 0 assert len(s) > 0
@@ -70,7 +70,7 @@ def test_wrong_encoding(Script, tmpdir):
# Use both latin-1 and utf-8 (a really broken file). # Use both latin-1 and utf-8 (a really broken file).
x.write_binary(u'foobar = 1\nä'.encode('latin-1') + u'ä'.encode('utf-8')) x.write_binary(u'foobar = 1\nä'.encode('latin-1') + u'ä'.encode('utf-8'))
c, = Script('import x; x.foo', sys_path=[tmpdir.strpath]).completions() c, = Script('import x; x.foo', sys_path=[tmpdir.strpath]).complete()
assert c.name == 'foobar' assert c.name == 'foobar'
+5 -4
View File
@@ -1,11 +1,12 @@
def test_import_usage(Script): def test_import_references(Script):
s = Script("from .. import foo", line=1, column=18, path="foo.py") s = Script("from .. import foo", path="foo.py")
assert [usage.line for usage in s.usages()] == [1] assert [usage.line for usage in s.find_references(line=1, column=18)] == [1]
def test_exclude_builtin_modules(Script): def test_exclude_builtin_modules(Script):
def get(include): def get(include):
return [(d.line, d.column) for d in Script(source, column=8).usages(include_builtins=include)] references = Script(source).find_references(column=8, include_builtins=include)
return [(d.line, d.column) for d in references]
source = '''import sys\nprint(sys.path)''' source = '''import sys\nprint(sys.path)'''
places = get(include=True) places = get(include=True)
assert len(places) > 2 # Includes stubs assert len(places) > 2 # Includes stubs
+3 -3
View File
@@ -3,12 +3,12 @@ Test all things related to the ``jedi.cache`` module.
""" """
def test_cache_call_signatures(Script): def test_cache_find_signatures(Script):
""" """
See github issue #390. See github issue #390.
""" """
def check(column, call_name, path=None): def check(column, call_name, path=None):
assert Script(s, 1, column, path).call_signatures()[0].name == call_name assert Script(s, path=path).find_signatures(1, column)[0].name == call_name
s = 'str(int())' s = 'str(int())'
@@ -26,4 +26,4 @@ def test_cache_call_signatures(Script):
def test_cache_line_split_issues(Script): def test_cache_line_split_issues(Script):
"""Should still work even if there's a newline.""" """Should still work even if there's a newline."""
assert Script('int(\n').call_signatures()[0].name == 'int' assert Script('int(\n').find_signatures()[0].name == 'int'
+27
View File
@@ -0,0 +1,27 @@
def test_goto_definitions(Script):
int_, = Script('x = 1\nx, y\ny', line=2, column=0).goto_definitions()
assert int_.name == 'int'
def test_completions(Script):
c1, c2 = Script('foobar = 1\nfoobaz= 2\nfoobaz, ffff\nfool = 3', line=3, column=3).completions()
assert c1.name == 'foobar'
assert c2.name == 'foobaz'
def test_goto_assignments(Script):
int_, = Script('x = 1\nx, y\ny', line=2, column=0).goto_assignments()
assert int_.get_line_code() == 'x = 1\n'
def test_usages(Script):
d1, d2 = Script('x = 1\nx, y\ny', line=2, column=0).usages()
assert d1.name == 'x'
assert d1.line == 1
assert d2.name == 'x'
assert d2.line == 2
def test_call_signatures(Script):
d1, = Script('abs(float(\nstr(', line=1, column=4).call_signatures()
assert d1.name == 'abs'
+1 -1
View File
@@ -8,4 +8,4 @@ from .. import helpers
@helpers.cwd_at("test/test_inference/absolute_import") @helpers.cwd_at("test/test_inference/absolute_import")
def test_can_complete_when_shadowing(Script): def test_can_complete_when_shadowing(Script):
script = Script(path="unittest.py") script = Script(path="unittest.py")
assert script.completions() assert script.complete()
+5 -5
View File
@@ -18,7 +18,7 @@ def test_simple_annotations(Script, environment):
annot('')""") annot('')""")
assert [d.name for d in Script(source).goto_definitions()] == ['str'] assert [d.name for d in Script(source).infer()] == ['str']
source = dedent("""\ source = dedent("""\
@@ -26,7 +26,7 @@ def test_simple_annotations(Script, environment):
return a return a
annot_ret('')""") annot_ret('')""")
assert [d.name for d in Script(source).goto_definitions()] == ['str'] assert [d.name for d in Script(source).infer()] == ['str']
source = dedent("""\ source = dedent("""\
def annot(a:int): def annot(a:int):
@@ -34,7 +34,7 @@ def test_simple_annotations(Script, environment):
annot('')""") annot('')""")
assert [d.name for d in Script(source).goto_definitions()] == ['int'] assert [d.name for d in Script(source).infer()] == ['int']
@pytest.mark.parametrize('reference', [ @pytest.mark.parametrize('reference', [
@@ -50,7 +50,7 @@ def test_illegal_forward_references(Script, environment, reference):
source = 'def foo(bar: "%s"): bar' % reference source = 'def foo(bar: "%s"): bar' % reference
assert not Script(source).goto_definitions() assert not Script(source).infer()
def test_lambda_forward_references(Script, environment): def test_lambda_forward_references(Script, environment):
@@ -61,4 +61,4 @@ def test_lambda_forward_references(Script, environment):
# For now just receiving the 3 is ok. I'm doubting that this is what we # 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? # want. We also execute functions. Should we only execute classes?
assert Script(source).goto_definitions() assert Script(source).infer()
+5 -5
View File
@@ -61,7 +61,7 @@ def test_doc(inference_state):
def test_string_literals(Script, environment): def test_string_literals(Script, environment):
def typ(string): def typ(string):
d = Script("a = %s; a" % string).goto_definitions()[0] d = Script("a = %s; a" % string).infer()[0]
return d.name return d.name
assert typ('""') == 'str' assert typ('""') == 'str'
@@ -83,12 +83,12 @@ def test_method_completion(Script, environment):
foo = Foo() foo = Foo()
foo.bar.__func__''') foo.bar.__func__''')
assert [c.name for c in Script(code).completions()] == ['__func__'] assert [c.name for c in Script(code).complete()] == ['__func__']
def test_time_docstring(Script): def test_time_docstring(Script):
import time import time
comp, = Script('import time\ntime.sleep').completions() comp, = Script('import time\ntime.sleep').complete()
assert comp.docstring(raw=True) == time.sleep.__doc__ assert comp.docstring(raw=True) == time.sleep.__doc__
expected = 'sleep(secs: float) -> None\n\n' + time.sleep.__doc__ expected = 'sleep(secs: float) -> None\n\n' + time.sleep.__doc__
assert comp.docstring() == expected assert comp.docstring() == expected
@@ -98,12 +98,12 @@ def test_dict_values(Script, environment):
if environment.version_info.major == 2: if environment.version_info.major == 2:
# It looks like typeshed for Python 2 returns Any. # It looks like typeshed for Python 2 returns Any.
pytest.skip() pytest.skip()
assert Script('import sys\nsys.modules["alshdb;lasdhf"]').goto_definitions() assert Script('import sys\nsys.modules["alshdb;lasdhf"]').infer()
def test_getitem_on_none(Script): def test_getitem_on_none(Script):
script = Script('None[1j]') script = Script('None[1j]')
assert not script.goto_definitions() assert not script.infer()
issue, = script._inference_state.analysis issue, = script._inference_state.analysis
assert issue.name == 'type-error-not-subscriptable' assert issue.name == 'type-error-not-subscriptable'
+4 -4
View File
@@ -2,7 +2,7 @@ from jedi._compatibility import force_unicode
def test_module_attributes(Script): def test_module_attributes(Script):
def_, = Script('__name__').completions() def_, = Script('__name__').complete()
assert def_.name == '__name__' assert def_.name == '__name__'
assert def_.line is None assert def_.line is None
assert def_.column is None assert def_.column is None
@@ -11,11 +11,11 @@ def test_module_attributes(Script):
def test_module__file__(Script, environment): def test_module__file__(Script, environment):
assert not Script('__file__').goto_definitions() assert not Script('__file__').infer()
def_, = Script('__file__', path='example.py').goto_definitions() def_, = Script('__file__', path='example.py').infer()
value = force_unicode(def_._name._value.get_safe_value()) value = force_unicode(def_._name._value.get_safe_value())
assert value.endswith('example.py') assert value.endswith('example.py')
def_, = Script('import antigravity; antigravity.__file__').goto_definitions() def_, = Script('import antigravity; antigravity.__file__').infer()
value = force_unicode(def_._name._value.get_safe_value()) value = force_unicode(def_._name._value.get_safe_value())
assert value.endswith('.py') assert value.endswith('.py')
+27 -27
View File
@@ -32,7 +32,7 @@ def test_function_doc(Script):
defs = Script(""" defs = Script("""
def func(): def func():
'''Docstring of `func`.''' '''Docstring of `func`.'''
func""").goto_definitions() func""").infer()
assert defs[0].docstring() == 'func()\n\nDocstring of `func`.' assert defs[0].docstring() == 'func()\n\nDocstring of `func`.'
@@ -40,7 +40,7 @@ def test_class_doc(Script):
defs = Script(""" defs = Script("""
class TestClass(): class TestClass():
'''Docstring of `TestClass`.''' '''Docstring of `TestClass`.'''
TestClass""").goto_definitions() TestClass""").infer()
expected = 'Docstring of `TestClass`.' expected = 'Docstring of `TestClass`.'
assert defs[0].docstring(raw=True) == expected assert defs[0].docstring(raw=True) == expected
@@ -52,7 +52,7 @@ def test_class_doc_with_init(Script):
class TestClass(): class TestClass():
'''Docstring''' '''Docstring'''
def __init__(self, foo, bar=3): pass def __init__(self, foo, bar=3): pass
TestClass""").goto_definitions() TestClass""").infer()
assert d.docstring() == 'TestClass(foo, bar=3)\n\nDocstring' assert d.docstring() == 'TestClass(foo, bar=3)\n\nDocstring'
@@ -62,7 +62,7 @@ def test_instance_doc(Script):
class TestClass(): class TestClass():
'''Docstring of `TestClass`.''' '''Docstring of `TestClass`.'''
tc = TestClass() tc = TestClass()
tc""").goto_definitions() tc""").infer()
assert defs[0].docstring() == 'Docstring of `TestClass`.' assert defs[0].docstring() == 'Docstring of `TestClass`.'
@@ -71,7 +71,7 @@ def test_attribute_docstring(Script):
defs = Script(""" defs = Script("""
x = None x = None
'''Docstring of `x`.''' '''Docstring of `x`.'''
x""").goto_definitions() x""").infer()
assert defs[0].docstring() == 'Docstring of `x`.' assert defs[0].docstring() == 'Docstring of `x`.'
@@ -82,7 +82,7 @@ def test_multiple_docstrings(Script):
'''Original docstring.''' '''Original docstring.'''
x = func x = func
'''Docstring of `x`.''' '''Docstring of `x`.'''
x""").goto_definitions() x""").infer()
docs = [d.docstring() for d in defs] docs = [d.docstring() for d in defs]
assert docs == ['Original docstring.', 'Docstring of `x`.'] assert docs == ['Original docstring.', 'Docstring of `x`.']
@@ -91,7 +91,7 @@ def test_completion(Script):
assert Script(''' assert Script('''
class DocstringCompletion(): class DocstringCompletion():
#? [] #? []
""" asdfas """''').completions() """ asdfas """''').complete()
def test_docstrings_type_dotted_import(Script): def test_docstrings_type_dotted_import(Script):
@@ -101,7 +101,7 @@ def test_docstrings_type_dotted_import(Script):
:type arg: random.Random :type arg: random.Random
''' '''
arg.""" arg."""
names = [c.name for c in Script(s).completions()] names = [c.name for c in Script(s).complete()]
assert 'seed' in names assert 'seed' in names
@@ -112,7 +112,7 @@ def test_docstrings_param_type(Script):
:param str arg: some description :param str arg: some description
''' '''
arg.""" arg."""
names = [c.name for c in Script(s).completions()] names = [c.name for c in Script(s).complete()]
assert 'join' in names assert 'join' in names
@@ -124,7 +124,7 @@ def test_docstrings_type_str(Script):
''' '''
arg.""" arg."""
names = [c.name for c in Script(s).completions()] names = [c.name for c in Script(s).complete()]
assert 'join' in names assert 'join' in names
@@ -150,14 +150,14 @@ def test_docstring_instance(Script):
c.""") c.""")
names = [c.name for c in Script(s).completions()] names = [c.name for c in Script(s).complete()]
assert 'a' in names assert 'a' in names
assert '__init__' in names assert '__init__' in names
assert 'mro' not in names # Exists only for types. assert 'mro' not in names # Exists only for types.
def test_docstring_keyword(Script): def test_docstring_keyword(Script):
completions = Script('assert').completions() completions = Script('assert').complete()
assert 'assert' in completions[0].docstring() assert 'assert' in completions[0].docstring()
@@ -167,7 +167,7 @@ def test_docstring_params_formatting(Script):
param2, param2,
param3): param3):
pass pass
func""").goto_definitions() func""").infer()
assert defs[0].docstring() == 'func(param1, param2, param3)' assert defs[0].docstring() == 'func(param1, param2, param3)'
@@ -185,7 +185,7 @@ def test_numpydoc_parameters():
y : str y : str
""" """
y.''') y.''')
names = [c.name for c in jedi.Script(s).completions()] names = [c.name for c in jedi.Script(s).complete()]
assert 'isupper' in names assert 'isupper' in names
assert 'capitalize' in names assert 'capitalize' in names
@@ -201,7 +201,7 @@ def test_numpydoc_parameters_set_of_values():
x : {'foo', 'bar', 100500}, optional x : {'foo', 'bar', 100500}, optional
""" """
x.''') x.''')
names = [c.name for c in jedi.Script(s).completions()] names = [c.name for c in jedi.Script(s).complete()]
assert 'isupper' in names assert 'isupper' in names
assert 'capitalize' in names assert 'capitalize' in names
assert 'numerator' in names assert 'numerator' in names
@@ -218,7 +218,7 @@ def test_numpydoc_parameters_alternative_types():
x : int or str or list x : int or str or list
""" """
x.''') x.''')
names = [c.name for c in jedi.Script(s).completions()] names = [c.name for c in jedi.Script(s).complete()]
assert 'isupper' in names assert 'isupper' in names
assert 'capitalize' in names assert 'capitalize' in names
assert 'numerator' in names assert 'numerator' in names
@@ -237,7 +237,7 @@ def test_numpydoc_invalid():
""" """
x.''') x.''')
assert not jedi.Script(s).completions() assert not jedi.Script(s).complete()
@pytest.mark.skipif(numpydoc_unavailable, @pytest.mark.skipif(numpydoc_unavailable,
@@ -256,7 +256,7 @@ def test_numpydoc_returns():
def bazbiz(): def bazbiz():
z = foobar() z = foobar()
z.''') z.''')
names = [c.name for c in jedi.Script(s).completions()] names = [c.name for c in jedi.Script(s).complete()]
assert 'isupper' in names assert 'isupper' in names
assert 'capitalize' in names assert 'capitalize' in names
assert 'numerator' in names assert 'numerator' in names
@@ -277,7 +277,7 @@ def test_numpydoc_returns_set_of_values():
def bazbiz(): def bazbiz():
z = foobar() z = foobar()
z.''') z.''')
names = [c.name for c in jedi.Script(s).completions()] names = [c.name for c in jedi.Script(s).complete()]
assert 'isupper' in names assert 'isupper' in names
assert 'capitalize' in names assert 'capitalize' in names
assert 'numerator' in names assert 'numerator' in names
@@ -298,7 +298,7 @@ def test_numpydoc_returns_alternative_types():
def bazbiz(): def bazbiz():
z = foobar() z = foobar()
z.''') z.''')
names = [c.name for c in jedi.Script(s).completions()] names = [c.name for c in jedi.Script(s).complete()]
assert 'isupper' not in names assert 'isupper' not in names
assert 'capitalize' not in names assert 'capitalize' not in names
assert 'numerator' in names assert 'numerator' in names
@@ -320,7 +320,7 @@ def test_numpydoc_returns_list_of():
def bazbiz(): def bazbiz():
z = foobar() z = foobar()
z.''') z.''')
names = [c.name for c in jedi.Script(s).completions()] names = [c.name for c in jedi.Script(s).complete()]
assert 'append' in names assert 'append' in names
assert 'isupper' not in names assert 'isupper' not in names
assert 'capitalize' not in names assert 'capitalize' not in names
@@ -342,7 +342,7 @@ def test_numpydoc_returns_obj():
z = foobar(x, y) z = foobar(x, y)
z.''') z.''')
script = jedi.Script(s) script = jedi.Script(s)
names = [c.name for c in script.completions()] names = [c.name for c in script.complete()]
assert 'numerator' in names assert 'numerator' in names
assert 'seed' in names assert 'seed' in names
@@ -363,7 +363,7 @@ def test_numpydoc_yields():
def bazbiz(): def bazbiz():
z = foobar(): z = foobar():
z.''') z.''')
names = [c.name for c in jedi.Script(s).completions()] names = [c.name for c in jedi.Script(s).complete()]
assert 'isupper' in names assert 'isupper' in names
assert 'capitalize' in names assert 'capitalize' in names
assert 'numerator' in names assert 'numerator' in names
@@ -377,7 +377,7 @@ def test_numpy_returns():
x = numpy.asarray([]) x = numpy.asarray([])
x.d''' x.d'''
) )
names = [c.name for c in jedi.Script(s).completions()] names = [c.name for c in jedi.Script(s).complete()]
assert 'diagonal' in names assert 'diagonal' in names
@@ -389,7 +389,7 @@ def test_numpy_comp_returns():
x = numpy.array([]) x = numpy.array([])
x.d''' x.d'''
) )
names = [c.name for c in jedi.Script(s).completions()] names = [c.name for c in jedi.Script(s).complete()]
assert 'diagonal' in names assert 'diagonal' in names
@@ -412,7 +412,7 @@ def test_decorator(Script):
check_user''') check_user''')
d, = Script(code).goto_definitions() d, = Script(code).infer()
assert d.docstring(raw=True) == 'Nice docstring' assert d.docstring(raw=True) == 'Nice docstring'
@@ -422,5 +422,5 @@ def test_basic_str_init_signature(Script, disable_typeshed):
class Foo(str): class Foo(str):
pass pass
Foo(''') Foo(''')
c, = Script(code).call_signatures() c, = Script(code).find_signatures()
assert c.name == 'Foo' assert c.name == 'Foo'
+7 -7
View File
@@ -10,10 +10,10 @@ import pytest
def test_completions(Script): def test_completions(Script):
s = Script('import _ctypes; _ctypes.') s = Script('import _ctypes; _ctypes.')
assert len(s.completions()) >= 15 assert len(s.complete()) >= 15
def test_call_signatures_extension(Script): def test_find_signatures_extension(Script):
if os.name == 'nt': if os.name == 'nt':
func = 'LoadLibrary' func = 'LoadLibrary'
params = 1 params = 1
@@ -21,14 +21,14 @@ def test_call_signatures_extension(Script):
func = 'dlopen' func = 'dlopen'
params = 2 params = 2
s = Script('import _ctypes; _ctypes.%s(' % (func,)) s = Script('import _ctypes; _ctypes.%s(' % (func,))
sigs = s.call_signatures() sigs = s.find_signatures()
assert len(sigs) == 1 assert len(sigs) == 1
assert len(sigs[0].params) == params assert len(sigs[0].params) == params
def test_call_signatures_stdlib(Script): def test_find_signatures_stdlib(Script):
s = Script('import math; math.cos(') s = Script('import math; math.cos(')
sigs = s.call_signatures() sigs = s.find_signatures()
assert len(sigs) == 1 assert len(sigs) == 1
assert len(sigs[0].params) == 1 assert len(sigs[0].params) == 1
@@ -51,7 +51,7 @@ def test_init_extension_module(Script):
This is also why this test only runs on certain systems (and Python 3.4). 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') s = jedi.Script('import init_extension_module as i\ni.', path='not_existing.py')
assert 'foo' in [c.name for c in s.completions()] assert 'foo' in [c.name for c in s.complete()]
s = jedi.Script('from init_extension_module import foo\nfoo', path='not_existing.py') s = jedi.Script('from init_extension_module import foo\nfoo', path='not_existing.py')
assert ['foo'] == [c.name for c in s.completions()] assert ['foo'] == [c.name for c in s.complete()]
+2 -3
View File
@@ -13,7 +13,6 @@ def test_fstring_multiline(Script):
'' f'''s{ '' f'''s{
str.uppe str.uppe
''' '''
""" """)
) c, = Script(code).complete(line=2, column=9)
c, = Script(code, line=2, column=9).completions()
assert c.name == 'upper' assert c.name == 'upper'
@@ -7,18 +7,18 @@ from jedi.inference.gradual.conversion import convert_names
def test_sqlite3_conversion(Script): def test_sqlite3_conversion(Script):
script1 = Script('import sqlite3; sqlite3.Connection') script1 = Script('import sqlite3; sqlite3.Connection')
d, = script1.goto_definitions() d, = script1.infer()
assert not d.module_path assert not d.module_path
assert d.full_name == 'sqlite3.Connection' assert d.full_name == 'sqlite3.Connection'
assert convert_names([d._name], only_stubs=True) assert convert_names([d._name], only_stubs=True)
d, = script1.goto_definitions(only_stubs=True) d, = script1.infer(only_stubs=True)
assert d.is_stub() assert d.is_stub()
assert d.full_name == 'sqlite3.dbapi2.Connection' assert d.full_name == 'sqlite3.dbapi2.Connection'
script2 = Script(path=d.module_path, line=d.line, column=d.column) script2 = Script(path=d.module_path)
d, = script2.goto_definitions() d, = script2.infer(line=d.line, column=d.column)
assert not d.is_stub() assert not d.is_stub()
assert d.full_name == 'sqlite3.Connection' assert d.full_name == 'sqlite3.Connection'
v, = d._name.infer() v, = d._name.infer()
@@ -28,11 +28,11 @@ def test_sqlite3_conversion(Script):
def test_conversion_of_stub_only(Script): def test_conversion_of_stub_only(Script):
project = Project(os.path.join(root_dir, 'test', 'completion', 'stub_folder')) project = Project(os.path.join(root_dir, 'test', 'completion', 'stub_folder'))
code = 'import stub_only; stub_only.in_stub_only' code = 'import stub_only; stub_only.in_stub_only'
d1, = Script(code, _project=project).goto_assignments() d1, = Script(code, _project=project).goto()
assert d1.is_stub() assert d1.is_stub()
script = Script(path=d1.module_path, line=d1.line, column=d1.column, _project=project) script = Script(path=d1.module_path, _project=project)
d2, = script.goto_assignments() d2, = script.goto(line=d1.line, column=d1.column)
assert d2.is_stub() assert d2.is_stub()
assert d2.module_path == d1.module_path assert d2.module_path == d1.module_path
assert d2.line == d1.line assert d2.line == d1.line
@@ -43,7 +43,7 @@ def test_conversion_of_stub_only(Script):
def test_goto_on_file(Script): def test_goto_on_file(Script):
project = Project(os.path.join(root_dir, 'test', 'completion', 'stub_folder')) project = Project(os.path.join(root_dir, 'test', 'completion', 'stub_folder'))
script = Script('import stub_only; stub_only.Foo', _project=project) script = Script('import stub_only; stub_only.Foo', _project=project)
d1, = script.goto_assignments() d1, = script.goto()
v, = d1._name.infer() v, = d1._name.infer()
foo, bar, obj = v.py__mro__() foo, bar, obj = v.py__mro__()
assert foo.py__name__() == 'Foo' assert foo.py__name__() == 'Foo'
@@ -51,6 +51,6 @@ def test_goto_on_file(Script):
assert obj.py__name__() == 'object' assert obj.py__name__() == 'object'
# Make sure we go to Bar, because Foo is a bit before: `class Foo(Bar):` # Make sure we go to Bar, because Foo is a bit before: `class Foo(Bar):`
script = Script(path=d1.module_path, line=d1.line, column=d1.column + 4, _project=project) script = Script(path=d1.module_path, _project=project)
d2, = script.goto_assignments() d2, = script.goto(line=d1.line, column=d1.column + 4)
assert d2.name == 'Bar' assert d2.name == 'Bar'
@@ -23,5 +23,5 @@ def ScriptInStubFolder(Script):
] ]
) )
def test_find_stubs_infer(ScriptInStubFolder, code, expected): def test_find_stubs_infer(ScriptInStubFolder, code, expected):
defs = ScriptInStubFolder(code).goto_definitions() defs = ScriptInStubFolder(code).infer()
assert [d.name for d in defs] == expected assert [d.name for d in defs] == expected
@@ -64,17 +64,17 @@ def test_infer_and_goto(Script, code, full_name, has_stub, has_python, way,
if way == 'direct': if way == 'direct':
if type_ == 'goto': if type_ == 'goto':
defs = s.goto_assignments(follow_imports=True, **kwargs) defs = s.goto(follow_imports=True, **kwargs)
else: else:
defs = s.goto_definitions(**kwargs) defs = s.infer(**kwargs)
else: else:
goto_defs = s.goto_assignments( goto_defs = s.goto(
# Prefering stubs when we want to go to python and vice versa # Prefering stubs when we want to go to python and vice versa
prefer_stubs=not (prefer_stubs or only_stubs), prefer_stubs=not (prefer_stubs or only_stubs),
follow_imports=True, follow_imports=True,
) )
if type_ == 'goto': if type_ == 'goto':
defs = [d for goto_def in goto_defs for d in goto_def.goto_assignments(**kwargs)] defs = [d for goto_def in goto_defs for d in goto_def.goto(**kwargs)]
else: else:
defs = [d for goto_def in goto_defs for d in goto_def.infer(**kwargs)] defs = [d for goto_def in goto_defs for d in goto_def.infer(**kwargs)]
@@ -46,53 +46,53 @@ def test_get_stub_files():
def test_function(Script, environment): def test_function(Script, environment):
code = 'import threading; threading.current_thread' code = 'import threading; threading.current_thread'
def_, = Script(code).goto_definitions() def_, = Script(code).infer()
value = def_._name._value value = def_._name._value
assert isinstance(value, FunctionValue), value assert isinstance(value, FunctionValue), value
def_, = Script(code + '()').goto_definitions() def_, = Script(code + '()').infer()
value = def_._name._value value = def_._name._value
assert isinstance(value, TreeInstance) assert isinstance(value, TreeInstance)
def_, = Script('import threading; threading.Thread').goto_definitions() def_, = Script('import threading; threading.Thread').infer()
assert isinstance(def_._name._value, ClassValue), def_ assert isinstance(def_._name._value, ClassValue), def_
def test_keywords_variable(Script): def test_keywords_variable(Script):
code = 'import keyword; keyword.kwlist' code = 'import keyword; keyword.kwlist'
for seq in Script(code).goto_definitions(): for seq in Script(code).infer():
assert seq.name == 'Sequence' assert seq.name == 'Sequence'
# This points towards the typeshed implementation # This points towards the typeshed implementation
stub_seq, = seq.goto_assignments(only_stubs=True) stub_seq, = seq.goto(only_stubs=True)
assert typeshed.TYPESHED_PATH in stub_seq.module_path assert typeshed.TYPESHED_PATH in stub_seq.module_path
def test_class(Script): def test_class(Script):
def_, = Script('import threading; threading.Thread').goto_definitions() def_, = Script('import threading; threading.Thread').infer()
value = def_._name._value value = def_._name._value
assert isinstance(value, ClassValue), value assert isinstance(value, ClassValue), value
def test_instance(Script): def test_instance(Script):
def_, = Script('import threading; threading.Thread()').goto_definitions() def_, = Script('import threading; threading.Thread()').infer()
value = def_._name._value value = def_._name._value
assert isinstance(value, TreeInstance) assert isinstance(value, TreeInstance)
def test_class_function(Script): def test_class_function(Script):
def_, = Script('import threading; threading.Thread.getName').goto_definitions() def_, = Script('import threading; threading.Thread.getName').infer()
value = def_._name._value value = def_._name._value
assert isinstance(value, MethodValue), value assert isinstance(value, MethodValue), value
def test_method(Script): def test_method(Script):
code = 'import threading; threading.Thread().getName' code = 'import threading; threading.Thread().getName'
def_, = Script(code).goto_definitions() def_, = Script(code).infer()
value = def_._name._value value = def_._name._value
assert isinstance(value, BoundMethod), value assert isinstance(value, BoundMethod), value
assert isinstance(value._wrapped_value, MethodValue), value assert isinstance(value._wrapped_value, MethodValue), value
def_, = Script(code + '()').goto_definitions() def_, = Script(code + '()').infer()
value = def_._name._value value = def_._name._value
assert isinstance(value, TreeInstance) assert isinstance(value, TreeInstance)
assert value.class_value.py__name__() == 'str' assert value.class_value.py__name__() == 'str'
@@ -100,13 +100,13 @@ def test_method(Script):
def test_sys_exc_info(Script): def test_sys_exc_info(Script):
code = 'import sys; sys.exc_info()' code = 'import sys; sys.exc_info()'
none, def_ = Script(code + '[1]').goto_definitions() none, def_ = Script(code + '[1]').infer()
# It's an optional. # It's an optional.
assert def_.name == 'BaseException' assert def_.name == 'BaseException'
assert def_.type == 'instance' assert def_.type == 'instance'
assert none.name == 'NoneType' assert none.name == 'NoneType'
none, def_ = Script(code + '[0]').goto_definitions() none, def_ = Script(code + '[0]').infer()
assert def_.name == 'BaseException' assert def_.name == 'BaseException'
assert def_.type == 'class' assert def_.type == 'class'
@@ -114,7 +114,7 @@ def test_sys_exc_info(Script):
def test_sys_getwindowsversion(Script, environment): def test_sys_getwindowsversion(Script, environment):
# This should only exist on Windows, but type inference should happen # This should only exist on Windows, but type inference should happen
# everywhere. # everywhere.
definitions = Script('import sys; sys.getwindowsversion().major').goto_definitions() definitions = Script('import sys; sys.getwindowsversion().major').infer()
if environment.version_info.major == 2: if environment.version_info.major == 2:
assert not definitions assert not definitions
else: else:
@@ -124,22 +124,22 @@ def test_sys_getwindowsversion(Script, environment):
def test_sys_hexversion(Script): def test_sys_hexversion(Script):
script = Script('import sys; sys.hexversion') script = Script('import sys; sys.hexversion')
def_, = script.completions() def_, = script.complete()
assert isinstance(def_._name, stub_value._StubName), def_._name assert isinstance(def_._name, stub_value._StubName), def_._name
assert typeshed.TYPESHED_PATH in def_.module_path assert typeshed.TYPESHED_PATH in def_.module_path
def_, = script.goto_definitions() def_, = script.infer()
assert def_.name == 'int' assert def_.name == 'int'
def test_math(Script): def test_math(Script):
def_, = Script('import math; math.acos()').goto_definitions() def_, = Script('import math; math.acos()').infer()
assert def_.name == 'float' assert def_.name == 'float'
value = def_._name._value value = def_._name._value
assert value assert value
def test_type_var(Script): def test_type_var(Script):
def_, = Script('import typing; T = typing.TypeVar("T1")').goto_definitions() def_, = Script('import typing; T = typing.TypeVar("T1")').infer()
assert def_.name == 'TypeVar' assert def_.name == 'TypeVar'
assert def_.description == 'TypeVar = object()' assert def_.description == 'TypeVar = object()'
@@ -152,29 +152,29 @@ def test_type_var(Script):
) )
def test_math_is_stub(Script, code, full_name): def test_math_is_stub(Script, code, full_name):
s = Script(code) s = Script(code)
cos, = s.goto_definitions() cos, = s.infer()
wanted = os.path.join('typeshed', 'stdlib', '2and3', 'math.pyi') wanted = os.path.join('typeshed', 'stdlib', '2and3', 'math.pyi')
assert cos.module_path.endswith(wanted) assert cos.module_path.endswith(wanted)
assert cos.is_stub() is True assert cos.is_stub() is True
assert cos.goto_assignments(only_stubs=True) == [cos] assert cos.goto(only_stubs=True) == [cos]
assert cos.full_name == full_name assert cos.full_name == full_name
cos, = s.goto_assignments() cos, = s.goto()
assert cos.module_path.endswith(wanted) assert cos.module_path.endswith(wanted)
assert cos.goto_assignments(only_stubs=True) == [cos] assert cos.goto(only_stubs=True) == [cos]
assert cos.is_stub() is True assert cos.is_stub() is True
assert cos.full_name == full_name assert cos.full_name == full_name
def test_goto_stubs(Script): def test_goto_stubs(Script):
s = Script('import os; os') s = Script('import os; os')
os_module, = s.goto_definitions() os_module, = s.infer()
assert os_module.full_name == 'os' assert os_module.full_name == 'os'
assert os_module.is_stub() is False assert os_module.is_stub() is False
stub, = os_module.goto_assignments(only_stubs=True) stub, = os_module.goto(only_stubs=True)
assert stub.is_stub() is True assert stub.is_stub() is True
os_module, = s.goto_assignments() os_module, = s.goto()
def _assert_is_same(d1, d2): def _assert_is_same(d1, d2):
@@ -199,21 +199,17 @@ def test_goto_stubs_on_itself(Script, code, type_):
""" """
s = Script(code) s = Script(code)
if type_ == 'infer': if type_ == 'infer':
def_, = s.goto_definitions() def_, = s.infer()
else: else:
def_, = s.goto_assignments(follow_imports=True) def_, = s.goto(follow_imports=True)
stub, = def_.goto_assignments(only_stubs=True) stub, = def_.goto(only_stubs=True)
script_on_source = Script( script_on_source = Script(path=def_.module_path)
path=def_.module_path,
line=def_.line,
column=def_.column
)
if type_ == 'infer': if type_ == 'infer':
definition, = script_on_source.goto_definitions() definition, = script_on_source.infer(def_.line, def_.column)
else: else:
definition, = script_on_source.goto_assignments() definition, = script_on_source.goto(def_.line, def_.column)
same_stub, = definition.goto_assignments(only_stubs=True) same_stub, = definition.goto(only_stubs=True)
_assert_is_same(same_stub, stub) _assert_is_same(same_stub, stub)
_assert_is_same(definition, def_) _assert_is_same(definition, def_)
assert same_stub.module_path != def_.module_path assert same_stub.module_path != def_.module_path
@@ -221,16 +217,14 @@ def test_goto_stubs_on_itself(Script, code, type_):
# And the reverse. # And the reverse.
script_on_stub = Script( script_on_stub = Script(
path=same_stub.module_path, path=same_stub.module_path,
line=same_stub.line,
column=same_stub.column
) )
if type_ == 'infer': if type_ == 'infer':
same_definition, = script_on_stub.goto_definitions() same_definition, = script_on_stub.infer(same_stub.line, same_stub.column)
same_definition2, = same_stub.infer() same_definition2, = same_stub.infer()
else: else:
same_definition, = script_on_stub.goto_assignments() same_definition, = script_on_stub.goto(same_stub.line, same_stub.column)
same_definition2, = same_stub.goto_assignments() same_definition2, = same_stub.goto()
_assert_is_same(same_definition, definition) _assert_is_same(same_definition, definition)
_assert_is_same(same_definition, same_definition2) _assert_is_same(same_definition, same_definition2)
+2 -3
View File
@@ -1,15 +1,14 @@
from textwrap import dedent from textwrap import dedent
from jedi import names
from jedi.inference import helpers from jedi.inference import helpers
def test_call_of_leaf_in_brackets(environment): def test_call_of_leaf_in_brackets(Script):
s = dedent(""" s = dedent("""
x = 1 x = 1
type(x) type(x)
""") """)
last_x = names(s, references=True, definitions=False, environment=environment)[-1] last_x = Script(s).names(references=True, definitions=False)[-1]
name = last_x._name.tree_name name = last_x._name.tree_name
call = helpers.call_of_leaf(name) call = helpers.call_of_leaf(name)
@@ -17,9 +17,9 @@ def test_implicit_namespace_package(Script):
return Script(sys_path=sys_path, *args, **kwargs) return Script(sys_path=sys_path, *args, **kwargs)
# goto definition # goto definition
assert script_with_path('from pkg import ns1_file').goto_definitions() assert script_with_path('from pkg import ns1_file').infer()
assert script_with_path('from pkg import ns2_file').goto_definitions() assert script_with_path('from pkg import ns2_file').infer()
assert not script_with_path('from pkg import ns3_file').goto_definitions() assert not script_with_path('from pkg import ns3_file').infer()
# goto assignment # goto assignment
tests = { tests = {
@@ -27,12 +27,12 @@ def test_implicit_namespace_package(Script):
'from pkg.ns1_file import foo': 'ns1_file!', 'from pkg.ns1_file import foo': 'ns1_file!',
} }
for source, solution in tests.items(): for source, solution in tests.items():
ass = script_with_path(source).goto_assignments() ass = script_with_path(source).goto()
assert len(ass) == 1 assert len(ass) == 1
assert ass[0].description == "foo = '%s'" % solution assert ass[0].description == "foo = '%s'" % solution
# completion # completion
completions = script_with_path('from pkg import ').completions() completions = script_with_path('from pkg import ').complete()
names = [c.name for c in completions] names = [c.name for c in completions]
compare = ['ns1_file', 'ns2_file'] compare = ['ns1_file', 'ns2_file']
# must at least contain these items, other items are not important # must at least contain these items, other items are not important
@@ -43,7 +43,7 @@ def test_implicit_namespace_package(Script):
'from pkg import ns1_file as x': 'ns1_file!' 'from pkg import ns1_file as x': 'ns1_file!'
} }
for source, solution in tests.items(): for source, solution in tests.items():
for c in script_with_path(source + '; x.').completions(): for c in script_with_path(source + '; x.').complete():
if c.name == 'foo': if c.name == 'foo':
completion = c completion = c
solution = "foo = '%s'" % solution solution = "foo = '%s'" % solution
@@ -57,11 +57,11 @@ def test_implicit_nested_namespace_package(Script):
script = Script(sys_path=sys_path, source=code, line=1, column=61) script = Script(sys_path=sys_path, source=code, line=1, column=61)
result = script.goto_definitions() result = script.infer()
assert len(result) == 1 assert len(result) == 1
implicit_pkg, = Script(code, column=10, sys_path=sys_path).goto_definitions() implicit_pkg, = Script(code, sys_path=sys_path).infer(column=10)
assert implicit_pkg.type == 'module' assert implicit_pkg.type == 'module'
assert implicit_pkg.module_path is None assert implicit_pkg.module_path is None
@@ -72,7 +72,7 @@ def test_implicit_namespace_package_import_autocomplete(Script):
sys_path = [dirname(__file__)] sys_path = [dirname(__file__)]
script = Script(sys_path=sys_path, source=CODE) script = Script(sys_path=sys_path, source=CODE)
compl = script.completions() compl = script.complete()
assert [c.name for c in compl] == ['implicit_namespace_package'] assert [c.name for c in compl] == ['implicit_namespace_package']
@@ -82,7 +82,7 @@ def test_namespace_package_in_multiple_directories_autocompletion(Script):
for d in ['implicit_namespace_package/ns1', 'implicit_namespace_package/ns2']] for d in ['implicit_namespace_package/ns1', 'implicit_namespace_package/ns2']]
script = Script(sys_path=sys_path, source=CODE) script = Script(sys_path=sys_path, source=CODE)
compl = script.completions() compl = script.complete()
assert set(c.name for c in compl) == set(['ns1_file', 'ns2_file']) assert set(c.name for c in compl) == set(['ns1_file', 'ns2_file'])
@@ -91,7 +91,7 @@ def test_namespace_package_in_multiple_directories_goto_definition(Script):
sys_path = [join(dirname(__file__), d) sys_path = [join(dirname(__file__), d)
for d in ['implicit_namespace_package/ns1', 'implicit_namespace_package/ns2']] for d in ['implicit_namespace_package/ns1', 'implicit_namespace_package/ns2']]
script = Script(sys_path=sys_path, source=CODE) script = Script(sys_path=sys_path, source=CODE)
result = script.goto_definitions() result = script.infer()
assert len(result) == 1 assert len(result) == 1
@@ -101,5 +101,5 @@ def test_namespace_name_autocompletion_full_name(Script):
for d in ['implicit_namespace_package/ns1', 'implicit_namespace_package/ns2']] for d in ['implicit_namespace_package/ns1', 'implicit_namespace_package/ns2']]
script = Script(sys_path=sys_path, source=CODE) script = Script(sys_path=sys_path, source=CODE)
compl = script.completions() compl = script.complete()
assert set(c.full_name for c in compl) == set(['pkg']) assert set(c.full_name for c in compl) == set(['pkg'])
+50 -50
View File
@@ -46,7 +46,7 @@ pkg_zip_path = os.path.join(os.path.dirname(__file__),
def test_find_module_package_zipped(Script, inference_state, environment): def test_find_module_package_zipped(Script, inference_state, environment):
sys_path = environment.get_sys_path() + [pkg_zip_path] sys_path = environment.get_sys_path() + [pkg_zip_path]
script = Script('import pkg; pkg.mod', sys_path=sys_path) script = Script('import pkg; pkg.mod', sys_path=sys_path)
assert len(script.completions()) == 1 assert len(script.complete()) == 1
file_io, is_package = inference_state.compiled_subprocess.get_module_info( file_io, is_package = inference_state.compiled_subprocess.get_module_info(
sys_path=sys_path, sys_path=sys_path,
@@ -87,7 +87,7 @@ def test_find_module_package_zipped(Script, inference_state, environment):
def test_correct_zip_package_behavior(Script, inference_state, environment, code, def test_correct_zip_package_behavior(Script, inference_state, environment, code,
file, package, path, skip_python2): file, package, path, skip_python2):
sys_path = environment.get_sys_path() + [pkg_zip_path] sys_path = environment.get_sys_path() + [pkg_zip_path]
pkg, = Script(code, sys_path=sys_path).goto_definitions() pkg, = Script(code, sys_path=sys_path).infer()
value, = pkg._name.infer() value, = pkg._name.infer()
assert value.py__file__() == os.path.join(pkg_zip_path, 'pkg', file) assert value.py__file__() == os.path.join(pkg_zip_path, 'pkg', file)
assert '.'.join(value.py__package__()) == package assert '.'.join(value.py__package__()) == package
@@ -100,7 +100,7 @@ def test_find_module_not_package_zipped(Script, inference_state, environment):
path = os.path.join(os.path.dirname(__file__), 'zipped_imports/not_pkg.zip') path = os.path.join(os.path.dirname(__file__), 'zipped_imports/not_pkg.zip')
sys_path = environment.get_sys_path() + [path] sys_path = environment.get_sys_path() + [path]
script = Script('import not_pkg; not_pkg.val', sys_path=sys_path) script = Script('import not_pkg; not_pkg.val', sys_path=sys_path)
assert len(script.completions()) == 1 assert len(script.complete()) == 1
file_io, is_package = inference_state.compiled_subprocess.get_module_info( file_io, is_package = inference_state.compiled_subprocess.get_module_info(
sys_path=sys_path, sys_path=sys_path,
@@ -118,12 +118,12 @@ def test_import_not_in_sys_path(Script):
This is in the end just a fallback. This is in the end just a fallback.
""" """
a = Script(path='module.py', line=5).goto_definitions() a = Script(path='module.py').infer(line=5)
assert a[0].name == 'int' assert a[0].name == 'int'
a = Script(path='module.py', line=6).goto_definitions() a = Script(path='module.py').infer(line=6)
assert a[0].name == 'str' assert a[0].name == 'str'
a = Script(path='module.py', line=7).goto_definitions() a = Script(path='module.py').infer(line=7)
assert a[0].name == 'str' assert a[0].name == 'str'
@@ -145,19 +145,19 @@ def test_flask_ext(Script, code, name):
"""flask.ext.foo is really imported from flaskext.foo or flask_foo. """flask.ext.foo is really imported from flaskext.foo or flask_foo.
""" """
path = os.path.join(os.path.dirname(__file__), 'flask-site-packages') path = os.path.join(os.path.dirname(__file__), 'flask-site-packages')
completions = Script(code, sys_path=[path]).completions() completions = Script(code, sys_path=[path]).complete()
assert name in [c.name for c in completions] assert name in [c.name for c in completions]
@cwd_at('test/test_inference/') @cwd_at('test/test_inference/')
def test_not_importable_file(Script): def test_not_importable_file(Script):
src = 'import not_importable_file as x; x.' src = 'import not_importable_file as x; x.'
assert not Script(src, path='example.py').completions() assert not Script(src, path='example.py').complete()
def test_import_unique(Script): def test_import_unique(Script):
src = "import os; os.path" src = "import os; os.path"
defs = Script(src, path='example.py').goto_definitions() defs = Script(src, path='example.py').infer()
parent_contexts = [d._name._value for d in defs] parent_contexts = [d._name._value for d in defs]
assert len(parent_contexts) == len(set(parent_contexts)) assert len(parent_contexts) == len(set(parent_contexts))
@@ -168,9 +168,9 @@ def test_cache_works_with_sys_path_param(Script, tmpdir):
foo_path.join('module.py').write('foo = 123', ensure=True) foo_path.join('module.py').write('foo = 123', ensure=True)
bar_path.join('module.py').write('bar = 123', ensure=True) bar_path.join('module.py').write('bar = 123', ensure=True)
foo_completions = Script('import module; module.', foo_completions = Script('import module; module.',
sys_path=[foo_path.strpath]).completions() sys_path=[foo_path.strpath]).complete()
bar_completions = Script('import module; module.', bar_completions = Script('import module; module.',
sys_path=[bar_path.strpath]).completions() sys_path=[bar_path.strpath]).complete()
assert 'foo' in [c.name for c in foo_completions] assert 'foo' in [c.name for c in foo_completions]
assert 'bar' not in [c.name for c in foo_completions] assert 'bar' not in [c.name for c in foo_completions]
@@ -181,7 +181,7 @@ def test_cache_works_with_sys_path_param(Script, tmpdir):
def test_import_completion_docstring(Script): def test_import_completion_docstring(Script):
import abc import abc
s = Script('"""test"""\nimport ab') s = Script('"""test"""\nimport ab')
abc_completions = [c for c in s.completions() if c.name == 'abc'] abc_completions = [c for c in s.complete() if c.name == 'abc']
assert len(abc_completions) == 1 assert len(abc_completions) == 1
assert abc_completions[0].docstring(fast=False) == abc.__doc__ assert abc_completions[0].docstring(fast=False) == abc.__doc__
@@ -191,72 +191,72 @@ def test_import_completion_docstring(Script):
def test_goto_definition_on_import(Script): def test_goto_definition_on_import(Script):
assert Script("import sys_blabla", 1, 8).goto_definitions() == [] assert Script("import sys_blabla").infer(1, 8) == []
assert len(Script("import sys", 1, 8).goto_definitions()) == 1 assert len(Script("import sys").infer(1, 8)) == 1
@cwd_at('jedi') @cwd_at('jedi')
def test_complete_on_empty_import(Script): def test_complete_on_empty_import(Script):
assert Script("from datetime import").completions()[0].name == 'import' assert Script("from datetime import").complete()[0].name == 'import'
# should just list the files in the directory # should just list the files in the directory
assert 10 < len(Script("from .", path='whatever.py').completions()) < 30 assert 10 < len(Script("from .", path='whatever.py').complete()) < 30
# Global import # Global import
assert len(Script("from . import", 1, 5, 'whatever.py').completions()) > 30 assert len(Script("from . import", 'whatever.py').complete(1, 5)) > 30
# relative import # relative import
assert 10 < len(Script("from . import", 1, 6, 'whatever.py').completions()) < 30 assert 10 < len(Script("from . import", 'whatever.py').complete(1, 6)) < 30
# Global import # Global import
assert len(Script("from . import classes", 1, 5, 'whatever.py').completions()) > 30 assert len(Script("from . import classes", 'whatever.py').complete(1, 5)) > 30
# relative import # relative import
assert 10 < len(Script("from . import classes", 1, 6, 'whatever.py').completions()) < 30 assert 10 < len(Script("from . import classes", 'whatever.py').complete(1, 6)) < 30
wanted = {'ImportError', 'import', 'ImportWarning'} wanted = {'ImportError', 'import', 'ImportWarning'}
assert {c.name for c in Script("import").completions()} == wanted assert {c.name for c in Script("import").complete()} == wanted
assert len(Script("import import", path='').completions()) > 0 assert len(Script("import import", path='').complete()) > 0
# 111 # 111
assert Script("from datetime import").completions()[0].name == 'import' assert Script("from datetime import").complete()[0].name == 'import'
assert Script("from datetime import ").completions() assert Script("from datetime import ").complete()
def test_imports_on_global_namespace_without_path(Script): def test_imports_on_global_namespace_without_path(Script):
"""If the path is None, there shouldn't be any import problem""" """If the path is None, there shouldn't be any import problem"""
completions = Script("import operator").completions() completions = Script("import operator").complete()
assert [c.name for c in completions] == ['operator'] assert [c.name for c in completions] == ['operator']
completions = Script("import operator", path='example.py').completions() completions = Script("import operator", path='example.py').complete()
assert [c.name for c in completions] == ['operator'] assert [c.name for c in completions] == ['operator']
# the first one has a path the second doesn't # the first one has a path the second doesn't
completions = Script("import keyword", path='example.py').completions() completions = Script("import keyword", path='example.py').complete()
assert [c.name for c in completions] == ['keyword'] assert [c.name for c in completions] == ['keyword']
completions = Script("import keyword").completions() completions = Script("import keyword").complete()
assert [c.name for c in completions] == ['keyword'] assert [c.name for c in completions] == ['keyword']
def test_named_import(Script): def test_named_import(Script):
"""named import - jedi-vim issue #8""" """named import - jedi-vim issue #8"""
s = "import time as dt" s = "import time as dt"
assert len(Script(s, 1, 15, '/').goto_definitions()) == 1 assert len(Script(s, path='/').infer(1, 15)) == 1
assert len(Script(s, 1, 10, '/').goto_definitions()) == 1 assert len(Script(s, path='/').infer(1, 10)) == 1
@pytest.mark.skipif('True', reason='The nested import stuff is still very messy.') @pytest.mark.skipif('True', reason='The nested import stuff is still very messy.')
def test_goto_following_on_imports(Script): def test_goto_following_on_imports(Script):
s = "import multiprocessing.dummy; multiprocessing.dummy" s = "import multiprocessing.dummy; multiprocessing.dummy"
g = Script(s).goto_assignments() g = Script(s).goto()
assert len(g) == 1 assert len(g) == 1
assert (g[0].line, g[0].column) != (0, 0) assert (g[0].line, g[0].column) != (0, 0)
def test_goto_assignments(Script): def test_goto(Script):
sys, = Script("import sys", 1, 10).goto_assignments(follow_imports=True) sys, = Script("import sys", 1, 10).goto(follow_imports=True)
assert sys.type == 'module' assert sys.type == 'module'
def test_os_after_from(Script): def test_os_after_from(Script):
def check(source, result, column=None): def check(source, result, column=None):
completions = Script(source, column=column).completions() completions = Script(source).complete(column=column)
assert [c.name for c in completions] == result assert [c.name for c in completions] == result
check('\nfrom os. ', ['path']) check('\nfrom os. ', ['path'])
@@ -270,7 +270,7 @@ def test_os_after_from(Script):
def test_os_issues(Script): def test_os_issues(Script):
def import_names(*args, **kwargs): def import_names(*args, **kwargs):
return [d.name for d in Script(*args, **kwargs).completions()] return [d.name for d in Script(*args).complete(**kwargs)]
# Github issue #759 # Github issue #759
s = 'import os, s' s = 'import os, s'
@@ -291,7 +291,7 @@ def test_path_issues(Script):
See pull request #684 for details. See pull request #684 for details.
""" """
source = '''from datetime import ''' source = '''from datetime import '''
assert Script(source).completions() assert Script(source).complete()
def test_compiled_import_none(monkeypatch, Script): def test_compiled_import_none(monkeypatch, Script):
@@ -300,7 +300,7 @@ def test_compiled_import_none(monkeypatch, Script):
""" """
script = Script('import sys') script = Script('import sys')
monkeypatch.setattr(compiled, 'load_module', lambda *args, **kwargs: None) monkeypatch.setattr(compiled, 'load_module', lambda *args, **kwargs: None)
def_, = script.goto_definitions() def_, = script.infer()
assert def_.type == 'module' assert def_.type == 'module'
value, = def_._name.infer() value, = def_._name.infer()
assert not _stub_to_python_value_set(value) assert not _stub_to_python_value_set(value)
@@ -361,7 +361,7 @@ def test_relative_imports_with_multiple_similar_directories(Script, path, empty_
path=os.path.join(dir, path), path=os.path.join(dir, path),
_project=project, _project=project,
) )
name, import_ = script.completions() name, import_ = script.complete()
assert import_.name == 'import' assert import_.name == 'import'
assert name.name == 'api_test1' assert name.name == 'api_test1'
@@ -374,37 +374,37 @@ def test_relative_imports_with_outside_paths(Script):
path=os.path.join(dir, 'api/whatever/test_this.py'), path=os.path.join(dir, 'api/whatever/test_this.py'),
_project=project, _project=project,
) )
assert [c.name for c in script.completions()] == ['api', 'import', 'whatever'] assert [c.name for c in script.complete()] == ['api', 'import', 'whatever']
script = Script( script = Script(
"from " + '.' * 100, "from " + '.' * 100,
path=os.path.join(dir, 'api/whatever/test_this.py'), path=os.path.join(dir, 'api/whatever/test_this.py'),
_project=project, _project=project,
) )
assert [c.name for c in script.completions()] == ['import'] assert [c.name for c in script.complete()] == ['import']
@cwd_at('test/examples/issue1209/api/whatever/') @cwd_at('test/examples/issue1209/api/whatever/')
def test_relative_imports_without_path(Script): def test_relative_imports_without_path(Script):
project = Project('.', sys_path=[], smart_sys_path=False) project = Project('.', sys_path=[], smart_sys_path=False)
script = Script("from . ", _project=project) script = Script("from . ", _project=project)
assert [c.name for c in script.completions()] == ['api_test1', 'import'] assert [c.name for c in script.complete()] == ['api_test1', 'import']
script = Script("from .. ", _project=project) script = Script("from .. ", _project=project)
assert [c.name for c in script.completions()] == ['import', 'whatever'] assert [c.name for c in script.complete()] == ['import', 'whatever']
script = Script("from ... ", _project=project) script = Script("from ... ", _project=project)
assert [c.name for c in script.completions()] == ['api', 'import', 'whatever'] assert [c.name for c in script.complete()] == ['api', 'import', 'whatever']
def test_relative_import_out_of_file_system(Script): def test_relative_import_out_of_file_system(Script):
script = Script("from " + '.' * 100) script = Script("from " + '.' * 100)
import_, = script.completions() import_, = script.complete()
assert import_.name == 'import' assert import_.name == 'import'
script = Script("from " + '.' * 100 + 'abc import ABCMeta') script = Script("from " + '.' * 100 + 'abc import ABCMeta')
assert not script.goto_definitions() assert not script.infer()
assert not script.completions() assert not script.complete()
@pytest.mark.parametrize( @pytest.mark.parametrize(
@@ -456,13 +456,13 @@ def test_import_needed_modules_by_jedi(Script, environment, tmpdir, name):
path=tmpdir.join('something.py').strpath, path=tmpdir.join('something.py').strpath,
sys_path=[tmpdir.strpath] + environment.get_sys_path(), sys_path=[tmpdir.strpath] + environment.get_sys_path(),
) )
module, = script.goto_definitions() module, = script.infer()
assert module._inference_state.builtins_module.py__file__() != module_path assert module._inference_state.builtins_module.py__file__() != module_path
assert module._inference_state.typing_module.py__file__() != module_path assert module._inference_state.typing_module.py__file__() != module_path
def test_import_with_semicolon(Script): def test_import_with_semicolon(Script):
names = [c.name for c in Script('xzy; from abc import ').completions()] names = [c.name for c in Script('xzy; from abc import ').complete()]
assert 'ABCMeta' in names assert 'ABCMeta' in names
assert 'abc' not in names assert 'abc' not in names
@@ -475,6 +475,6 @@ def test_relative_import_star(Script):
from . import * from . import *
furl.c furl.c
""" """
script = jedi.Script(source, 3, len("furl.c"), 'export.py') script = jedi.Script(source, 'export.py')
assert script.completions() assert script.complete(3, len("furl.c"))
+1 -1
View File
@@ -3,7 +3,7 @@ from jedi.inference.value import TreeInstance
def _infer_literal(Script, code, is_fstring=False): def _infer_literal(Script, code, is_fstring=False):
def_, = Script(code).goto_definitions() def_, = Script(code).infer()
if is_fstring: if is_fstring:
assert def_.name == 'str' assert def_.name == 'str'
assert isinstance(def_._name._value, TreeInstance) assert isinstance(def_._name._value, TreeInstance)
+2 -2
View File
@@ -14,7 +14,7 @@ def interpreter(code, namespace, *args, **kwargs):
def test_on_code(): def test_on_code():
from functools import wraps from functools import wraps
i = interpreter("wraps.__code__", {'wraps': wraps}) i = interpreter("wraps.__code__", {'wraps': wraps})
assert i.goto_definitions() assert i.infer()
@pytest.mark.skipif('sys.version_info < (3,5)') @pytest.mark.skipif('sys.version_info < (3,5)')
@@ -39,4 +39,4 @@ def test_generics():
self.stack.push(1) self.stack.push(1)
s = StackWrapper() s = StackWrapper()
print(interpreter('s.stack.pop().', locals()).completions()) print(interpreter('s.stack.pop().', locals()).complete())
+11 -11
View File
@@ -15,9 +15,9 @@ def script_with_path(Script, *args, **kwargs):
def test_goto_definition(Script): 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 ns1_file').infer()
assert script_with_path(Script, 'from pkg import ns2_file').goto_definitions() assert script_with_path(Script, 'from pkg import ns2_file').infer()
assert not script_with_path(Script, 'from pkg import ns3_file').goto_definitions() assert not script_with_path(Script, 'from pkg import ns3_file').infer()
@pytest.mark.parametrize( @pytest.mark.parametrize(
@@ -31,14 +31,14 @@ def test_goto_definition(Script):
] ]
) )
def test_goto_assignment(Script, source, solution): def test_goto_assignment(Script, source, solution):
ass = script_with_path(Script, source).goto_assignments() ass = script_with_path(Script, source).goto()
assert len(ass) == 1 assert len(ass) == 1
assert ass[0].description == "foo = '%s'" % solution assert ass[0].description == "foo = '%s'" % solution
def test_simple_completions(Script): def test_simple_completions(Script):
# completion # completion
completions = script_with_path(Script, 'from pkg import ').completions() completions = script_with_path(Script, 'from pkg import ').complete()
names = [str(c.name) for c in completions] # str because of unicode names = [str(c.name) for c in completions] # str because of unicode
compare = ['foo', 'ns1_file', 'ns1_folder', 'ns2_folder', 'ns2_file', compare = ['foo', 'ns1_file', 'ns1_folder', 'ns2_folder', 'ns2_file',
'pkg_resources', 'pkgutil', '__name__', '__path__', 'pkg_resources', 'pkgutil', '__name__', '__path__',
@@ -58,7 +58,7 @@ def test_simple_completions(Script):
] ]
) )
def test_completions(Script, source, solution): def test_completions(Script, source, solution):
for c in script_with_path(Script, source + '; x.').completions(): for c in script_with_path(Script, source + '; x.').complete():
if c.name == 'foo': if c.name == 'foo':
completion = c completion = c
solution = "foo = '%s'" % solution solution = "foo = '%s'" % solution
@@ -70,9 +70,9 @@ def test_nested_namespace_package(Script):
sys_path = [dirname(__file__)] sys_path = [dirname(__file__)]
script = Script(sys_path=sys_path, source=code, line=1, column=45) script = Script(sys_path=sys_path, source=code)
result = script.goto_definitions() result = script.infer(line=1, column=45)
assert len(result) == 1 assert len(result) == 1
@@ -88,9 +88,9 @@ def test_relative_import(Script, environment, tmpdir):
# Need to copy the content in a directory where there's no __init__.py. # Need to copy the content in a directory where there's no __init__.py.
py.path.local(directory).copy(tmpdir) py.path.local(directory).copy(tmpdir)
file_path = join(tmpdir.strpath, "rel1.py") file_path = join(tmpdir.strpath, "rel1.py")
script = Script(path=file_path, line=1) script = Script(path=file_path)
d, = script.goto_definitions() d, = script.infer(line=1)
assert d.name == 'int' assert d.name == 'int'
d, = script.goto_assignments() d, = script.goto(line=1)
assert d.name == 'name' assert d.name == 'name'
assert d.module_name == 'rel2' assert d.module_name == 'rel2'
+1 -1
View File
@@ -70,4 +70,4 @@ def test_pyc(pyc_project_path, environment):
"from dummy_package import dummy; dummy.", "from dummy_package import dummy; dummy.",
path=path, path=path,
environment=environment) environment=environment)
assert len(s.completions()) >= 2 assert len(s.complete()) >= 2
+1 -1
View File
@@ -2,7 +2,7 @@ from textwrap import dedent
def get_definition_and_inference_state(Script, source): def get_definition_and_inference_state(Script, source):
first, = Script(dedent(source)).goto_definitions() first, = Script(dedent(source)).infer()
return first._name._value, first._inference_state return first._name._value, first._inference_state
+9 -9
View File
@@ -32,7 +32,7 @@ def test_compiled_signature(Script, environment, code, sig, names, op, version):
if not op(environment.version_info, version): if not op(environment.version_info, version):
return # The test right next to it should take over. return # The test right next to it should take over.
d, = Script(code).goto_definitions() d, = Script(code).infer()
value, = d._name.infer() value, = d._name.infer()
compiled, = _stub_to_python_value_set(value) compiled, = _stub_to_python_value_set(value)
signature, = compiled.get_signatures() signature, = compiled.get_signatures()
@@ -90,9 +90,9 @@ def test_tree_signature(Script, environment, code, expected):
pytest.skip() pytest.skip()
if expected is None: if expected is None:
assert not Script(code).call_signatures() assert not Script(code).find_signatures()
else: else:
sig, = Script(code).call_signatures() sig, = Script(code).find_signatures()
assert expected == sig.to_string() assert expected == sig.to_string()
@@ -182,7 +182,7 @@ def test_nested_signatures(Script, environment, combination, expected, skip_pre_
super().foo(**kwargs) super().foo(**kwargs)
''') ''')
code += 'z = ' + combination + '\nz(' code += 'z = ' + combination + '\nz('
sig, = Script(code).call_signatures() sig, = Script(code).find_signatures()
computed = sig.to_string() computed = sig.to_string()
if not re.match(r'\w+\(', expected): if not re.match(r'\w+\(', expected):
expected = '<lambda>(' + expected + ')' expected = '<lambda>(' + expected + ')'
@@ -191,7 +191,7 @@ def test_nested_signatures(Script, environment, combination, expected, skip_pre_
def test_pow_signature(Script): def test_pow_signature(Script):
# See github #1357 # See github #1357
sigs = Script('pow(').call_signatures() sigs = Script('pow(').find_signatures()
strings = {sig.to_string() for sig in sigs} strings = {sig.to_string() for sig in sigs}
assert strings == {'pow(x: float, y: float, z: float, /) -> float', assert strings == {'pow(x: float, y: float, z: float, /) -> float',
'pow(x: float, y: float, /) -> float', 'pow(x: float, y: float, /) -> float',
@@ -230,7 +230,7 @@ def test_pow_signature(Script):
] ]
) )
def test_wraps_signature(Script, code, signature, skip_pre_python35): def test_wraps_signature(Script, code, signature, skip_pre_python35):
sigs = Script(code).call_signatures() sigs = Script(code).find_signatures()
assert {sig.to_string() for sig in sigs} == {signature} assert {sig.to_string() for sig in sigs} == {signature}
@@ -263,7 +263,7 @@ def test_dataclass_signature(Script, skip_pre_python37, start, start_params):
code = 'from dataclasses import dataclass\n' + start + code code = 'from dataclasses import dataclass\n' + start + code
sig, = Script(code).call_signatures() sig, = Script(code).find_signatures()
assert [p.name for p in sig.params] == start_params + ['name', 'price', 'quantity'] assert [p.name for p in sig.params] == start_params + ['name', 'price', 'quantity']
quantity, = sig.params[-1].infer() quantity, = sig.params[-1].infer()
assert quantity.name == 'int' assert quantity.name == 'int'
@@ -289,13 +289,13 @@ def test_param_resolving_to_static(Script, stmt, expected, skip_pre_python35):
def simple(a, b, *, c): ... def simple(a, b, *, c): ...
full_redirect(simple)('''.format(stmt=stmt)) full_redirect(simple)('''.format(stmt=stmt))
sig, = Script(code).call_signatures() sig, = Script(code).find_signatures()
assert sig.to_string() == expected assert sig.to_string() == expected
def test_overload(Script): def test_overload(Script):
dir_ = get_example_dir('typing_overload') dir_ = get_example_dir('typing_overload')
code = 'from file import with_overload; with_overload(' code = 'from file import with_overload; with_overload('
x1, x2 = Script(code, path=os.path.join(dir_, 'foo.py')).call_signatures() x1, x2 = Script(code, path=os.path.join(dir_, 'foo.py')).find_signatures()
assert x1.to_string() == 'with_overload(x: int, y: int) -> float' assert x1.to_string() == 'with_overload(x: int, y: int) -> float'
assert x2.to_string() == 'with_overload(x: str, y: list) -> float' assert x2.to_string() == 'with_overload(x: str, y: list) -> float'
+7 -7
View File
@@ -17,7 +17,7 @@ def test_namedtuple_str(letter, expected, Script):
Person = collections.namedtuple('Person', 'name smart') Person = collections.namedtuple('Person', 'name smart')
dave = Person('Dave', False) dave = Person('Dave', False)
dave.%s""") % letter dave.%s""") % letter
result = Script(source).completions() result = Script(source).complete()
completions = set(r.name for r in result) completions = set(r.name for r in result)
assert completions == set(expected) assert completions == set(expected)
@@ -28,7 +28,7 @@ def test_namedtuple_list(Script):
Cat = collections.namedtuple('Person', ['legs', u'length', 'large']) Cat = collections.namedtuple('Person', ['legs', u'length', 'large'])
garfield = Cat(4, '85cm', True) garfield = Cat(4, '85cm', True)
garfield.l""") garfield.l""")
result = Script(source).completions() result = Script(source).complete()
completions = set(r.name for r in result) completions = set(r.name for r in result)
assert completions == {'legs', 'length', 'large'} assert completions == {'legs', 'length', 'large'}
@@ -42,7 +42,7 @@ def test_namedtuple_content(Script):
""") """)
def d(source): def d(source):
x, = Script(source).goto_definitions() x, = Script(source).infer()
return x.name return x.name
assert d(source + 'unnamed.bar') == 'int' assert d(source + 'unnamed.bar') == 'int'
@@ -62,10 +62,10 @@ def test_nested_namedtuples(Script):
train_x = Datasets(train=Dataset('data_value')) train_x = Datasets(train=Dataset('data_value'))
train_x.train.''' train_x.train.'''
)) ))
assert 'data' in [c.name for c in s.completions()] assert 'data' in [c.name for c in s.complete()]
def test_namedtuple_goto_definitions(Script): def test_namedtuple_infer(Script):
source = dedent(""" source = dedent("""
from collections import namedtuple from collections import namedtuple
@@ -74,7 +74,7 @@ def test_namedtuple_goto_definitions(Script):
from jedi.api import Script from jedi.api import Script
d1, = Script(source).goto_definitions() d1, = Script(source).infer()
assert d1.get_line_code() == "class Foo(tuple):\n" assert d1.get_line_code() == "class Foo(tuple):\n"
assert d1.module_path is None assert d1.module_path is None
@@ -86,7 +86,7 @@ def test_re_sub(Script, environment):
version differences. version differences.
""" """
def run(code): def run(code):
defs = Script(code).goto_definitions() defs = Script(code).infer()
return {d.name for d in defs} return {d.name for d in defs}
names = run("import re; re.sub('a', 'a', 'f')") names = run("import re; re.sub('a', 'a', 'f')")
+7 -7
View File
@@ -6,7 +6,7 @@ from parso import parse
def test_form_feed_characters(Script): def test_form_feed_characters(Script):
s = "\f\nclass Test(object):\n pass" s = "\f\nclass Test(object):\n pass"
Script(s, line=2, column=18).call_signatures() Script(s).find_signatures(line=2, column=18)
def check_p(src): def check_p(src):
@@ -29,7 +29,7 @@ def test_if(Script):
# Two parsers needed, one for pass and one for the function. # Two parsers needed, one for pass and one for the function.
check_p(src) check_p(src)
assert [d.name for d in Script(src, 8, 6).goto_definitions()] == ['int'] assert [d.name for d in Script(src).infer(8, 6)] == ['int']
def test_class_and_if(Script): def test_class_and_if(Script):
@@ -47,7 +47,7 @@ def test_class_and_if(Script):
# COMMENT # COMMENT
a_func()""") a_func()""")
check_p(src) check_p(src)
assert [d.name for d in Script(src).goto_definitions()] == ['int'] assert [d.name for d in Script(src).infer()] == ['int']
def test_add_to_end(Script): def test_add_to_end(Script):
@@ -70,8 +70,8 @@ def test_add_to_end(Script):
" self." " self."
def complete(code, line=None, column=None): def complete(code, line=None, column=None):
script = Script(code, line, column, 'example.py') script = Script(code, 'example.py')
assert script.completions() assert script.complete(line, column)
complete(a, 7, 12) complete(a, 7, 12)
complete(a + b) complete(a + b)
@@ -82,7 +82,7 @@ def test_add_to_end(Script):
def test_tokenizer_with_string_literal_backslash(Script): def test_tokenizer_with_string_literal_backslash(Script):
c = Script("statement = u'foo\\\n'; statement").goto_definitions() c = Script("statement = u'foo\\\n'; statement").infer()
assert c[0]._name._value.get_safe_value() == 'foo' assert c[0]._name._value.get_safe_value() == 'foo'
@@ -90,6 +90,6 @@ def test_ellipsis_without_getitem(Script, environment):
if environment.version_info.major == 2: if environment.version_info.major == 2:
pytest.skip('In 2.7 Ellipsis can only be used like x[...]') pytest.skip('In 2.7 Ellipsis can only be used like x[...]')
def_, = Script('x=...;x').goto_definitions() def_, = Script('x=...;x').infer()
assert def_.name == 'ellipsis' assert def_.name == 'ellipsis'
@@ -6,7 +6,7 @@ def test_error_correction_with(Script):
with open() as f: with open() as f:
try: try:
f.""" f."""
comps = Script(source).completions() comps = Script(source).complete()
assert len(comps) > 30 assert len(comps) > 30
# `open` completions have a closed attribute. # `open` completions have a closed attribute.
assert [1 for c in comps if c.name == 'closed'] assert [1 for c in comps if c.name == 'closed']
@@ -23,14 +23,14 @@ def test_string_literals(Script):
script = Script(dedent(source)) script = Script(dedent(source))
assert script._get_module_context().tree_node.end_pos == (6, 0) assert script._get_module_context().tree_node.end_pos == (6, 0)
assert script.completions() assert script.complete()
def test_incomplete_function(Script): def test_incomplete_function(Script):
source = '''return ImportErr''' source = '''return ImportErr'''
script = Script(dedent(source), 1, 3) script = Script(dedent(source))
assert script.completions() assert script.complete(1, 3)
def test_decorator_string_issue(Script): def test_decorator_string_issue(Script):
@@ -46,5 +46,5 @@ def test_decorator_string_issue(Script):
bla.''') bla.''')
s = Script(source) s = Script(source)
assert s.completions() assert s.complete()
assert s._get_module_context().tree_node.get_code() == source assert s._get_module_context().tree_node.get_code() == source
@@ -62,13 +62,13 @@ def test_hex_values_in_docstring():
@pytest.mark.parametrize( @pytest.mark.parametrize(
'code,call_signature', [ 'code,signature', [
('def my_function(x, typed: Type, z):\n return', 'my_function(x, typed: Type, z)'), ('def my_function(x, typed: Type, z):\n return', 'my_function(x, typed: Type, z)'),
('def my_function(x, y, z) -> str:\n return', 'my_function(x, y, z) -> str'), ('def my_function(x, y, z) -> str:\n return', 'my_function(x, y, z) -> str'),
('lambda x, y, z: x + y * z\n', '<lambda>(x, y, z)') ('lambda x, y, z: x + y * z\n', '<lambda>(x, y, z)')
]) ])
def test_get_call_signature(code, call_signature): def test_get_signature(code, signature):
node = parse(code, version='3.5').children[0] node = parse(code, version='3.5').children[0]
if node.type == 'simple_stmt': if node.type == 'simple_stmt':
node = node.children[0] node = node.children[0]
assert parser_utils.get_call_signature(node) == call_signature assert parser_utils.get_signature(node) == signature
+5 -5
View File
@@ -12,14 +12,14 @@ def auto_import_json(monkeypatch):
def test_base_auto_import_modules(auto_import_json, Script): def test_base_auto_import_modules(auto_import_json, Script):
loads, = Script('import json; json.loads').goto_definitions() loads, = Script('import json; json.loads').infer()
assert isinstance(loads._name, ValueName) assert isinstance(loads._name, ValueName)
value, = loads._name.infer() value, = loads._name.infer()
assert isinstance(value.parent_context._value, StubModuleValue) assert isinstance(value.parent_context._value, StubModuleValue)
def test_auto_import_modules_imports(auto_import_json, Script): def test_auto_import_modules_imports(auto_import_json, Script):
main, = Script('from json import tool; tool.main').goto_definitions() main, = Script('from json import tool; tool.main').infer()
assert isinstance(main._name, CompiledValueName) assert isinstance(main._name, CompiledValueName)
@@ -31,7 +31,7 @@ def test_additional_dynamic_modules(monkeypatch, Script):
'additional_dynamic_modules', 'additional_dynamic_modules',
['/foo/bar/jedi_not_existing_file.py'] ['/foo/bar/jedi_not_existing_file.py']
) )
assert not Script('def some_func(f):\n f.').completions() assert not Script('def some_func(f):\n f.').complete()
def test_cropped_file_size(monkeypatch, names, Script): def test_cropped_file_size(monkeypatch, names, Script):
@@ -47,5 +47,5 @@ def test_cropped_file_size(monkeypatch, names, Script):
# It should just not crash if we are outside of the cropped range. # It should just not crash if we are outside of the cropped range.
script = Script(code + code + 'Foo') script = Script(code + code + 'Foo')
assert not script.goto_definitions() assert not script.infer()
assert 'Foo' in [c.name for c in script.completions()] assert 'Foo' in [c.name for c in script.complete()]
+5 -5
View File
@@ -33,14 +33,14 @@ def _check_speed(time_per_run, number=4, run_warm=True):
@_check_speed(0.5) @_check_speed(0.5)
def test_os_path_join(Script): def test_os_path_join(Script):
s = "from posixpath import join; join('', '')." s = "from posixpath import join; join('', '')."
assert len(Script(s).completions()) > 10 # is a str completion assert len(Script(s).complete()) > 10 # is a str completion
@_check_speed(0.15) @_check_speed(0.15)
def test_scipy_speed(Script): def test_scipy_speed(Script):
s = 'import scipy.weave; scipy.weave.inline(' s = 'import scipy.weave; scipy.weave.inline('
script = Script(s, 1, len(s), '') script = Script(s, path='')
script.call_signatures() script.find_signatures(1, len(s))
@_check_speed(0.8) @_check_speed(0.8)
@@ -52,7 +52,7 @@ def test_precedence_slowdown(Script):
""" """
with open('speed/precedence.py') as f: with open('speed/precedence.py') as f:
line = len(f.read().splitlines()) line = len(f.read().splitlines())
assert Script(line=line, path='speed/precedence.py').goto_definitions() assert Script(path='speed/precedence.py').infer(line=line)
@_check_speed(0.1) @_check_speed(0.1)
@@ -70,4 +70,4 @@ def test_no_repr_computation(Script):
def __repr__(self): def __repr__(self):
time.sleep(0.2) time.sleep(0.2)
test = SlowRepr() test = SlowRepr()
jedi.Interpreter('test.som', [locals()]).completions() jedi.Interpreter('test.som', [locals()]).complete()
+19 -19
View File
@@ -19,7 +19,7 @@ class TestSetupReadline(unittest.TestCase):
self.namespace = self.NameSpace() self.namespace = self.NameSpace()
utils.setup_readline(self.namespace) utils.setup_readline(self.namespace)
def completions(self, text): def complete(self, text):
completer = readline.get_completer() completer = readline.get_completer()
i = 0 i = 0
completions = [] completions = []
@@ -32,18 +32,18 @@ class TestSetupReadline(unittest.TestCase):
return completions return completions
def test_simple(self): def test_simple(self):
assert self.completions('list') == ['list'] assert self.complete('list') == ['list']
assert self.completions('importerror') == ['ImportError'] assert self.complete('importerror') == ['ImportError']
s = "print(BaseE" s = "print(BaseE"
assert self.completions(s) == [s + 'xception'] assert self.complete(s) == [s + 'xception']
def test_nested(self): def test_nested(self):
assert self.completions('list.Insert') == ['list.insert'] assert self.complete('list.Insert') == ['list.insert']
assert self.completions('list().Insert') == ['list().insert'] assert self.complete('list().Insert') == ['list().insert']
def test_magic_methods(self): def test_magic_methods(self):
assert self.completions('list.__getitem__') == ['list.__getitem__'] assert self.complete('list.__getitem__') == ['list.__getitem__']
assert self.completions('list().__getitem__') == ['list().__getitem__'] assert self.complete('list().__getitem__') == ['list().__getitem__']
def test_modules(self): def test_modules(self):
import sys import sys
@@ -52,31 +52,31 @@ class TestSetupReadline(unittest.TestCase):
self.namespace.os = os self.namespace.os = os
try: try:
assert self.completions('os.path.join') == ['os.path.join'] assert self.complete('os.path.join') == ['os.path.join']
string = 'os.path.join("a").upper' string = 'os.path.join("a").upper'
assert self.completions(string) == [string] assert self.complete(string) == [string]
c = {'os.' + d for d in dir(os) if d.startswith('ch')} c = {'os.' + d for d in dir(os) if d.startswith('ch')}
assert set(self.completions('os.ch')) == set(c) assert set(self.complete('os.ch')) == set(c)
finally: finally:
del self.namespace.sys del self.namespace.sys
del self.namespace.os del self.namespace.os
def test_calls(self): def test_calls(self):
s = 'str(bytes' s = 'str(bytes'
assert self.completions(s) == [s, 'str(BytesWarning'] assert self.complete(s) == [s, 'str(BytesWarning']
def test_import(self): def test_import(self):
s = 'from os.path import a' s = 'from os.path import a'
assert set(self.completions(s)) == {s + 'ltsep', s + 'bspath'} assert set(self.complete(s)) == {s + 'ltsep', s + 'bspath'}
assert self.completions('import keyword') == ['import keyword'] assert self.complete('import keyword') == ['import keyword']
import os import os
s = 'from os import ' s = 'from os import '
goal = {s + el for el in dir(os)} goal = {s + el for el in dir(os)}
# There are minor differences, e.g. the dir doesn't include deleted # There are minor differences, e.g. the dir doesn't include deleted
# items as well as items that are not only available on linux. # items as well as items that are not only available on linux.
difference = set(self.completions(s)).symmetric_difference(goal) difference = set(self.complete(s)).symmetric_difference(goal)
difference = { difference = {
x for x in difference x for x in difference
if all(not x.startswith('from os import ' + s) if all(not x.startswith('from os import ' + s)
@@ -89,11 +89,11 @@ class TestSetupReadline(unittest.TestCase):
@cwd_at('test') @cwd_at('test')
def test_local_import(self): def test_local_import(self):
s = 'import test_utils' s = 'import test_utils'
assert self.completions(s) == [s] assert self.complete(s) == [s]
def test_preexisting_values(self): def test_preexisting_values(self):
self.namespace.a = range(10) self.namespace.a = range(10)
assert set(self.completions('a.')) == {'a.' + n for n in dir(range(1))} assert set(self.complete('a.')) == {'a.' + n for n in dir(range(1))}
del self.namespace.a del self.namespace.a
def test_colorama(self): def test_colorama(self):
@@ -110,8 +110,8 @@ class TestSetupReadline(unittest.TestCase):
pass pass
else: else:
self.namespace.colorama = colorama self.namespace.colorama = colorama
assert self.completions('colorama') assert self.complete('colorama')
assert self.completions('colorama.Fore.BLACK') == ['colorama.Fore.BLACK'] assert self.complete('colorama.Fore.BLACK') == ['colorama.Fore.BLACK']
del self.namespace.colorama del self.namespace.colorama