Merge branch 'api', fixes #1166

This commit is contained in:
Dave Halter
2019-12-20 20:05:10 +01:00
74 changed files with 859 additions and 779 deletions

View File

@@ -3,10 +3,15 @@
Changelog
---------
0.16.0 (2020--)
+++++++++++++++++++
- ``BaseDefinition.goto_assignments`` renamed to ``BaseDefinition.goto``
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)``
- Files bigger than one MB (about 20kLOC) get cropped to avoid getting
stuck completely.
@@ -33,7 +38,7 @@ New APIs:
- ``Definition.get_signatures() -> List[Signature]``. Signatures are similar to
``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
following additional attributes ``infer_default()``, ``infer_annotation()``,
``to_string()``, and ``kind``.

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.
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
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:
- ``jedi.Script.goto_assignments``
- ``jedi.Script.completions``
- ``jedi.Script.usages``
- ``jedi.Script.goto``
- ``jedi.Script.complete``
- ``jedi.Script.find_references``
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
------------------------
To do all forms of static analysis, please try to use ``jedi.names``. It will
return a list of names that you can use to infer types and so on.
To do all forms of static analysis, please try to use
``jedi.Script(...).names``. It will return a list of names that you can use to
infer types and so on.
Refactoring

View File

@@ -106,8 +106,8 @@ def Script(environment):
@pytest.fixture(scope='session')
def names(environment):
return partial(jedi.names, environment=environment)
def names(Script):
return lambda code, **kwargs: Script(code).names(**kwargs)
@pytest.fixture(scope='session')
@@ -118,7 +118,7 @@ def has_typing(environment):
return True
script = jedi.Script('import typing', environment=environment)
return bool(script.goto_definitions())
return bool(script.infer())
@pytest.fixture(scope='session')

View File

@@ -29,9 +29,8 @@ API Documentation
The API consists of a few different parts:
- The main starting points for completions/goto: :class:`.Script` and :class:`.Interpreter`
- Helpful functions: :func:`.names`, :func:`.preload_module` and
:func:`.set_debug_function`
- The main starting points for complete/goto: :class:`.Script` and :class:`.Interpreter`
- Helpful functions: :func:`.preload_module` and :func:`.set_debug_function`
- :ref:`API Result Classes <api-classes>`
- :ref:`Python Versions/Virtualenv Support <environments>` with functions like
:func:`.find_system_environments` and :func:`.find_virtualenvs`
@@ -47,7 +46,6 @@ Static Analysis Interface
:members:
.. autoclass:: jedi.Interpreter
:members:
.. autofunction:: jedi.names
.. autofunction:: jedi.preload_module
.. autofunction:: jedi.set_debug_function
@@ -76,10 +74,10 @@ Completions:
>>> import jedi
>>> source = '''import json; json.l'''
>>> script = jedi.Script(source, 1, 19, '')
>>> script = jedi.Script(source, path='')
>>> script
<jedi.api.Script object at 0x2121b10>
>>> completions = script.completions()
>>> completions = script.complete(1, 19)
>>> completions
[<Completion: load>, <Completion: loads>]
>>> completions[1]
@@ -102,15 +100,15 @@ Definitions / Goto:
... inception = my_list[2]
...
... inception()'''
>>> script = jedi.Script(source, 8, 1, '')
>>> script = jedi.Script(source, path='')
>>>
>>> script.goto_assignments()
>>> script.goto(8, 1)
[<Definition inception=my_list[2]>]
>>>
>>> script.goto_definitions()
>>> script.infer(8, 1)
[<Definition def my_func>]
Related names:
References:
.. sourcecode:: python
@@ -120,13 +118,12 @@ Related names:
... x = 4
... else:
... del x'''
>>> script = jedi.Script(source, 5, 8, '')
>>> rns = script.related_names()
>>> script = jedi.Script(source, '')
>>> rns = script.find_references(5, 8)
>>> rns
[<RelatedName x@3,4>, <RelatedName x@1,0>]
>>> rns[0].start_pos
(3, 4)
>>> rns[0].is_keyword
False
>>> rns[0].text
'x'
[<Definition full_name='__main__.x', description='x = 3'>,
<Definition full_name='__main__.x', description='x'>]
>>> rns[1].line
5
>>> rns[0].column
8

View File

@@ -6,7 +6,7 @@ Features and Caveats
Jedi obviously supports autocompletion. It's also possible to get it working in
(: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,
because it's not production ready. If you're interested in helping out here,

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.
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
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 = '''
... import json
... json.lo'''
>>> script = jedi.Script(source, 3, len('json.lo'), 'example.py')
>>> script = jedi.Script(source, path='example.py')
>>> script
<Script: 'example.py' ...>
>>> completions = script.completions()
>>> completions = script.complete(3, len('json.lo'))
>>> completions
[<Completion: load>, <Completion: loads>]
>>> 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.
"""
__version__ = '0.15.2'
__version__ = '0.16.0'
from jedi.api import Script, Interpreter, set_debug_function, \
preload_module, names

View File

@@ -25,12 +25,13 @@ from jedi.file_io import KnownContentFileIO
from jedi.api import classes
from jedi.api import interpreter
from jedi.api import helpers
from jedi.api.helpers import validate_line_column
from jedi.api.completion import Completion
from jedi.api.environment import InterpreterEnvironment
from jedi.api.project import get_default_project, Project
from jedi.inference import InferenceState
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.helpers import get_module_names, infer_call_of_leaf
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.
: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
:param column: The column of the cursor (starting with 0).
:param column: Deprecated, please use it directly on e.g. `.complete`
:type column: int
:param path: The path of the file in the file system, or ``''`` if
it hasn't been saved yet.
@@ -126,22 +127,6 @@ class Script(object):
debug.speed('parsed')
self._code_lines = parso.split_lines(source, keepends=True)
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
cache.clear_time_caches()
@@ -201,27 +186,38 @@ class Script(object):
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
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`
"""
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(
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!
This follows complicated paths and returns the end, not the first
definition. The big difference between :meth:`goto_assignments` and
:meth:`goto_definitions` is that :meth:`goto_assignments` doesn't
definition. The big difference between :meth:`goto` and
:meth:`infer` is that :meth:`goto` doesn't
follow imports and statements. Multiple objects may be returned,
because Python itself is a dynamic language, which means depending on
an option you can have two different versions of a function.
@@ -231,19 +227,24 @@ class Script(object):
inference call.
:rtype: list of :class:`classes.Definition`
"""
with debug.increase_indent_cm('goto_definitions'):
return self._goto_definitions(**kwargs)
with debug.increase_indent_cm('infer'):
return self._infer(line, column, **kwargs)
def _goto_definitions(self, only_stubs=False, prefer_stubs=False):
leaf = self._module_node.get_name_of_position(self._pos)
def goto_definitions(self, **kwargs):
# 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:
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':
return []
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,
only_stubs=only_stubs,
@@ -257,6 +258,14 @@ class Script(object):
return helpers.sorted_definitions(set(defs))
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.
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.
:rtype: list of :class:`classes.Definition`
"""
with debug.increase_indent_cm('goto_assignments'):
return self._goto_assignments(follow_imports, follow_builtin_imports, **kwargs)
with debug.increase_indent_cm('goto'):
return self._goto(line, column, **kwargs)
def _goto_assignments(self, follow_imports, follow_builtin_imports,
only_stubs=False, prefer_stubs=False):
def _goto(self, line, column, follow_imports=False, follow_builtin_imports=False,
only_stubs=False, prefer_stubs=False):
def filter_follow_imports(names):
for name in names:
if name.is_import():
@@ -296,11 +305,11 @@ class Script(object):
else:
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:
# Without a name we really just want to jump to the result e.g.
# 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)
names = list(name.goto())
@@ -315,42 +324,43 @@ class Script(object):
defs = [classes.Definition(self._inference_state, d) for d in set(names)]
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
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
variable.
is very useful for refactoring (renaming), or to show all references of
a variable.
.. todo:: Implement additional_module_paths
: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.
:param include_builtins: Default True, checks if a reference is a
builtin (e.g. ``sys``) and in that case does not return it.
: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):
tree_name = self._module_node.get_name_of_position(self._pos)
def _references(include_builtins=True):
tree_name = self._module_node.get_name_of_position((line, column))
if tree_name is None:
# Must be syntax
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]
if not include_builtins:
definitions = [d for d in definitions if not d.in_builtin_module()]
return helpers.sorted_definitions(definitions)
return _usages(**kwargs)
return _references(**kwargs)
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.
@@ -364,25 +374,26 @@ class Script(object):
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:
return []
context = self._get_module_context().create_context(call_details.bracket_leaf)
definitions = helpers.cache_call_signatures(
definitions = helpers.cache_signatures(
self._inference_state,
context,
call_details.bracket_leaf,
self._code_lines,
self._pos
pos
)
debug.speed('func_call followed')
# TODO here we use stubs instead of the actual values. We should use
# 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()]
def _analysis(self):
@@ -408,7 +419,7 @@ class Script(object):
unpack_tuple_to_dict(context, types, testlist)
else:
if node.type == 'name':
defs = self._inference_state.goto_definitions(context, node)
defs = self._inference_state.infer(context, node)
else:
defs = infer_call_of_leaf(context, node)
try_iter_content(defs)
@@ -419,6 +430,36 @@ class Script(object):
finally:
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):
"""
@@ -432,7 +473,7 @@ class Interpreter(Script):
>>> from os.path import join
>>> namespace = locals()
>>> script = Interpreter('join("").up', [namespace])
>>> print(script.completions()[0].name)
>>> print(script.complete()[0].name)
upper
"""
_allow_descriptor_getattr_default = True
@@ -484,34 +525,17 @@ class Interpreter(Script):
def names(source=None, path=None, encoding='utf-8', all_scopes=False,
definitions=True, references=False, environment=None):
"""
Returns a list of `Definition` objects, containing name parts.
This means you can call ``Definition.goto_assignments()`` and get the
reference of a name.
The parameters are the same as in :py:class:`Script`, except or the
following ones:
warnings.warn(
"Deprecated since version 0.16.0. Use Script(...).names instead.",
DeprecationWarning,
stacklevel=2
)
: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``.
"""
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))
return Script(source, path=path, encoding=encoding).names(
all_scopes=all_scopes,
definitions=definitions,
references=references,
)
def preload_module(*modules):
@@ -523,7 +547,7 @@ def preload_module(*modules):
"""
for m in modules:
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,

View File

@@ -104,7 +104,7 @@ class BaseDefinition(object):
Here is an example of the value of this attribute. Let's consider
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``.
>>> from jedi._compatibility import no_unicode_pprint
@@ -127,7 +127,7 @@ class BaseDefinition(object):
... variable'''
>>> script = Script(source)
>>> defs = script.goto_definitions()
>>> defs = script.infer()
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.
@@ -177,7 +177,7 @@ class BaseDefinition(object):
>>> from jedi import Script
>>> source = 'import json'
>>> script = Script(source, path='example.py')
>>> d = script.goto_definitions()[0]
>>> d = script.infer()[0]
>>> print(d.module_name) # doctest: +ELLIPSIS
json
"""
@@ -217,18 +217,18 @@ class BaseDefinition(object):
... def f(a, b=1):
... "Document for function f."
... '''
>>> script = Script(source, 1, len('def f'), 'example.py')
>>> doc = script.goto_definitions()[0].docstring()
>>> script = Script(source, path='example.py')
>>> doc = script.infer(1, len('def f'))[0].docstring()
>>> print(doc)
f(a, b=1)
<BLANKLINE>
Document for function f.
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.
>>> print(script.goto_definitions()[0].docstring(raw=True))
>>> print(script.infer(1, len('def f'))[0].docstring(raw=True))
Document for function f.
:param fast: Don't follow imports that are only one level deep like
@@ -259,8 +259,8 @@ class BaseDefinition(object):
>>> source = '''
... import os
... os.path.join'''
>>> script = Script(source, 3, len('os.path.join'), 'example.py')
>>> print(script.goto_definitions()[0].full_name)
>>> script = Script(source, path='example.py')
>>> print(script.infer(3, len('os.path.join'))[0].full_name)
os.path.join
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()
def goto_assignments(self, **kwargs): # Python 2...
def goto(self, **kwargs):
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)
if not self._name.is_value_name:
@@ -397,7 +405,10 @@ class BaseDefinition(object):
return ''.join(lines[start_index:index + after + 1])
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):
return _values_to_definitions(self._name.infer().execute_with_values())
@@ -405,7 +416,7 @@ class BaseDefinition(object):
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.
"""
def __init__(self, inference_state, name, stack, like_name_length, is_fuzzy):
@@ -514,8 +525,8 @@ class Completion(BaseDefinition):
class Definition(BaseDefinition):
"""
*Definition* objects are returned from :meth:`api.Script.goto_assignments`
or :meth:`api.Script.goto_definitions`.
*Definition* objects are returned from :meth:`api.Script.goto`
or :meth:`api.Script.infer`.
"""
def __init__(self, inference_state, definition):
super(Definition, self).__init__(inference_state, definition)
@@ -538,8 +549,8 @@ class Definition(BaseDefinition):
... pass
...
... variable = f if random.choice([0,1]) else C'''
>>> script = Script(source, column=3) # line is maximum by default
>>> defs = script.goto_definitions()
>>> script = Script(source) # line is maximum by default
>>> defs = script.infer(column=3)
>>> defs = sorted(defs, key=lambda d: d.line)
>>> no_unicode_pprint(defs) # doctest: +NORMALIZE_WHITESPACE
[<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))
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
return the `isinstance` function. without `(` it would return nothing.
"""
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
@property
@@ -642,15 +653,15 @@ class Signature(Definition):
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
return the `isinstance` function with its params. Without `(` it would
return nothing.
"""
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._signature = signature

