mirror of
https://github.com/davidhalter/jedi.git
synced 2026-01-10 05:52:22 +08:00
Merge branch 'api', fixes #1166
This commit is contained in:
@@ -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``.
|
||||
|
||||
13
README.rst
13
README.rst
@@ -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
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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.
|
||||
"""
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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()
|
||||
@@ -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')
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 = [
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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())
|
||||
|
||||
8
sith.py
8
sith.py
@@ -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)
|
||||
|
||||
@@ -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']
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# goto_assignments command tests are different in syntax
|
||||
# goto command tests are different in syntax
|
||||
|
||||
definition = 3
|
||||
#! 0 ['a = definition']
|
||||
|
||||
2
test/completion/thirdparty/jedi_.py
vendored
2
test/completion/thirdparty/jedi_.py
vendored
@@ -1,7 +1,7 @@
|
||||
|
||||
from jedi import functions, inference, parsing
|
||||
|
||||
el = functions.completions()[0]
|
||||
el = functions.complete()[0]
|
||||
#? ['description']
|
||||
el.description
|
||||
|
||||
|
||||
@@ -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.
|
||||
"""
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"""
|
||||
Test coverage for renaming is mostly being done by testing
|
||||
`Script.usages`.
|
||||
`Script.find_references`.
|
||||
"""
|
||||
|
||||
# --- simple
|
||||
|
||||
72
test/run.py
72
test/run.py
@@ -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).
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
"""
|
||||
An import tree, for testing usages.
|
||||
An import tree, for testing references.
|
||||
"""
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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']
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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'
|
||||
|
||||
|
||||
@@ -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']
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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 == '('
|
||||
|
||||
@@ -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])'
|
||||
|
||||
@@ -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'
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
27
test/test_deprecation.py
Normal 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'
|
||||
@@ -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()
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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'
|
||||
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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()]
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)]
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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'])
|
||||
|
||||
@@ -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"))
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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')")
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()]
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user