View File

@@ -10,7 +10,7 @@ from jedi import settings
from jedi.api import classes
from jedi.api import helpers
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.helpers import infer_call_of_leaf, parse_dotted_names
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
def get_call_signature_param_names(call_signatures):
def get_signature_param_names(signatures):
# add named params
for call_sig in call_signatures:
for call_sig in signatures:
for p in call_sig.params:
# Allow protected access, because it's a public API.
if p._name.get_kind() in (Parameter.POSITIONAL_OR_KEYWORD,
@@ -74,7 +74,7 @@ def get_flow_scope_node(module_node, position):
class Completion:
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._module_context = module_context
self._module_node = module_context.tree_node
@@ -86,27 +86,24 @@ class Completion:
# everything. We want the start of the name we're on.
self._original_position = position
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
def completions(self, fuzzy=False, **kwargs):
return self._completions(fuzzy, **kwargs)
def _completions(self, fuzzy):
def complete(self, fuzzy):
leaf = self._module_node.get_leaf_for_position(self._position, include_prefixes=True)
string, start_leaf = _extract_string_while_in_string(leaf, self._position)
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._like_name, self._call_signatures_callback,
self._like_name, self._signatures_callback,
self._code_lines, self._original_position,
fuzzy
))
if completions:
return completions
completion_names = self._get_value_completions(leaf)
completion_names = self._complete_python(leaf)
completions = filter_names(self._inference_state, completion_names,
self.stack, self._like_name, fuzzy)
@@ -115,7 +112,7 @@ class Completion:
x.name.startswith('_'),
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
return.
@@ -145,7 +142,7 @@ class Completion:
return []
# If we don't have a value, just use global completion.
return self._global_completions()
return self._complete_global_scope()
allowed_transitions = \
list(stack._allowed_transition_names_and_token_types())
@@ -185,7 +182,7 @@ class Completion:
completion_names = []
current_line = self._code_lines[self._position[0] - 1][:self._position[1]]
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,
PythonTokenTypes.INDENT)):
@@ -203,7 +200,7 @@ class Completion:
if nodes and nodes[-1] in ('as', 'def', 'class'):
# No completions for ``with x as foo`` and ``import x as foo``.
# 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:
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] == '.':
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:
completion_names += self._global_completions()
completion_names += self._get_class_value_completions(is_function=False)
completion_names += self._complete_global_scope()
completion_names += self._complete_inherited(is_function=False)
# Apparently this looks like it's good enough to filter most cases
# so that signature completions don't randomly appear.
@@ -229,17 +226,17 @@ class Completion:
# 3. Decorators are very primitive and have an optional `(` with
# optional arglist in them.
if nodes[-1] in ['(', ','] and nonterminals[-1] in ('trailer', 'arglist', 'decorator'):
call_signatures = self._call_signatures_callback()
completion_names += get_call_signature_param_names(call_signatures)
signatures = self._signatures_callback(*self._position)
completion_names += get_signature_param_names(signatures)
return completion_names
def _get_keyword_completion_names(self, allowed_transitions):
def _complete_keywords(self, allowed_transitions):
for k in allowed_transitions:
if isinstance(k, str) and k.isalpha():
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)
debug.dbg('global completion scope: %s', context)
flow_scope_node = get_flow_scope_node(self._module_node, self._position)
@@ -253,7 +250,7 @@ class Completion:
completion_names += filter.values()
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)
inferred_context = self._module_context.create_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)
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.
"""

View File

@@ -8,8 +8,8 @@ from jedi.inference.helpers import get_str_or_none
from jedi.parser_utils import get_string_quote
def file_name_completions(inference_state, module_context, start_leaf, string,
like_name, call_signatures_callback, code_lines, position, fuzzy):
def complete_file_name(inference_state, module_context, start_leaf, string,
like_name, signatures_callback, code_lines, position, fuzzy):
# First we want to find out what can actually be changed as a 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
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)
if is_in_os_path_join:
to_be_added = _add_os_path_join(module_context, start_leaf, sigs[0].bracket_start)

View File

@@ -4,6 +4,7 @@ Helpers for the API
import re
from collections import namedtuple
from textwrap import dedent
from functools import wraps
from parso.python.parser import Parser
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.helpers import infer_call_of_leaf
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'])
@@ -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':
# In case of a name we can just use goto_definition which does all the
# magic itself.
return inference_state.goto_definitions(context, leaf)
return inference_state.infer(context, leaf)
parent = leaf.parent
definitions = NO_VALUES
@@ -327,7 +326,7 @@ def _get_index_and_key(nodes, position):
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))):
# `index > 0` means that it's a trailer and not an atom.
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)
def get_call_signature_details(module, position):
def get_signature_details(module, position):
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
# case.
@@ -356,15 +355,15 @@ def get_call_signature_details(module, position):
node = leaf.parent
while node is not None:
if node.type in ('funcdef', 'classdef'):
# Don't show call signatures if there's stuff before it that just
# makes it feel strange to have a call signature.
# Don't show signatures if there's stuff before it that just
# makes it feel strange to have a signature.
return None
additional_children = []
for n in reversed(node.children):
if n.start_pos < position:
if n.type == 'error_node':
result = _get_call_signature_details_from_error_node(
result = _get_signature_details_from_error_node(
n, additional_children, position
)
if result is not None:
@@ -391,8 +390,8 @@ def get_call_signature_details(module, position):
return None
@call_signature_time_cache("call_signatures_validity")
def cache_call_signatures(inference_state, context, bracket_leaf, code_lines, user_pos):
@signature_time_cache("call_signatures_validity")
def cache_signatures(inference_state, context, bracket_leaf, code_lines, user_pos):
"""This function calculates the cache key."""
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!
else:
yield (module_path, before_bracket, bracket_leaf.start_pos)
yield infer_goto_definition(
yield infer(
inference_state,
context,
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

View File

@@ -75,7 +75,7 @@ def clear_time_caches(delete_all=False):
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
use the function with a callable that returns the key.

View File

@@ -143,7 +143,7 @@ class InferenceState(object):
"""Convenience function"""
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)
if def_ is not None:
type_ = def_.type

View File

@@ -74,7 +74,7 @@ def dynamic_param_lookup(function_value, param_index):
path = function_value.get_root_context().py__file__()
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).
# This makes everything slower. Just disable it and run the tests,
# 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)
return args
for value in inference_state.goto_definitions(context, name):
for value in inference_state.infer(context, name):
value_node = value.tree_node
if compare_node == value_node:
yield create_args(value)

View File

@@ -32,13 +32,13 @@ def _find_names(module_context, tree_name):
return _dictionarize(_resolve_names(found_names))
def usages(module_context, tree_name):
def find_references(module_context, tree_name):
search_name = tree_name.value
found_names = _find_names(module_context, tree_name)
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())
non_matching_usage_maps = {}
non_matching_reference_maps = {}
inf = module_context.inference_state
potential_modules = imports.get_module_contexts_containing_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):
found_names.update(new)
for tree_name in new:
for dct in non_matching_usage_maps.get(tree_name, []):
# A usage that was previously searched for matches with
# a now found name. Merge.
for dct in non_matching_reference_maps.get(tree_name, []):
# A reference that was previously searched for matches
# with a now found name. Merge.
found_names.update(dct)
try:
del non_matching_usage_maps[tree_name]
del non_matching_reference_maps[tree_name]
except KeyError:
pass
else:
for name in new:
non_matching_usage_maps.setdefault(name, []).append(new)
non_matching_reference_maps.setdefault(name, []).append(new)
return found_names.values()

View File

@@ -107,7 +107,7 @@ class TreeSignature(AbstractSignature):
for executed_param_name in executed_param_names)
if debug.enable_notice:
tree_node = self._function_value.tree_node
signature = parser_utils.get_call_signature(tree_node)
signature = parser_utils.get_signature(tree_node)
if matches:
debug.dbg("Overloading match: %s@%s (%s)",
signature, tree_node.start_pos[0], arguments, color='BLUE')

View File

@@ -108,7 +108,7 @@ def infer_node(context, element):
str_element_names = [e.value for e in element_names]
if any(i.value in str_element_names for i 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
# causes the complexity to rise. The complexity should
# never fall below 1.

View File

@@ -127,10 +127,10 @@ def safe_literal_eval(value):
return ''
def get_call_signature(funcdef, width=72, call_string=None,
omit_first_param=False, omit_return_annotation=False):
def get_signature(funcdef, width=72, call_string=None,
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.
:type width: int

View File

@@ -57,7 +57,7 @@ def rename(script, new_name):
:param script: The source Script object.
: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):
@@ -166,11 +166,11 @@ def inline(script):
dct = {}
definitions = script.goto_assignments()
definitions = script.goto()
assert len(definitions) == 1
stmt = definitions[0]._definition
usages = script.usages()
inlines = [r for r in usages
references = script.find_references()
inlines = [r for r in references
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),
reverse=True)

View File

@@ -83,7 +83,7 @@ def setup_readline(namespace_module=__main__, fuzzy=False):
logging.debug("Start REPL completion: " + repr(text))
interpreter = Interpreter(text, [namespace_module.__dict__])
completions = interpreter.completions(fuzzy=fuzzy)
completions = interpreter.complete(fuzzy=fuzzy)
logging.debug("REPL completions: %s", completions)
self.matches = [

View File

@@ -45,9 +45,9 @@ def run(code, index, infer=False):
start = time.time()
script = jedi.Script(code)
if infer:
result = script.goto_definitions()
result = script.infer()
else:
result = script.completions()
result = script.complete()
print('Used %ss for the %sth run.' % (time.time() - start, index + 1))
return result

View File

@@ -45,7 +45,7 @@ def run():
print('Process Memory before: %skB' % process_memory())
# After this the module should be 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.
print('Process Memory after: %skB' % process_memory())

View File

@@ -95,9 +95,7 @@ class TestCase(object):
args = json.load(f)
return cls(*args)
operations = [
'completions', 'goto_assignments', 'goto_definitions', 'usages',
'call_signatures']
operations = ['complete', 'goto', 'infer', 'find_references', 'find_signatures']
@classmethod
def generate(cls, file_path):
@@ -123,12 +121,12 @@ class TestCase(object):
def run(self, debugger, record=None, print_result=False):
try:
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 = {}
if self.operation == 'goto_assignments':
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:
print("{path}: Line {line} column {column}".format(**self.__dict__))
self.show_location(self.line, self.column)

View File

@@ -1,29 +1,29 @@
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[0].doc) > 100
r = list(Script("asfdasfd", 1, 1).goto_definitions())
r = list(Script("asfdasfd").infer(1, 1))
assert len(r) == 0
k = Script("fro").completions()[0]
k = Script("fro").complete()[0]
imp_start = '\nThe ``import'
assert k.raw_doc.startswith(imp_start)
assert k.doc.startswith(imp_start)
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]
# unrelated to #44
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[0].doc) > 100
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']

View File

@@ -1,4 +1,4 @@
# goto_assignments command tests are different in syntax
# goto command tests are different in syntax
definition = 3
#! 0 ['a = definition']

View File

@@ -1,7 +1,7 @@
from jedi import functions, inference, parsing
el = functions.completions()[0]
el = functions.complete()[0]
#? ['description']
el.description

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
results always contain position informations.
"""

View File

@@ -1,6 +1,6 @@
"""
Test coverage for renaming is mostly being done by testing
`Script.usages`.
`Script.find_references`.
"""
# --- simple

View File

@@ -10,9 +10,9 @@ tests.
There are different kind of tests:
- completions / goto_definitions ``#?``
- goto_assignments: ``#!``
- usages: ``#<``
- completions / inference ``#?``
- goto: ``#!``
- references: ``#<``
How to run tests?
+++++++++++++++++
@@ -26,7 +26,7 @@ multiple Python versions.
Integration test cases are located in ``test/completion`` directory
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
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``
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::
#? int()
ab = 3; ab
Goto Assignments
++++++++++++++++
Goto
++++
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']
abc
Usages
++++++
References
++++++++++
Tests look like this::
@@ -131,9 +131,9 @@ from jedi.inference.analysis import Warning
TEST_COMPLETIONS = 0
TEST_DEFINITIONS = 1
TEST_ASSIGNMENTS = 2
TEST_USAGES = 3
TEST_INFERENCE = 1
TEST_GOTO = 2
TEST_REFERENCES = 3
grammar36 = parso.load_grammar(version='3.6')
@@ -195,28 +195,25 @@ class IntegrationTestCase(BaseTestCase):
self.line_nr_test, self.line.rstrip())
def script(self, environment):
return jedi.Script(
self.source, self.line_nr, self.column, self.path,
environment=environment
)
return jedi.Script(self.source, path=self.path, environment=environment)
def run(self, compare_cb, environment=None):
testers = {
TEST_COMPLETIONS: self.run_completion,
TEST_DEFINITIONS: self.run_goto_definitions,
TEST_ASSIGNMENTS: self.run_goto_assignments,
TEST_USAGES: self.run_usages,
TEST_INFERENCE: self.run_inference,
TEST_GOTO: self.run_goto,
TEST_REFERENCES: self.run_find_references,
}
return testers[self.test_type](compare_cb, environment)
def run_completion(self, compare_cb, environment):
completions = self.script(environment).completions()
#import cProfile; cProfile.run('script.completions()')
completions = self.script(environment).complete(self.line_nr, self.column)
# import cProfile; cProfile.run('...')
comp_str = {c.name for c in completions}
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)
inference_state = script._inference_state
@@ -233,9 +230,6 @@ class IntegrationTestCase(BaseTestCase):
node = parser.get_root_node()
module_context = script._get_module_context()
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
results = convert_values(user_context.infer_node(node))
if not results:
@@ -250,17 +244,17 @@ class IntegrationTestCase(BaseTestCase):
return should
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)
return compare_cb(self, is_str, should)
def run_goto_assignments(self, compare_cb, environment):
result = self.script(environment).goto_assignments()
def run_goto(self, compare_cb, environment):
result = self.script(environment).goto(self.line_nr, self.column)
comp_str = str(sorted(str(r.description) for r in result))
return compare_cb(self, comp_str, self.correct)
def run_usages(self, compare_cb, environment):
result = self.script(environment).usages()
def run_find_references(self, compare_cb, environment):
result = self.script(environment).find_references(self.line_nr, self.column)
self.correct = self.correct.strip()
compare = sorted(
(re.sub(r'^test\.completion\.', '', r.module_name), r.line, r.column)
@@ -287,7 +281,7 @@ class IntegrationTestCase(BaseTestCase):
class StaticAnalysisCase(BaseTestCase):
"""
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):
self._path = path
@@ -311,12 +305,14 @@ class StaticAnalysisCase(BaseTestCase):
return cases
def run(self, compare_cb, environment):
def typ_str(inst):
return 'warning ' if isinstance(inst, Warning) else ''
analysis = jedi.Script(
self._source,
path=self._path,
environment=environment,
)._analysis()
typ_str = lambda inst: 'warning ' if isinstance(inst, Warning) else ''
analysis = [(r.line, r.column, typ_str(r) + r.name)
for r in analysis]
compare_cb(self, analysis, self.collect_comparison())
@@ -354,19 +350,19 @@ def collect_file_tests(path, lines, lines_to_execute):
else:
column = len(line) - 1 # -1 for the \n
if test_type == '!':
yield makecase(TEST_ASSIGNMENTS)
yield makecase(TEST_GOTO)
elif test_type == '<':
yield makecase(TEST_USAGES)
yield makecase(TEST_REFERENCES)
elif correct.startswith('['):
yield makecase(TEST_COMPLETIONS)
else:
yield makecase(TEST_DEFINITIONS)
yield makecase(TEST_INFERENCE)
correct = None
else:
skip_version_info = skip_python_version(line) or skip_version_info
try:
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)
correct = r.group(2)
# Quick hack to make everything work (not quite a bloody unicorn hack though).

View File

@@ -1,4 +1,4 @@
"""
An import tree, for testing usages.
An import tree, for testing references.
"""

View File

@@ -56,29 +56,29 @@ def test_line_number_errors(Script):
s = 'hello'
# lines
with raises(ValueError):
Script(s, 2, 0)
Script(s).complete(2, 0)
with raises(ValueError):
Script(s, 0, 0)
Script(s).complete(0, 0)
# columns
with raises(ValueError):
Script(s, 1, len(s) + 1)
Script(s).infer(1, len(s) + 1)
with raises(ValueError):
Script(s, 1, -1)
Script(s).goto(1, -1)
# ok
Script(s, 1, 0)
Script(s, 1, len(s))
Script(s).find_signatures(1, 0)
Script(s).find_references(1, len(s))
def _check_number(Script, source, result='float'):
completions = Script(source).completions()
completions = Script(source).complete()
assert completions[0].parent().name == result
def test_completion_on_number_literals(Script):
# 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']
# 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.e-3.')
_check_number(Script, '9e3.')
assert Script('1.e3..').completions() == []
assert Script('1.e-13..').completions() == []
assert Script('1.e3..').complete() == []
assert Script('1.e-13..').complete() == []
def test_completion_on_hex_literals(Script):
assert Script('0x1..').completions() == []
assert Script('0x1..').complete() == []
_check_number(Script, '0x1.', 'int') # hexdecimal
# Completing binary literals doesn't work if they are not actually binary
# (invalid statements).
assert Script('0b2.b').completions() == []
assert Script('0b2.b').complete() == []
_check_number(Script, '0b1.', 'int') # binary
_check_number(Script, '0x2e.', 'int')
_check_number(Script, '0xE7.', 'int')
_check_number(Script, '0xEa.', 'int')
# theoretically, but people can just check for syntax errors:
assert Script('0x.').completions() == []
assert Script('0x.').complete() == []
def test_completion_on_complex_literals(Script):
assert Script('1j..').completions() == []
assert Script('1j..').complete() == []
_check_number(Script, '1j.', 'complex')
_check_number(Script, '44.j.', '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!
# However this has been disabled again, because it apparently annoyed
# users. So no completion after j without a space :)
assert not Script('4j').completions()
assert ({c.name for c in Script('4j ').completions()} ==
assert not Script('4j').complete()
assert ({c.name for c in Script('4j ').complete()} ==
{'if', 'and', 'in', 'is', 'not', 'or'})
def test_goto_assignments_on_non_name(Script, environment):
assert Script('for').goto_assignments() == []
def test_goto_non_name(Script, environment):
assert Script('for').goto() == []
assert Script('assert').goto_assignments() == []
assert Script('True').goto_assignments() == []
assert Script('assert').goto() == []
assert Script('True').goto() == []
def test_goto_definitions_on_non_name(Script):
assert Script('import x', column=0).goto_definitions() == []
def test_infer_on_non_name(Script):
assert Script('import x').infer(column=0) == []
def test_goto_definitions_on_generator(Script):
def_, = Script('def x(): yield 1\ny=x()\ny').goto_definitions()
def test_infer_on_generator(Script):
def_, = Script('def x(): yield 1\ny=x()\ny').infer()
assert def_.name == 'Generator'
@@ -159,17 +159,17 @@ def test_goto_definition_not_multiple(Script):
else:
a = A(1)
a''')
assert len(Script(s).goto_definitions()) == 1
assert len(Script(s).infer()) == 1
def test_usage_description(Script):
descs = [u.description for u in Script("foo = ''; foo").usages()]
def test_reference_description(Script):
descs = [u.description for u in Script("foo = ''; foo").find_references()]
assert set(descs) == {"foo = ''", 'foo'}
def test_get_line_code(Script):
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
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):
abs_ = Script('abs').completions()[0]
abs_ = Script('abs').complete()[0]
assert abs_.name == 'abs'
assert abs_.get_line_code() == ''
assert abs_.line is None
def test_goto_assignments_follow_imports(Script):
def test_goto_follow_imports(Script):
code = dedent("""
import inspect
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 (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 (definition.line, definition.column) > (1, 0)
code = '''def param(p): pass\nparam(1)'''
start_pos = 1, len('def param(')
script = Script(code, *start_pos)
definition, = script.goto_assignments(follow_imports=True)
script = Script(code)
definition, = script.goto(*start_pos, follow_imports=True)
assert (definition.line, definition.column) == start_pos
assert definition.name == 'p'
result, = definition.goto_assignments()
result, = definition.goto()
assert result.name == 'p'
result, = definition.infer()
assert result.name == 'int'
result, = result.infer()
assert result.name == 'int'
definition, = script.goto_assignments()
definition, = script.goto(*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'
def test_goto_module(Script):
def check(line, expected, follow_imports=False):
script = Script(path=path, line=line)
module, = script.goto_assignments(follow_imports=follow_imports)
script = Script(path=path)
module, = script.goto(line=line, follow_imports=follow_imports)
assert module.module_path == expected
base_path = os.path.join(os.path.dirname(__file__), 'simple_import')
@@ -264,7 +264,7 @@ def test_goto_definition_cursor(Script):
should2 = 8, 10
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)
under_score = get_def(under_score)
@@ -290,7 +290,7 @@ def test_no_statement_parent(Script):
pass
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)
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()
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'
def test_goto_follow_builtin_imports(Script):
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
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
def test_docstrings_for_completions(Script):
for c in Script('').completions():
for c in Script('').complete():
assert isinstance(c.docstring(), (str, unicode))
def test_fuzzy_completion(Script):
script = Script('string = "hello"\nstring.upper')
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):
@@ -331,7 +331,7 @@ def test_math_fuzzy_completion(Script, environment):
expected = ['copysign', 'log', 'log10', 'log1p']
if environment.version_info.major >= 3:
expected.append('log2')
completions = script.completions(fuzzy=True)
completions = script.complete(fuzzy=True)
assert expected == [comp.name for comp in completions]
for c in completions:
assert c.complete is None
@@ -341,7 +341,7 @@ def test_file_fuzzy_completion(Script):
path = os.path.join(test_dir, 'completion')
script = Script('"{}/ep08_i'.format(path))
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(
@@ -355,6 +355,14 @@ def test_file_fuzzy_completion(Script):
]
)
def test_goto_on_string(Script, code, column):
script = Script(code, column=column)
assert not script.goto_definitions()
assert not script.goto_assignments()
script = Script(code)
assert not script.infer(column=column)
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

View File

@@ -6,14 +6,14 @@ from ..helpers import cwd_at
def test_import_empty(Script):
""" github #340, return the full word. """
completion = Script("import ").completions()[0]
completion = Script("import ").complete()[0]
definition = completion.infer()[0]
assert definition
def check_follow_definition_types(Script, source):
# 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)
return [d.type for d in defs]
@@ -27,7 +27,7 @@ def test_follow_import_incomplete(Script, environment):
assert datetime == ['module']
# 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']
assert len(definitions) == 1
assert [d.type for d in definitions[0].infer()] == ['class']

View File

@@ -6,12 +6,12 @@ import pytest
from ..helpers import TestCase
from jedi import cache
from jedi.parser_utils import get_call_signature
from jedi.parser_utils import get_signature
from jedi import Interpreter
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
@@ -28,7 +28,7 @@ def test_valid_call(Script):
assert_signature(Script, 'bool()', 'bool', column=5)
class TestCallSignatures(TestCase):
class TestSignatures(TestCase):
@pytest.fixture(autouse=True)
def init(self, Script):
self.Script = Script
@@ -96,12 +96,12 @@ class TestCallSignatures(TestCase):
def test_with(Script):
# jedi-vim #9
sigs = Script("with open(").call_signatures()
sigs = Script("with open(").find_signatures()
assert 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("""\
def f(a, b):
pass
@@ -118,10 +118,10 @@ def test_multiple_signatures(Script):
def f(a, b):
pass
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("""\
abs(
def x():
@@ -148,7 +148,7 @@ def test_decorator_in_class(Script):
C().test(""")
signatures = Script(s).call_signatures()
signatures = Script(s).find_signatures()
assert len(signatures) == 1
x = [p.description for p in signatures[0].params]
assert x == ['param *args']
@@ -176,14 +176,14 @@ def test_brackets_in_string_literals(Script):
def test_function_definitions_should_break(Script):
"""
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 not Script('abs(\ndef x(): pass').call_signatures()
assert not Script('abs(\ndef x(): pass').find_signatures()
def test_flow_call(Script):
assert not Script('if (1').call_signatures()
assert not Script('if (1').find_signatures()
def test_chained_calls(Script):
@@ -209,11 +209,11 @@ def test_return(Script):
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"""
s = 'import datetime; datetime('
# 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):
@@ -234,7 +234,7 @@ def test_complex(Script, environment):
re.compile(
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.index == sig2.index == 0
func1, = sig1._name.infer()
@@ -243,14 +243,14 @@ def test_complex(Script, environment):
if environment.version_info.major == 3:
# Do these checks just for Python 3, I'm too lazy to deal with this
# legacy stuff. ~ dave.
assert get_call_signature(func1.tree_node) \
assert get_signature(func1.tree_node) \
== '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]'
# jedi-vim #70
s = """def foo("""
assert Script(s).call_signatures() == []
assert Script(s).find_signatures() == []
# jedi-vim #116
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):
signatures = Script(source, line, column).call_signatures()
signatures = Script(source, line, column).find_signatures()
assert len(signatures) == 1
return signatures[0].params
def test_int_params(Script):
sig1, sig2 = Script('int(').call_signatures()
sig1, sig2 = Script('int(').find_signatures()
# int is defined as: `int(x[, base])`
assert len(sig1.params) == 1
assert sig1.params[0].name == 'x'
@@ -275,13 +275,13 @@ def test_int_params(Script):
def test_pow_params(Script):
# 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]
assert param_names in (['x', 'y'], ['x', 'y', 'z'])
def test_param_name(Script):
sigs = Script('open(something,').call_signatures()
sigs = Script('open(something,').find_signatures()
for sig in sigs:
# All of the signatures (in Python the function is overloaded),
# contain the same param names.
@@ -304,19 +304,19 @@ def test_builtins(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.
"""
s = """class Spam(): pass\nSpam"""
signature = Script(s + '(').call_signatures()[0]
definition = Script(s + '(', column=0).goto_definitions()[0]
signature = Script(s + '(').find_signatures()[0]
definition = Script(s + '(').infer(column=0)[0]
signature.line == 1
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):
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:
continue
@@ -330,15 +330,15 @@ def test_signature_is_definition(Script):
def test_no_signature(Script):
# str doesn't have a __call__ method
assert Script('str()(').call_signatures() == []
assert Script('str()(').find_signatures() == []
s = dedent("""\
class X():
pass
X()(""")
assert Script(s).call_signatures() == []
assert len(Script(s, column=2).call_signatures()) == 1
assert Script('').call_signatures() == []
assert Script(s).find_signatures() == []
assert len(Script(s).find_signatures(column=2)) == 1
assert Script('').find_signatures() == []
def test_dict_literal_in_incomplete_call(Script):
@@ -354,24 +354,24 @@ def test_dict_literal_in_incomplete_call(Script):
c = Foo()
"""
script = Script(dedent(source), line=4, column=15)
assert script.call_signatures()
script = Script(dedent(source))
assert script.find_signatures(line=4, column=15)
def test_completion_interference(Script):
"""Seems to cause problems, see also #396."""
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.
assert Script('from datetime import ').completions()
# complete something usual, before doing the same find_signatures again.
assert Script('from datetime import ').complete()
assert Script('open(').call_signatures()
assert Script('open(').find_signatures()
def test_keyword_argument_index(Script, environment):
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.
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):
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
assert expected_index == index
@@ -547,14 +547,14 @@ def test_arg_defaults(Script, environment, code):
yield Interpreter(code + '2(', namespaces=[executed_locals])
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[1].description == 'param arg1=1'
def test_bracket_start(Script):
def bracket_start(src):
signatures = Script(src).call_signatures()
signatures = Script(src).find_signatures()
assert len(signatures) == 1
return signatures[0].bracket_start
@@ -564,7 +564,7 @@ def test_bracket_start(Script):
def test_different_caller(Script):
"""
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)
@@ -579,14 +579,14 @@ def test_in_function(Script):
class X():
@property
def func(''')
assert not Script(code).call_signatures()
assert not Script(code).find_signatures()
def test_lambda_params(Script):
code = dedent('''\
my_lambda = lambda x: x+1
my_lambda(1)''')
sig, = Script(code, column=11).call_signatures()
sig, = Script(code).find_signatures(column=11)
assert sig.index == 0
assert sig.name == '<lambda>'
assert [p.name for p in sig.params] == ['x']
@@ -601,19 +601,19 @@ class X():
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.name == 'X'
assert [p.name for p in sig.params] == ['foo', 'bar']
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']
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']
@@ -623,14 +623,14 @@ def test_call_magic_method(Script):
def __call__(self, baz):
pass
''')
sig, = Script(code + 'X()(').call_signatures()
sig, = Script(code + 'X()(').find_signatures()
assert sig.index == 0
assert sig.name == 'X'
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']
sig, = Script(code + 'X().__call__(').call_signatures()
sig, = Script(code + 'X().__call__(').find_signatures()
assert [p.name for p in sig.params] == ['baz']
@@ -642,9 +642,9 @@ def test_cursor_after_signature(Script, column):
foo() # _
""")
script = Script(source, 4, column)
script = Script(source)
assert not script.call_signatures()
assert not script.find_signatures(4, column)
@pytest.mark.parametrize(
@@ -661,7 +661,7 @@ def test_cursor_after_signature(Script, column):
]
)
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.index == index

View File

@@ -14,7 +14,7 @@ from ..helpers import get_example_dir
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
@@ -48,15 +48,15 @@ def test_basedefinition_type(Script, names):
source += dedent("""
variable = sys or C or x or f or g or g() or h""")
lines = source.splitlines()
script = Script(source, len(lines), len('variable'), None)
definitions += script.goto_definitions()
script = Script(source, path=None)
definitions += script.infer(len(lines), len('variable'))
script2 = Script(source, 4, len('class C'), None)
definitions += script2.usages()
script2 = Script(source, path=None)
definitions += script2.find_references(4, len('class C'))
source_param = "def f(a): return a"
script_param = Script(source_param, 1, len(source_param), None)
definitions += script_param.goto_assignments()
script_param = Script(source_param, path=None)
definitions += script_param.goto(1, len(source_param))
return definitions
@@ -88,15 +88,15 @@ def test_basedefinition_type(Script, names):
)
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}
def test_function_call_signature_in_doc(Script):
def test_function_signature_in_doc(Script):
defs = Script("""
def f(x, y=1, z='a'):
pass
f""").goto_definitions()
f""").infer()
doc = defs[0].docstring()
assert "f(x, y=1, z='a')" in str(doc)
@@ -107,18 +107,18 @@ def test_param_docstring(names):
assert param.docstring() == ''
def test_class_call_signature(Script):
def test_class_signature(Script):
defs = Script("""
class Foo:
def __init__(self, x, y=1, z='a'):
pass
Foo""").goto_definitions()
Foo""").infer()
doc = defs[0].docstring()
assert doc == "Foo(x, y=1, z='a')"
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].line 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
"""
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)
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)
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):
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']
def test_functions_should_have_params(Script):
for c in Script('bool.').completions():
for c in Script('bool.').complete():
if c.type == 'function':
assert isinstance(c.params, list)
@@ -189,7 +189,7 @@ def test_hashlib_params(Script, environment):
pytest.skip()
script = Script(source='from hashlib import sha256')
c, = script.completions()
c, = script.complete()
assert [p.name for p in c.params] == ['arg']
@@ -204,10 +204,10 @@ def test_signature_params(Script):
pass
foo''')
check(Script(s).goto_definitions())
check(Script(s).infer())
check(Script(s).goto_assignments())
check(Script(s + '\nbar=foo\nbar').goto_assignments())
check(Script(s).goto())
check(Script(s + '\nbar=foo\nbar').goto())
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
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=""']
@@ -253,7 +253,7 @@ def test_is_definition_import(names, code, expected):
def test_parent(Script):
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()
parent = _parent('foo=1\nfoo')
@@ -270,7 +270,7 @@ def test_parent(Script):
def test_parent_on_function(Script):
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()
assert parent.name == ''
assert parent.type == 'module'
@@ -280,20 +280,20 @@ def test_parent_on_completion(Script):
parent = Script(dedent('''\
class Foo():
def bar(): pass
Foo().bar''')).completions()[0].parent()
Foo().bar''')).complete()[0].parent()
assert parent.name == 'Foo'
assert parent.type == 'class'
parent = Script('str.join').completions()[0].parent()
parent = Script('str.join').complete()[0].parent()
assert parent.name == 'str'
assert parent.type == 'class'
def test_parent_on_comprehension():
ns = jedi.names('''\
def test_parent_on_comprehension(Script):
ns = Script('''\
def spam():
return [i for i in range(5)]
''', all_scopes=True)
''').names(all_scopes=True)
assert [name.name for name in ns] == ['spam', 'i']
@@ -304,17 +304,17 @@ def test_parent_on_comprehension():
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.
assert c.type == 'class'
else:
assert c.type in ('function', 'statement')
for c in Script('list.').completions():
for c in Script('list.').complete():
assert c.type
# 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
@@ -322,36 +322,36 @@ def test_type_II(Script):
"""
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':
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
different as an implementation.
"""
def test_goto_assignment_repetition(names):
def test_goto_repetition(names):
defs = names('a = 1; a', references=True, definitions=False)
# Repeat on the same variable. Shouldn't change once we're on a
# definition.
for _ in range(3):
assert len(defs) == 1
ass = defs[0].goto_assignments()
ass = defs[0].goto()
assert ass[0].description == 'a = 1'
def test_goto_assignments_named_params(names):
def test_goto_named_params(names):
src = """\
def foo(a=1, bar=2):
pass
foo(bar=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.type == 'param'
@@ -360,46 +360,46 @@ def test_class_call(names):
src = 'from threading import Thread; Thread(group=1)'
n = names(src, references=True)[-1]
assert n.name == 'group'
param_def = n.goto_assignments()[0]
param_def = n.goto()[0]
assert param_def.name == 'group'
assert param_def.type == 'param'
def test_parentheses(names):
n = names('("").upper', references=True)[-1]
assert n.goto_assignments()[0].name == 'upper'
assert n.goto()[0].name == 'upper'
def test_import(names):
nms = names('from json import load', references=True)
assert nms[0].name == 'json'
assert nms[0].type == 'module'
n = nms[0].goto_assignments()[0]
n = nms[0].goto()[0]
assert n.name == 'json'
assert n.type == 'module'
assert nms[1].name == 'load'
assert nms[1].type == 'function'
n = nms[1].goto_assignments()[0]
n = nms[1].goto()[0]
assert n.name == 'load'
assert n.type == 'function'
nms = names('import os; os.path', references=True)
assert nms[0].name == 'os'
assert nms[0].type == 'module'
n = nms[0].goto_assignments()[0]
n = nms[0].goto()[0]
assert n.name == 'os'
assert n.type == 'module'
n = nms[2].goto_assignments()[0]
n = nms[2].goto()[0]
assert n.name == 'path'
assert n.type == 'module'
nms = names('import os.path', references=True)
n = nms[0].goto_assignments()[0]
n = nms[0].goto()[0]
assert n.name == 'os'
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
# os.path is a sys.modules hack, it does.
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].type == 'module'
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.type == 'module'
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].type == 'module'
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 ass[0].name == 'json'
assert ass[0].type == 'module'
@@ -432,7 +432,7 @@ def test_added_equals_to_params(Script):
def foo(bar, baz):
pass
""")
results = Script(source + rest_source).completions()
results = Script(source + rest_source).complete()
assert len(results) == 1
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
confusing.
"""
semlock, = Script('from _multiprocessing import SemLock').goto_definitions()
semlock, = Script('from _multiprocessing import SemLock').infer()
assert isinstance(semlock._name, CompiledValueName)
assert semlock.module_path is None
assert semlock.in_builtin_module() is True
@@ -468,7 +468,7 @@ def test_builtin_module_with_path(Script):
]
)
def test_execute(Script, code, description):
definition, = Script(code).goto_assignments()
definition, = Script(code).goto()
definitions = definition.execute()
if description is None:
assert not definitions
@@ -477,7 +477,7 @@ def test_execute(Script, code, description):
assert d.description == description
@pytest.mark.parametrize('goto_assignment', [False, True, None])
@pytest.mark.parametrize('goto', [False, True, None])
@pytest.mark.parametrize(
'code, name, file_name', [
('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'),
])
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')
whatever_path = os.path.join(base_path, 'NOT_EXISTING.py')
script = Script(code, path=whatever_path)
if goto_assignment is None:
func, = script.goto_definitions()
if goto is None:
func, = script.infer()
else:
func, = script.goto_assignments(follow_imports=goto_assignment)
func, = script.goto(follow_imports=goto)
assert func.type == 'function'
assert func.name == name
assert func.module_path == os.path.join(base_path, file_name)

View File

@@ -4,14 +4,16 @@ import sys
from textwrap import dedent
import pytest
from ..helpers import root_dir
from jedi.api.helpers import start_match, fuzzy_match
def test_in_whitespace(Script):
code = dedent('''
def x():
pass''')
assert len(Script(code, column=2).completions()) > 20
assert len(Script(code).complete(column=2)) > 20
def test_empty_init(Script):
@@ -19,7 +21,7 @@ def test_empty_init(Script):
code = dedent('''\
class X(object): pass
X(''')
assert Script(code).completions()
assert Script(code).complete()
def test_in_empty_space(Script):
@@ -28,7 +30,7 @@ def test_in_empty_space(Script):
def __init__(self):
hello
''')
comps = Script(code, 3, 7).completions()
comps = Script(code).complete(3, 7)
self, = [c for c in comps if c.name == 'self']
assert self.name == 'self'
def_, = self.infer()
@@ -41,13 +43,13 @@ def test_indent_value(Script):
complete.
"""
code = 'if 1:\nisinstanc'
comp, = Script(code).completions()
comp, = Script(code).complete()
assert comp.name == 'isinstance'
def test_keyword_value(Script):
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')
assert 'if' in names
@@ -56,7 +58,7 @@ def test_keyword_value(Script):
def test_os_nowait(Script):
""" 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]
@@ -64,7 +66,7 @@ def test_points_in_completion(Script):
"""At some point, points were inserted into the completions, this
caused problems, sometimes.
"""
c = Script("if IndentationErr").completions()
c = Script("if IndentationErr").complete()
assert c[0].name == 'IndentationError'
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:
f.write(data)
s = Script("from test1 import foo\nfoo.",
line=2, column=4, path=filename2)
s.completions()
s = Script("from test1 import foo\nfoo.", path=filename2)
s.complete(line=2, column=4)
def test_fake_subnodes(Script):
@@ -100,7 +101,7 @@ def test_fake_subnodes(Script):
return c
limit = None
for i in range(2):
completions = Script('').completions()
completions = Script('').complete()
c = get_str_completion(completions)
str_value, = c._name.infer()
n = len(str_value.tree_node.children[-1].children)
@@ -116,17 +117,17 @@ def test_generator(Script):
s = "def abc():\n" \
" yield 1\n" \
"abc()."
assert Script(s).completions()
assert Script(s).complete()
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.
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):
assert not Script(" # Foo\n'asdf'", line=1).completions()
assert not Script(" # Foo\n'asdf'").complete(line=1)
def test_async(Script, environment):
@@ -137,16 +138,15 @@ def test_async(Script, environment):
foo = 3
async def x():
hey = 3
ho'''
)
comps = Script(code, column=4).completions()
ho''')
comps = Script(code).complete(column=4)
names = [c.name for c in comps]
assert 'foo' in names
assert 'hey' in names
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(
@@ -161,7 +161,7 @@ def test_with_stmt_error_recovery(Script):
)
)
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')
@@ -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, 11, ['letion' + s]),
('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
(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
if isinstance(column, tuple):
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":
assert len(comps) > 100 # This is basically global completions.
else:
assert [c.complete for c in comps] == expected
from jedi.api.helpers import start_match, fuzzy_match
def test_start_match():
assert start_match('Condition', 'C')
def test_fuzzy_match():
assert fuzzy_match('Condition', 'i')
assert not fuzzy_match('Condition', 'p')

View File

@@ -139,12 +139,12 @@ def test_follow_imports(names):
def test_names_twice(names):
source = dedent('''
code = dedent('''
def lol():
pass
''')
defs = names(source=source)
defs = names(code)
assert defs[0].defined_names() == []
@@ -166,4 +166,4 @@ def test_no_error(names):
assert a.name == 'a'
assert b.name == 'b'
assert a20.name == 'a'
assert a20.goto_assignments() == [a20]
assert a20.goto() == [a20]

View File

@@ -66,13 +66,13 @@ def test_error_in_environment(inference_state, Script, environment):
with pytest.raises(jedi.InternalError):
inference_state.compiled_subprocess._test_raise_error(KeyboardInterrupt)
# Jedi should still work.
def_, = Script('str').goto_definitions()
def_, = Script('str').infer()
assert def_.name == 'str'
def test_stdout_in_subprocess(inference_state, Script):
inference_state.compiled_subprocess._test_print(stdout='.')
Script('1').goto_definitions()
Script('1').infer()
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
# Jedi call fails.
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.
assert def_.name == 'str'

View File

@@ -31,7 +31,7 @@ class MixinTestFullName(object):
def check(self, source, desired):
script = self.Script(textwrap.dedent(source))
definitions = getattr(script, type(self).operation)()
definitions = getattr(script, self.operation)()
for d in definitions:
self.assertEqual(d.full_name, desired)
@@ -43,7 +43,7 @@ class MixinTestFullName(object):
class TestFullNameWithGotoDefinitions(MixinTestFullName, TestCase):
operation = 'goto_definitions'
operation = 'infer'
def test_tuple_mapping(self):
if self.environment.version_info.major == 2:
@@ -59,7 +59,7 @@ class TestFullNameWithGotoDefinitions(MixinTestFullName, TestCase):
class TestFullNameWithCompletions(MixinTestFullName, TestCase):
operation = 'completions'
operation = 'complete'
class TestFullDefinedName(TestCase):
@@ -71,7 +71,8 @@ class TestFullDefinedName(TestCase):
self.environment = environment
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]
self.assertEqual(full_names, desired)
@@ -96,19 +97,19 @@ def test_sub_module(Script, jedi_path):
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']
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']
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'
d, = Script('import os.p').completions()
d, = Script('import os.p').complete()
assert d.full_name == 'os.path'
def test_os_issues(Script):
"""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']

View File

@@ -26,7 +26,7 @@ class _GlobalNameSpace:
def get_completion(source, namespace):
i = jedi.Interpreter(source, [namespace])
completions = i.completions()
completions = i.complete()
assert len(completions) == 1
return completions[0]
@@ -111,7 +111,7 @@ def test_side_effect_completion():
def _assert_interpreter_complete(source, namespace, completions,
**kwds):
script = jedi.Interpreter(source, [namespace], **kwds)
cs = script.completions()
cs = script.complete()
actual = [c.name for c in cs]
assert sorted(actual) == sorted(completions)
@@ -298,7 +298,7 @@ def test_property_content():
return 1
foo = Foo3()
def_, = jedi.Interpreter('foo.bar', [locals()]).goto_definitions()
def_, = jedi.Interpreter('foo.bar', [locals()]).infer()
assert def_.name == 'int'
@@ -310,7 +310,7 @@ def test_param_completion():
lambd = lambda xyz: 3
_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():
@@ -325,7 +325,7 @@ def test_completion_params():
foo = lambda a, b=3: None
script = jedi.Interpreter('foo', [locals()])
c, = script.completions()
c, = script.complete()
assert [p.name for p in c.params] == ['a', 'b']
assert c.params[0].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'
exec_(code, locals())
script = jedi.Interpreter('foo', [locals()])
c, = script.completions()
c, = script.complete()
a, b, c = c.params
assert a.infer() == []
assert [d.name for d in b.infer()] == ['str']
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'
@@ -354,7 +354,7 @@ def test_keyword_argument():
def f(some_keyword_argument):
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.complete == 'ord_argument='
@@ -362,7 +362,7 @@ def test_keyword_argument():
if is_py3:
# Make it impossible for jedi to find the source of the function.
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'
@@ -376,12 +376,12 @@ def test_more_complex_instances():
return Something()
#script = jedi.Interpreter('Base().wow().foo', [locals()])
#c, = script.completions()
#c, = script.complete()
#assert c.name == 'foo'
x = Base()
script = jedi.Interpreter('x.wow().foo', [locals()])
c, = script.completions()
c, = script.complete()
assert c.name == 'foo'
@@ -397,7 +397,7 @@ def test_repr_execution_issue():
er = ErrorRepr()
script = jedi.Interpreter('er', [locals()])
d, = script.goto_definitions()
d, = script.infer()
assert d.name == 'ErrorRepr'
assert d.type == 'instance'
@@ -419,7 +419,7 @@ def test_dir_magic_method(allow_unsafe_getattr):
return ['foo', 'bar'] + names
itp = jedi.Interpreter("ca.", [{'ca': CompleteAttrs()}])
completions = itp.completions()
completions = itp.complete()
names = [c.name for c in completions]
assert ('__dir__' in names) == is_py3
assert '__class__' in names
@@ -447,19 +447,19 @@ def test_name_not_findable():
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():
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']
def test_sys_path_docstring(): # Was an issue in #1298
import jedi
s = jedi.Interpreter("from sys import path\npath", line=2, column=4, namespaces=[locals()])
s.completions()[0].docstring()
s = jedi.Interpreter("from sys import path\npath", namespaces=[locals()])
s.complete(line=2, column=4)[0].docstring()
@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'])
string = ''
defs = jedi.Interpreter(code, [locals()]).completions()
defs = jedi.Interpreter(code, [locals()]).complete()
assert [d.name for d in defs] == completions
@@ -516,7 +516,7 @@ def test__wrapped__():
def syslogs_to_df():
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.
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'])
def test_core_module_completes(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")
@@ -548,7 +548,7 @@ def test_partial_signatures(code, expected, index):
b = functools.partial(func, 1)
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 [p.name for p in sig.params] == expected
assert index == sig.index
@@ -559,7 +559,7 @@ def test_type_var():
"""This was an issue before, see Github #1369"""
import typing
x = typing.TypeVar('myvar')
def_, = jedi.Interpreter('x', [locals()]).goto_definitions()
def_, = jedi.Interpreter('x', [locals()]).infer()
assert def_.name == 'TypeVar'
@@ -573,5 +573,5 @@ def test_param_annotation_completion(class_is_findable):
Foo.__name__ = 'asdf'
code = 'def CallFoo(x: Foo):\n x.ba'
def_, = jedi.Interpreter(code, [locals()]).completions()
def_, = jedi.Interpreter(code, [locals()]).complete()
assert def_.name == 'bar'

View File

@@ -5,38 +5,38 @@ Test of keywords and ``jedi.keywords``
import pytest
def test_goto_assignments_keyword(Script):
def test_goto_keyword(Script):
"""
Bug: goto assignments on ``in`` used to raise AttributeError::
'unicode' object has no attribute 'generate_call_path'
"""
Script('in').goto_assignments()
Script('in').goto()
def test_keyword(Script, environment):
""" github jedi-vim issue #44 """
defs = Script("print").goto_definitions()
defs = Script("print").infer()
if environment.version_info.major < 3:
assert defs == []
else:
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 Script("assert").goto_definitions() == []
assert Script("assert").infer() == []
def test_keyword_attributes(Script):
def_, = Script('def').completions()
def_, = Script('def').complete()
assert def_.name == 'def'
assert def_.complete == ''
assert def_.is_keyword is True
assert def_.is_stub() is False
assert def_.goto_assignments(only_stubs=True) == []
assert def_.goto_assignments() == []
assert def_.goto(only_stubs=True) == []
assert def_.goto() == []
assert def_.infer() == []
assert def_.parent() is None
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.
pytest.skip()
none, = Script('None').completions()
none, = Script('None').complete()
assert not none.docstring()
assert none.name == 'None'

View File

@@ -11,7 +11,7 @@ def test_django_default_project(Script):
"from app import models\nmodels.SomeMo",
path=os.path.join(dir, 'models/x.py')
)
c, = script.completions()
c, = script.complete()
assert c.name == "SomeModel"
assert script._inference_state.project._django is True

View File

@@ -18,7 +18,7 @@ def test_add_dynamic_mods(Script):
src2 = 'from .. import setup; setup.r(1)'
script = Script(src1, path='../setup.py')
imports.load_module(script._inference_state, os.path.abspath(fname), src2)
result = script.goto_definitions()
result = script.infer()
assert len(result) == 1
assert result[0].description == 'class int'
@@ -30,5 +30,5 @@ def test_add_bracket_after_function(monkeypatch, Script):
def foo():
pass
foo''')
completions = script.completions()
completions = script.complete()
assert completions[0].complete == '('

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):
func, = Script(code).goto_assignments()
func, = Script(code).goto()
sig, = func.get_signatures()
for p, expected in zip(sig.params, expected_params):
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):
func, = Script(code).goto_assignments()
func, = Script(code).goto()
sig, = func.get_signatures()
for p, expected in zip(sig.params, expected_params):
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):
func, = Script(code).goto_assignments()
func, = Script(code).goto()
sig, = func.get_signatures()
param = sig.params[index]
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):
s, = Script('staticmethod(').call_signatures()
s, = Script('staticmethod(').find_signatures()
assert s.to_string() == 'staticmethod(f: Callable[..., Any])'

View File

@@ -8,18 +8,18 @@ from jedi._compatibility import u, unicode
def test_unicode_script(Script):
""" normally no unicode objects are being used. (<=2.7) """
s = unicode("import datetime; datetime.timedelta")
completions = Script(s).completions()
completions = Script(s).complete()
assert len(completions)
assert type(completions[0].description) is unicode
s = u("author='öä'; author")
completions = Script(s).completions()
completions = Script(s).complete()
x = completions[0].description
assert type(x) is unicode
s = u("#-*- coding: iso-8859-1 -*-\nauthor='öä'; author")
s = s.encode('latin-1')
completions = Script(s).completions()
completions = Script(s).complete()
assert type(completions[0].description) is unicode
@@ -27,11 +27,11 @@ def test_unicode_attribute(Script):
""" github jedi-vim issue #94 """
s1 = u('#-*- coding: utf-8 -*-\nclass Person():\n'
' name = "e"\n\nPerson().name.')
completions1 = Script(s1).completions()
completions1 = Script(s1).complete()
assert 'strip' in [c.name for c in completions1]
s2 = u('#-*- coding: utf-8 -*-\nclass Person():\n'
' name = "é"\n\nPerson().name.')
completions2 = Script(s2).completions()
completions2 = Script(s2).complete()
assert 'strip' in [c.name for c in completions2]
@@ -44,24 +44,24 @@ def test_multibyte_script(Script):
except NameError:
pass # python 3 has no unicode method
else:
assert len(Script(s, 1, len(code)).completions())
assert len(Script(s).complete(1, len(code)))
def test_goto_definition_at_zero(Script):
"""At zero usually sometimes raises unicode issues."""
assert Script("a", 1, 1).goto_definitions() == []
s = Script("str", 1, 1).goto_definitions()
assert Script("a").infer(1, 1) == []
s = Script("str").infer(1, 1)
assert len(s) == 1
assert list(s)[0].description == 'class str'
assert Script("", 1, 0).goto_definitions() == []
assert Script("").infer(1, 0) == []
def test_complete_at_zero(Script):
s = Script("str", 1, 3).completions()
s = Script("str").complete(1, 3)
assert len(s) == 1
assert list(s)[0].name == 'str'
s = Script("", 1, 0).completions()
s = Script("").complete(1, 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).
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'

View File

@@ -1,11 +1,12 @@
def test_import_usage(Script):
s = Script("from .. import foo", line=1, column=18, path="foo.py")
assert [usage.line for usage in s.usages()] == [1]
def test_import_references(Script):
s = Script("from .. import foo", path="foo.py")
assert [usage.line for usage in s.find_references(line=1, column=18)] == [1]
def test_exclude_builtin_modules(Script):
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)'''
places = get(include=True)
assert len(places) > 2 # Includes stubs

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.
"""
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())'
@@ -26,4 +26,4 @@ def test_cache_call_signatures(Script):
def test_cache_line_split_issues(Script):
"""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
test/test_deprecation.py Normal file
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'

View File

@@ -8,4 +8,4 @@ from .. import helpers
@helpers.cwd_at("test/test_inference/absolute_import")
def test_can_complete_when_shadowing(Script):
script = Script(path="unittest.py")
assert script.completions()
assert script.complete()

View File

@@ -18,7 +18,7 @@ def test_simple_annotations(Script, environment):
annot('')""")
assert [d.name for d in Script(source).goto_definitions()] == ['str']
assert [d.name for d in Script(source).infer()] == ['str']
source = dedent("""\
@@ -26,7 +26,7 @@ def test_simple_annotations(Script, environment):
return a
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("""\
def annot(a:int):
@@ -34,7 +34,7 @@ def test_simple_annotations(Script, environment):
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', [
@@ -50,7 +50,7 @@ def test_illegal_forward_references(Script, environment, 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):
@@ -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
# want. We also execute functions. Should we only execute classes?
assert Script(source).goto_definitions()
assert Script(source).infer()

View File

@@ -61,7 +61,7 @@ def test_doc(inference_state):
def test_string_literals(Script, environment):
def typ(string):
d = Script("a = %s; a" % string).goto_definitions()[0]
d = Script("a = %s; a" % string).infer()[0]
return d.name
assert typ('""') == 'str'
@@ -83,12 +83,12 @@ def test_method_completion(Script, environment):
foo = Foo()
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):
import time
comp, = Script('import time\ntime.sleep').completions()
comp, = Script('import time\ntime.sleep').complete()
assert comp.docstring(raw=True) == time.sleep.__doc__
expected = 'sleep(secs: float) -> None\n\n' + time.sleep.__doc__
assert comp.docstring() == expected
@@ -98,12 +98,12 @@ def test_dict_values(Script, environment):
if environment.version_info.major == 2:
# It looks like typeshed for Python 2 returns Any.
pytest.skip()
assert Script('import sys\nsys.modules["alshdb;lasdhf"]').goto_definitions()
assert Script('import sys\nsys.modules["alshdb;lasdhf"]').infer()
def test_getitem_on_none(Script):
script = Script('None[1j]')
assert not script.goto_definitions()
assert not script.infer()
issue, = script._inference_state.analysis
assert issue.name == 'type-error-not-subscriptable'

View File

@@ -2,7 +2,7 @@ from jedi._compatibility import force_unicode
def test_module_attributes(Script):
def_, = Script('__name__').completions()
def_, = Script('__name__').complete()
assert def_.name == '__name__'
assert def_.line is None
assert def_.column is None
@@ -11,11 +11,11 @@ def test_module_attributes(Script):
def test_module__file__(Script, environment):
assert not Script('__file__').goto_definitions()
def_, = Script('__file__', path='example.py').goto_definitions()
assert not Script('__file__').infer()
def_, = Script('__file__', path='example.py').infer()
value = force_unicode(def_._name._value.get_safe_value())
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())
assert value.endswith('.py')

View File

@@ -32,7 +32,7 @@ def test_function_doc(Script):
defs = Script("""
def func():
'''Docstring of `func`.'''
func""").goto_definitions()
func""").infer()
assert defs[0].docstring() == 'func()\n\nDocstring of `func`.'
@@ -40,7 +40,7 @@ def test_class_doc(Script):
defs = Script("""
class TestClass():
'''Docstring of `TestClass`.'''
TestClass""").goto_definitions()
TestClass""").infer()
expected = 'Docstring of `TestClass`.'
assert defs[0].docstring(raw=True) == expected
@@ -52,7 +52,7 @@ def test_class_doc_with_init(Script):
class TestClass():
'''Docstring'''
def __init__(self, foo, bar=3): pass
TestClass""").goto_definitions()
TestClass""").infer()
assert d.docstring() == 'TestClass(foo, bar=3)\n\nDocstring'
@@ -62,7 +62,7 @@ def test_instance_doc(Script):
class TestClass():
'''Docstring of `TestClass`.'''
tc = TestClass()
tc""").goto_definitions()
tc""").infer()
assert defs[0].docstring() == 'Docstring of `TestClass`.'
@@ -71,7 +71,7 @@ def test_attribute_docstring(Script):
defs = Script("""
x = None
'''Docstring of `x`.'''
x""").goto_definitions()
x""").infer()
assert defs[0].docstring() == 'Docstring of `x`.'
@@ -82,7 +82,7 @@ def test_multiple_docstrings(Script):
'''Original docstring.'''
x = func
'''Docstring of `x`.'''
x""").goto_definitions()
x""").infer()
docs = [d.docstring() for d in defs]
assert docs == ['Original docstring.', 'Docstring of `x`.']
@@ -91,7 +91,7 @@ def test_completion(Script):
assert Script('''
class DocstringCompletion():
#? []
""" asdfas """''').completions()
""" asdfas """''').complete()
def test_docstrings_type_dotted_import(Script):
@@ -101,7 +101,7 @@ def test_docstrings_type_dotted_import(Script):
:type arg: random.Random
'''
arg."""
names = [c.name for c in Script(s).completions()]
names = [c.name for c in Script(s).complete()]
assert 'seed' in names
@@ -112,7 +112,7 @@ def test_docstrings_param_type(Script):
:param str arg: some description
'''
arg."""
names = [c.name for c in Script(s).completions()]
names = [c.name for c in Script(s).complete()]
assert 'join' in names
@@ -124,7 +124,7 @@ def test_docstrings_type_str(Script):
'''
arg."""
names = [c.name for c in Script(s).completions()]
names = [c.name for c in Script(s).complete()]
assert 'join' in names
@@ -150,14 +150,14 @@ def test_docstring_instance(Script):
c.""")
names = [c.name for c in Script(s).completions()]
names = [c.name for c in Script(s).complete()]
assert 'a' in names
assert '__init__' in names
assert 'mro' not in names # Exists only for types.
def test_docstring_keyword(Script):
completions = Script('assert').completions()
completions = Script('assert').complete()
assert 'assert' in completions[0].docstring()
@@ -167,7 +167,7 @@ def test_docstring_params_formatting(Script):
param2,
param3):
pass
func""").goto_definitions()
func""").infer()
assert defs[0].docstring() == 'func(param1, param2, param3)'
@@ -185,7 +185,7 @@ def test_numpydoc_parameters():
y : str
"""
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 'capitalize' in names
@@ -201,7 +201,7 @@ def test_numpydoc_parameters_set_of_values():
x : {'foo', 'bar', 100500}, optional
"""
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 'capitalize' in names
assert 'numerator' in names
@@ -218,7 +218,7 @@ def test_numpydoc_parameters_alternative_types():
x : int or str or list
"""
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 'capitalize' in names
assert 'numerator' in names
@@ -237,7 +237,7 @@ def test_numpydoc_invalid():
"""
x.''')
assert not jedi.Script(s).completions()
assert not jedi.Script(s).complete()
@pytest.mark.skipif(numpydoc_unavailable,
@@ -256,7 +256,7 @@ def test_numpydoc_returns():
def bazbiz():
z = foobar()
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 'capitalize' in names
assert 'numerator' in names
@@ -277,7 +277,7 @@ def test_numpydoc_returns_set_of_values():
def bazbiz():
z = foobar()
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 'capitalize' in names
assert 'numerator' in names
@@ -298,7 +298,7 @@ def test_numpydoc_returns_alternative_types():
def bazbiz():
z = foobar()
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 'capitalize' not in names
assert 'numerator' in names
@@ -320,7 +320,7 @@ def test_numpydoc_returns_list_of():
def bazbiz():
z = foobar()
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 'isupper' not in names
assert 'capitalize' not in names
@@ -342,7 +342,7 @@ def test_numpydoc_returns_obj():
z = foobar(x, y)
z.''')
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 'seed' in names
@@ -363,7 +363,7 @@ def test_numpydoc_yields():
def bazbiz():
z = foobar():
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 'capitalize' in names
assert 'numerator' in names
@@ -377,7 +377,7 @@ def test_numpy_returns():
x = numpy.asarray([])
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
@@ -389,7 +389,7 @@ def test_numpy_comp_returns():
x = numpy.array([])
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
@@ -412,7 +412,7 @@ def test_decorator(Script):
check_user''')
d, = Script(code).goto_definitions()
d, = Script(code).infer()
assert d.docstring(raw=True) == 'Nice docstring'
@@ -422,5 +422,5 @@ def test_basic_str_init_signature(Script, disable_typeshed):
class Foo(str):
pass
Foo(''')
c, = Script(code).call_signatures()
c, = Script(code).find_signatures()
assert c.name == 'Foo'

View File

@@ -10,10 +10,10 @@ import pytest
def test_completions(Script):
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':
func = 'LoadLibrary'
params = 1
@@ -21,14 +21,14 @@ def test_call_signatures_extension(Script):
func = 'dlopen'
params = 2
s = Script('import _ctypes; _ctypes.%s(' % (func,))
sigs = s.call_signatures()
sigs = s.find_signatures()
assert len(sigs) == 1
assert len(sigs[0].params) == params
def test_call_signatures_stdlib(Script):
def test_find_signatures_stdlib(Script):
s = Script('import math; math.cos(')
sigs = s.call_signatures()
sigs = s.find_signatures()
assert len(sigs) == 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).
"""
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')
assert ['foo'] == [c.name for c in s.completions()]
assert ['foo'] == [c.name for c in s.complete()]

View File

@@ -13,7 +13,6 @@ def test_fstring_multiline(Script):
'' f'''s{
str.uppe
'''
"""
)
c, = Script(code, line=2, column=9).completions()
""")
c, = Script(code).complete(line=2, column=9)
assert c.name == 'upper'

View File

@@ -7,18 +7,18 @@ from jedi.inference.gradual.conversion import convert_names
def test_sqlite3_conversion(Script):
script1 = Script('import sqlite3; sqlite3.Connection')
d, = script1.goto_definitions()
d, = script1.infer()
assert not d.module_path
assert d.full_name == 'sqlite3.Connection'
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.full_name == 'sqlite3.dbapi2.Connection'
script2 = Script(path=d.module_path, line=d.line, column=d.column)
d, = script2.goto_definitions()
script2 = Script(path=d.module_path)
d, = script2.infer(line=d.line, column=d.column)
assert not d.is_stub()
assert d.full_name == 'sqlite3.Connection'
v, = d._name.infer()
@@ -28,11 +28,11 @@ def test_sqlite3_conversion(Script):
def test_conversion_of_stub_only(Script):
project = Project(os.path.join(root_dir, 'test', 'completion', 'stub_folder'))
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()
script = Script(path=d1.module_path, line=d1.line, column=d1.column, _project=project)
d2, = script.goto_assignments()
script = Script(path=d1.module_path, _project=project)
d2, = script.goto(line=d1.line, column=d1.column)
assert d2.is_stub()
assert d2.module_path == d1.module_path
assert d2.line == d1.line
@@ -43,7 +43,7 @@ def test_conversion_of_stub_only(Script):
def test_goto_on_file(Script):
project = Project(os.path.join(root_dir, 'test', 'completion', 'stub_folder'))
script = Script('import stub_only; stub_only.Foo', _project=project)
d1, = script.goto_assignments()
d1, = script.goto()
v, = d1._name.infer()
foo, bar, obj = v.py__mro__()
assert foo.py__name__() == 'Foo'
@@ -51,6 +51,6 @@ def test_goto_on_file(Script):
assert obj.py__name__() == 'object'
# 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)
d2, = script.goto_assignments()
script = Script(path=d1.module_path, _project=project)
d2, = script.goto(line=d1.line, column=d1.column + 4)
assert d2.name == 'Bar'

View File

@@ -23,5 +23,5 @@ def ScriptInStubFolder(Script):
]
)
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

View File

@@ -64,17 +64,17 @@ def test_infer_and_goto(Script, code, full_name, has_stub, has_python, way,
if way == 'direct':
if type_ == 'goto':
defs = s.goto_assignments(follow_imports=True, **kwargs)
defs = s.goto(follow_imports=True, **kwargs)
else:
defs = s.goto_definitions(**kwargs)
defs = s.infer(**kwargs)
else:
goto_defs = s.goto_assignments(
goto_defs = s.goto(
# Prefering stubs when we want to go to python and vice versa
prefer_stubs=not (prefer_stubs or only_stubs),
follow_imports=True,
)
if type_ == 'goto':
defs = [d for goto_def in goto_defs for d in goto_def.goto_assignments(**kwargs)]
defs = [d for goto_def in goto_defs for d in goto_def.goto(**kwargs)]
else:
defs = [d for goto_def in goto_defs for d in goto_def.infer(**kwargs)]

View File

@@ -46,53 +46,53 @@ def test_get_stub_files():
def test_function(Script, environment):
code = 'import threading; threading.current_thread'
def_, = Script(code).goto_definitions()
def_, = Script(code).infer()
value = def_._name._value
assert isinstance(value, FunctionValue), value
def_, = Script(code + '()').goto_definitions()
def_, = Script(code + '()').infer()
value = def_._name._value
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_
def test_keywords_variable(Script):
code = 'import keyword; keyword.kwlist'
for seq in Script(code).goto_definitions():
for seq in Script(code).infer():
assert seq.name == 'Sequence'
# 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
def test_class(Script):
def_, = Script('import threading; threading.Thread').goto_definitions()
def_, = Script('import threading; threading.Thread').infer()
value = def_._name._value
assert isinstance(value, ClassValue), value
def test_instance(Script):
def_, = Script('import threading; threading.Thread()').goto_definitions()
def_, = Script('import threading; threading.Thread()').infer()
value = def_._name._value
assert isinstance(value, TreeInstance)
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
assert isinstance(value, MethodValue), value
def test_method(Script):
code = 'import threading; threading.Thread().getName'
def_, = Script(code).goto_definitions()
def_, = Script(code).infer()
value = def_._name._value
assert isinstance(value, BoundMethod), value
assert isinstance(value._wrapped_value, MethodValue), value
def_, = Script(code + '()').goto_definitions()
def_, = Script(code + '()').infer()
value = def_._name._value
assert isinstance(value, TreeInstance)
assert value.class_value.py__name__() == 'str'
@@ -100,13 +100,13 @@ def test_method(Script):
def test_sys_exc_info(Script):
code = 'import sys; sys.exc_info()'
none, def_ = Script(code + '[1]').goto_definitions()
none, def_ = Script(code + '[1]').infer()
# It's an optional.
assert def_.name == 'BaseException'
assert def_.type == 'instance'
assert none.name == 'NoneType'
none, def_ = Script(code + '[0]').goto_definitions()
none, def_ = Script(code + '[0]').infer()
assert def_.name == 'BaseException'
assert def_.type == 'class'
@@ -114,7 +114,7 @@ def test_sys_exc_info(Script):
def test_sys_getwindowsversion(Script, environment):
# This should only exist on Windows, but type inference should happen
# everywhere.
definitions = Script('import sys; sys.getwindowsversion().major').goto_definitions()
definitions = Script('import sys; sys.getwindowsversion().major').infer()
if environment.version_info.major == 2:
assert not definitions
else:
@@ -124,22 +124,22 @@ def test_sys_getwindowsversion(Script, environment):
def test_sys_hexversion(Script):
script = Script('import sys; sys.hexversion')
def_, = script.completions()
def_, = script.complete()
assert isinstance(def_._name, stub_value._StubName), def_._name
assert typeshed.TYPESHED_PATH in def_.module_path
def_, = script.goto_definitions()
def_, = script.infer()
assert def_.name == 'int'
def test_math(Script):
def_, = Script('import math; math.acos()').goto_definitions()
def_, = Script('import math; math.acos()').infer()
assert def_.name == 'float'
value = def_._name._value
assert value
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_.description == 'TypeVar = object()'
@@ -152,29 +152,29 @@ def test_type_var(Script):
)
def test_math_is_stub(Script, code, full_name):
s = Script(code)
cos, = s.goto_definitions()
cos, = s.infer()
wanted = os.path.join('typeshed', 'stdlib', '2and3', 'math.pyi')
assert cos.module_path.endswith(wanted)
assert cos.is_stub() is True
assert cos.goto_assignments(only_stubs=True) == [cos]
assert cos.goto(only_stubs=True) == [cos]
assert cos.full_name == full_name
cos, = s.goto_assignments()
cos, = s.goto()
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.full_name == full_name
def test_goto_stubs(Script):
s = Script('import os; os')
os_module, = s.goto_definitions()
os_module, = s.infer()
assert os_module.full_name == 'os'
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
os_module, = s.goto_assignments()
os_module, = s.goto()
def _assert_is_same(d1, d2):
@@ -199,21 +199,17 @@ def test_goto_stubs_on_itself(Script, code, type_):
"""
s = Script(code)
if type_ == 'infer':
def_, = s.goto_definitions()
def_, = s.infer()
else:
def_, = s.goto_assignments(follow_imports=True)
stub, = def_.goto_assignments(only_stubs=True)
def_, = s.goto(follow_imports=True)
stub, = def_.goto(only_stubs=True)
script_on_source = Script(
path=def_.module_path,
line=def_.line,
column=def_.column
)
script_on_source = Script(path=def_.module_path)
if type_ == 'infer':
definition, = script_on_source.goto_definitions()
definition, = script_on_source.infer(def_.line, def_.column)
else:
definition, = script_on_source.goto_assignments()
same_stub, = definition.goto_assignments(only_stubs=True)
definition, = script_on_source.goto(def_.line, def_.column)
same_stub, = definition.goto(only_stubs=True)
_assert_is_same(same_stub, stub)
_assert_is_same(definition, def_)
assert same_stub.module_path != def_.module_path
@@ -221,16 +217,14 @@ def test_goto_stubs_on_itself(Script, code, type_):
# And the reverse.
script_on_stub = Script(
path=same_stub.module_path,
line=same_stub.line,
column=same_stub.column
)
if type_ == 'infer':
same_definition, = script_on_stub.goto_definitions()
same_definition, = script_on_stub.infer(same_stub.line, same_stub.column)
same_definition2, = same_stub.infer()
else:
same_definition, = script_on_stub.goto_assignments()
same_definition2, = same_stub.goto_assignments()
same_definition, = script_on_stub.goto(same_stub.line, same_stub.column)
same_definition2, = same_stub.goto()
_assert_is_same(same_definition, definition)
_assert_is_same(same_definition, same_definition2)

View File

@@ -1,15 +1,14 @@
from textwrap import dedent
from jedi import names
from jedi.inference import helpers
def test_call_of_leaf_in_brackets(environment):
def test_call_of_leaf_in_brackets(Script):
s = dedent("""
x = 1
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
call = helpers.call_of_leaf(name)

View File

@@ -17,9 +17,9 @@ def test_implicit_namespace_package(Script):
return Script(sys_path=sys_path, *args, **kwargs)
# goto definition
assert script_with_path('from pkg import ns1_file').goto_definitions()
assert script_with_path('from pkg import ns2_file').goto_definitions()
assert not script_with_path('from pkg import ns3_file').goto_definitions()
assert script_with_path('from pkg import ns1_file').infer()
assert script_with_path('from pkg import ns2_file').infer()
assert not script_with_path('from pkg import ns3_file').infer()
# goto assignment
tests = {
@@ -27,12 +27,12 @@ def test_implicit_namespace_package(Script):
'from pkg.ns1_file import foo': 'ns1_file!',
}
for source, solution in tests.items():
ass = script_with_path(source).goto_assignments()
ass = script_with_path(source).goto()
assert len(ass) == 1
assert ass[0].description == "foo = '%s'" % solution
# completion
completions = script_with_path('from pkg import ').completions()
completions = script_with_path('from pkg import ').complete()
names = [c.name for c in completions]
compare = ['ns1_file', 'ns2_file']
# 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!'
}
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':
completion = c
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)
result = script.goto_definitions()
result = script.infer()
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.module_path is None
@@ -72,7 +72,7 @@ def test_implicit_namespace_package_import_autocomplete(Script):
sys_path = [dirname(__file__)]
script = Script(sys_path=sys_path, source=CODE)
compl = script.completions()
compl = script.complete()
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']]
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'])
@@ -91,7 +91,7 @@ def test_namespace_package_in_multiple_directories_goto_definition(Script):
sys_path = [join(dirname(__file__), d)
for d in ['implicit_namespace_package/ns1', 'implicit_namespace_package/ns2']]
script = Script(sys_path=sys_path, source=CODE)
result = script.goto_definitions()
result = script.infer()
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']]
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'])

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):
sys_path = environment.get_sys_path() + [pkg_zip_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(
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,
file, package, path, skip_python2):
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()
assert value.py__file__() == os.path.join(pkg_zip_path, 'pkg', file)
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')
sys_path = environment.get_sys_path() + [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(
sys_path=sys_path,
@@ -118,12 +118,12 @@ def test_import_not_in_sys_path(Script):
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'
a = Script(path='module.py', line=6).goto_definitions()
a = Script(path='module.py').infer(line=6)
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'
@@ -145,19 +145,19 @@ def test_flask_ext(Script, code, name):
"""flask.ext.foo is really imported from flaskext.foo or flask_foo.
"""
path = os.path.join(os.path.dirname(__file__), 'flask-site-packages')
completions = Script(code, sys_path=[path]).completions()
completions = Script(code, sys_path=[path]).complete()
assert name in [c.name for c in completions]
@cwd_at('test/test_inference/')
def test_not_importable_file(Script):
src = 'import not_importable_file as x; x.'
assert not Script(src, path='example.py').completions()
assert not Script(src, path='example.py').complete()
def test_import_unique(Script):
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]
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)
bar_path.join('module.py').write('bar = 123', ensure=True)
foo_completions = Script('import module; module.',
sys_path=[foo_path.strpath]).completions()
sys_path=[foo_path.strpath]).complete()
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 '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):
import abc
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 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):
assert Script("import sys_blabla", 1, 8).goto_definitions() == []
assert len(Script("import sys", 1, 8).goto_definitions()) == 1
assert Script("import sys_blabla").infer(1, 8) == []
assert len(Script("import sys").infer(1, 8)) == 1
@cwd_at('jedi')
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
assert 10 < len(Script("from .", path='whatever.py').completions()) < 30
assert 10 < len(Script("from .", path='whatever.py').complete()) < 30
# 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
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
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
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'}
assert {c.name for c in Script("import").completions()} == wanted
assert len(Script("import import", path='').completions()) > 0
assert {c.name for c in Script("import").complete()} == wanted
assert len(Script("import import", path='').complete()) > 0
# 111
assert Script("from datetime import").completions()[0].name == 'import'
assert Script("from datetime import ").completions()
assert Script("from datetime import").complete()[0].name == 'import'
assert Script("from datetime import ").complete()
def test_imports_on_global_namespace_without_path(Script):
"""If the path is None, there shouldn't be any import problem"""
completions = Script("import operator").completions()
completions = Script("import operator").complete()
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']
# 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']
completions = Script("import keyword").completions()
completions = Script("import keyword").complete()
assert [c.name for c in completions] == ['keyword']
def test_named_import(Script):
"""named import - jedi-vim issue #8"""
s = "import time as dt"
assert len(Script(s, 1, 15, '/').goto_definitions()) == 1
assert len(Script(s, 1, 10, '/').goto_definitions()) == 1
assert len(Script(s, path='/').infer(1, 15)) == 1
assert len(Script(s, path='/').infer(1, 10)) == 1
@pytest.mark.skipif('True', reason='The nested import stuff is still very messy.')
def test_goto_following_on_imports(Script):
s = "import multiprocessing.dummy; multiprocessing.dummy"
g = Script(s).goto_assignments()
g = Script(s).goto()
assert len(g) == 1
assert (g[0].line, g[0].column) != (0, 0)
def test_goto_assignments(Script):
sys, = Script("import sys", 1, 10).goto_assignments(follow_imports=True)
def test_goto(Script):
sys, = Script("import sys", 1, 10).goto(follow_imports=True)
assert sys.type == 'module'
def test_os_after_from(Script):
def check(source, result, column=None):
completions = Script(source, column=column).completions()
completions = Script(source).complete(column=column)
assert [c.name for c in completions] == result
check('\nfrom os. ', ['path'])
@@ -270,7 +270,7 @@ def test_os_after_from(Script):
def test_os_issues(Script):
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
s = 'import os, s'
@@ -291,7 +291,7 @@ def test_path_issues(Script):
See pull request #684 for details.
"""
source = '''from datetime import '''
assert Script(source).completions()
assert Script(source).complete()
def test_compiled_import_none(monkeypatch, Script):
@@ -300,7 +300,7 @@ def test_compiled_import_none(monkeypatch, Script):
"""
script = Script('import sys')
monkeypatch.setattr(compiled, 'load_module', lambda *args, **kwargs: None)
def_, = script.goto_definitions()
def_, = script.infer()
assert def_.type == 'module'
value, = def_._name.infer()
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),
_project=project,
)
name, import_ = script.completions()
name, import_ = script.complete()
assert import_.name == 'import'
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'),
_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(
"from " + '.' * 100,
path=os.path.join(dir, 'api/whatever/test_this.py'),
_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/')
def test_relative_imports_without_path(Script):
project = Project('.', sys_path=[], smart_sys_path=False)
script = Script("from . ", _project=project)
assert [c.name for c in script.completions()] == ['api_test1', 'import']
assert [c.name for c in script.complete()] == ['api_test1', 'import']
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)
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):
script = Script("from " + '.' * 100)
import_, = script.completions()
import_, = script.complete()
assert import_.name == 'import'
script = Script("from " + '.' * 100 + 'abc import ABCMeta')
assert not script.goto_definitions()
assert not script.completions()
assert not script.infer()
assert not script.complete()
@pytest.mark.parametrize(
@@ -456,13 +456,13 @@ def test_import_needed_modules_by_jedi(Script, environment, tmpdir, name):
path=tmpdir.join('something.py').strpath,
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.typing_module.py__file__() != module_path
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 'abc' not in names
@@ -475,6 +475,6 @@ def test_relative_import_star(Script):
from . import *
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"))

View File

@@ -3,7 +3,7 @@ from jedi.inference.value import TreeInstance
def _infer_literal(Script, code, is_fstring=False):
def_, = Script(code).goto_definitions()
def_, = Script(code).infer()
if is_fstring:
assert def_.name == 'str'
assert isinstance(def_._name._value, TreeInstance)

View File

@@ -14,7 +14,7 @@ def interpreter(code, namespace, *args, **kwargs):
def test_on_code():
from functools import wraps
i = interpreter("wraps.__code__", {'wraps': wraps})
assert i.goto_definitions()
assert i.infer()
@pytest.mark.skipif('sys.version_info < (3,5)')
@@ -39,4 +39,4 @@ def test_generics():
self.stack.push(1)
s = StackWrapper()
print(interpreter('s.stack.pop().', locals()).completions())
print(interpreter('s.stack.pop().', locals()).complete())

View File

@@ -15,9 +15,9 @@ def script_with_path(Script, *args, **kwargs):
def test_goto_definition(Script):
assert script_with_path(Script, 'from pkg import ns1_file').goto_definitions()
assert script_with_path(Script, 'from pkg import ns2_file').goto_definitions()
assert not script_with_path(Script, 'from pkg import ns3_file').goto_definitions()
assert script_with_path(Script, 'from pkg import ns1_file').infer()
assert script_with_path(Script, 'from pkg import ns2_file').infer()
assert not script_with_path(Script, 'from pkg import ns3_file').infer()
@pytest.mark.parametrize(
@@ -31,14 +31,14 @@ def test_goto_definition(Script):
]
)
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 ass[0].description == "foo = '%s'" % solution
def test_simple_completions(Script):
# 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
compare = ['foo', 'ns1_file', 'ns1_folder', 'ns2_folder', 'ns2_file',
'pkg_resources', 'pkgutil', '__name__', '__path__',
@@ -58,7 +58,7 @@ def test_simple_completions(Script):
]
)
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':
completion = c
solution = "foo = '%s'" % solution
@@ -70,9 +70,9 @@ def test_nested_namespace_package(Script):
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
@@ -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.
py.path.local(directory).copy(tmpdir)
file_path = join(tmpdir.strpath, "rel1.py")
script = Script(path=file_path, line=1)
d, = script.goto_definitions()
script = Script(path=file_path)
d, = script.infer(line=1)
assert d.name == 'int'
d, = script.goto_assignments()
d, = script.goto(line=1)
assert d.name == 'name'
assert d.module_name == 'rel2'

View File

@@ -70,4 +70,4 @@ def test_pyc(pyc_project_path, environment):
"from dummy_package import dummy; dummy.",
path=path,
environment=environment)
assert len(s.completions()) >= 2
assert len(s.complete()) >= 2

View File

@@ -2,7 +2,7 @@ from textwrap import dedent
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

View File

@@ -32,7 +32,7 @@ def test_compiled_signature(Script, environment, code, sig, names, op, version):
if not op(environment.version_info, version):
return # The test right next to it should take over.
d, = Script(code).goto_definitions()
d, = Script(code).infer()
value, = d._name.infer()
compiled, = _stub_to_python_value_set(value)
signature, = compiled.get_signatures()
@@ -90,9 +90,9 @@ def test_tree_signature(Script, environment, code, expected):
pytest.skip()
if expected is None:
assert not Script(code).call_signatures()
assert not Script(code).find_signatures()
else:
sig, = Script(code).call_signatures()
sig, = Script(code).find_signatures()
assert expected == sig.to_string()
@@ -182,7 +182,7 @@ def test_nested_signatures(Script, environment, combination, expected, skip_pre_
super().foo(**kwargs)
''')
code += 'z = ' + combination + '\nz('
sig, = Script(code).call_signatures()
sig, = Script(code).find_signatures()
computed = sig.to_string()
if not re.match(r'\w+\(', expected):
expected = '<lambda>(' + expected + ')'
@@ -191,7 +191,7 @@ def test_nested_signatures(Script, environment, combination, expected, skip_pre_
def test_pow_signature(Script):
# See github #1357
sigs = Script('pow(').call_signatures()
sigs = Script('pow(').find_signatures()
strings = {sig.to_string() for sig in sigs}
assert strings == {'pow(x: float, y: float, z: float, /) -> float',
'pow(x: float, y: float, /) -> float',
@@ -230,7 +230,7 @@ def test_pow_signature(Script):
]
)
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}
@@ -263,7 +263,7 @@ def test_dataclass_signature(Script, skip_pre_python37, start, start_params):
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']
quantity, = sig.params[-1].infer()
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): ...
full_redirect(simple)('''.format(stmt=stmt))
sig, = Script(code).call_signatures()
sig, = Script(code).find_signatures()
assert sig.to_string() == expected
def test_overload(Script):
dir_ = get_example_dir('typing_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 x2.to_string() == 'with_overload(x: str, y: list) -> float'

View File

@@ -17,7 +17,7 @@ def test_namedtuple_str(letter, expected, Script):
Person = collections.namedtuple('Person', 'name smart')
dave = Person('Dave', False)
dave.%s""") % letter
result = Script(source).completions()
result = Script(source).complete()
completions = set(r.name for r in result)
assert completions == set(expected)
@@ -28,7 +28,7 @@ def test_namedtuple_list(Script):
Cat = collections.namedtuple('Person', ['legs', u'length', 'large'])
garfield = Cat(4, '85cm', True)
garfield.l""")
result = Script(source).completions()
result = Script(source).complete()
completions = set(r.name for r in result)
assert completions == {'legs', 'length', 'large'}
@@ -42,7 +42,7 @@ def test_namedtuple_content(Script):
""")
def d(source):
x, = Script(source).goto_definitions()
x, = Script(source).infer()
return x.name
assert d(source + 'unnamed.bar') == 'int'
@@ -62,10 +62,10 @@ def test_nested_namedtuples(Script):
train_x = Datasets(train=Dataset('data_value'))
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("""
from collections import namedtuple
@@ -74,7 +74,7 @@ def test_namedtuple_goto_definitions(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.module_path is None
@@ -86,7 +86,7 @@ def test_re_sub(Script, environment):
version differences.
"""
def run(code):
defs = Script(code).goto_definitions()
defs = Script(code).infer()
return {d.name for d in defs}
names = run("import re; re.sub('a', 'a', 'f')")

View File

@@ -6,7 +6,7 @@ from parso import parse
def test_form_feed_characters(Script):
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):
@@ -29,7 +29,7 @@ def test_if(Script):
# Two parsers needed, one for pass and one for the function.
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):
@@ -47,7 +47,7 @@ def test_class_and_if(Script):
# COMMENT
a_func()""")
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):
@@ -70,8 +70,8 @@ def test_add_to_end(Script):
" self."
def complete(code, line=None, column=None):
script = Script(code, line, column, 'example.py')
assert script.completions()
script = Script(code, 'example.py')
assert script.complete(line, column)
complete(a, 7, 12)
complete(a + b)
@@ -82,7 +82,7 @@ def test_add_to_end(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'
@@ -90,6 +90,6 @@ def test_ellipsis_without_getitem(Script, environment):
if environment.version_info.major == 2:
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'

View File

@@ -6,7 +6,7 @@ def test_error_correction_with(Script):
with open() as f:
try:
f."""
comps = Script(source).completions()
comps = Script(source).complete()
assert len(comps) > 30
# `open` completions have a closed attribute.
assert [1 for c in comps if c.name == 'closed']
@@ -23,14 +23,14 @@ def test_string_literals(Script):
script = Script(dedent(source))
assert script._get_module_context().tree_node.end_pos == (6, 0)
assert script.completions()
assert script.complete()
def test_incomplete_function(Script):
source = '''return ImportErr'''
script = Script(dedent(source), 1, 3)
assert script.completions()
script = Script(dedent(source))
assert script.complete(1, 3)
def test_decorator_string_issue(Script):
@@ -46,5 +46,5 @@ def test_decorator_string_issue(Script):
bla.''')
s = Script(source)
assert s.completions()
assert s.complete()
assert s._get_module_context().tree_node.get_code() == source

View File

@@ -62,13 +62,13 @@ def test_hex_values_in_docstring():
@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, y, z) -> str:\n return', 'my_function(x, y, z) -> str'),
('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]
if node.type == 'simple_stmt':
node = node.children[0]
assert parser_utils.get_call_signature(node) == call_signature
assert parser_utils.get_signature(node) == signature

View File

@@ -12,14 +12,14 @@ def auto_import_json(monkeypatch):
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)
value, = loads._name.infer()
assert isinstance(value.parent_context._value, StubModuleValue)
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)
@@ -31,7 +31,7 @@ def test_additional_dynamic_modules(monkeypatch, Script):
'additional_dynamic_modules',
['/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):
@@ -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.
script = Script(code + code + 'Foo')
assert not script.goto_definitions()
assert 'Foo' in [c.name for c in script.completions()]
assert not script.infer()
assert 'Foo' in [c.name for c in script.complete()]

View File

@@ -33,14 +33,14 @@ def _check_speed(time_per_run, number=4, run_warm=True):
@_check_speed(0.5)
def test_os_path_join(Script):
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)
def test_scipy_speed(Script):
s = 'import scipy.weave; scipy.weave.inline('
script = Script(s, 1, len(s), '')
script.call_signatures()
script = Script(s, path='')
script.find_signatures(1, len(s))
@_check_speed(0.8)
@@ -52,7 +52,7 @@ def test_precedence_slowdown(Script):
"""
with open('speed/precedence.py') as f:
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)
@@ -70,4 +70,4 @@ def test_no_repr_computation(Script):
def __repr__(self):
time.sleep(0.2)
test = SlowRepr()
jedi.Interpreter('test.som', [locals()]).completions()
jedi.Interpreter('test.som', [locals()]).complete()

View File

@@ -19,7 +19,7 @@ class TestSetupReadline(unittest.TestCase):
self.namespace = self.NameSpace()
utils.setup_readline(self.namespace)
def completions(self, text):
def complete(self, text):
completer = readline.get_completer()
i = 0
completions = []
@@ -32,18 +32,18 @@ class TestSetupReadline(unittest.TestCase):
return completions
def test_simple(self):
assert self.completions('list') == ['list']
assert self.completions('importerror') == ['ImportError']
assert self.complete('list') == ['list']
assert self.complete('importerror') == ['ImportError']
s = "print(BaseE"
assert self.completions(s) == [s + 'xception']
assert self.complete(s) == [s + 'xception']
def test_nested(self):
assert self.completions('list.Insert') == ['list.insert']
assert self.completions('list().Insert') == ['list().insert']
assert self.complete('list.Insert') == ['list.insert']
assert self.complete('list().Insert') == ['list().insert']
def test_magic_methods(self):
assert self.completions('list.__getitem__') == ['list.__getitem__']
assert self.completions('list().__getitem__') == ['list().__getitem__']
assert self.complete('list.__getitem__') == ['list.__getitem__']
assert self.complete('list().__getitem__') == ['list().__getitem__']
def test_modules(self):
import sys
@@ -52,31 +52,31 @@ class TestSetupReadline(unittest.TestCase):
self.namespace.os = os
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'
assert self.completions(string) == [string]
assert self.complete(string) == [string]
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:
del self.namespace.sys
del self.namespace.os
def test_calls(self):
s = 'str(bytes'
assert self.completions(s) == [s, 'str(BytesWarning']
assert self.complete(s) == [s, 'str(BytesWarning']
def test_import(self):
s = 'from os.path import a'
assert set(self.completions(s)) == {s + 'ltsep', s + 'bspath'}
assert self.completions('import keyword') == ['import keyword']
assert set(self.complete(s)) == {s + 'ltsep', s + 'bspath'}
assert self.complete('import keyword') == ['import keyword']
import os
s = 'from os import '
goal = {s + el for el in dir(os)}
# There are minor differences, e.g. the dir doesn't include deleted
# 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 = {
x for x in difference
if all(not x.startswith('from os import ' + s)
@@ -89,11 +89,11 @@ class TestSetupReadline(unittest.TestCase):
@cwd_at('test')
def test_local_import(self):
s = 'import test_utils'
assert self.completions(s) == [s]
assert self.complete(s) == [s]
def test_preexisting_values(self):
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
def test_colorama(self):
@@ -110,8 +110,8 @@ class TestSetupReadline(unittest.TestCase):
pass
else:
self.namespace.colorama = colorama
assert self.completions('colorama')
assert self.completions('colorama.Fore.BLACK') == ['colorama.Fore.BLACK']
assert self.complete('colorama')
assert self.complete('colorama.Fore.BLACK') == ['colorama.Fore.BLACK']
del self.namespace.colorama