You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
	
	
		
			799 lines
		
	
	
		
			32 KiB
		
	
	
	
		
			Python
		
	
			
		
		
	
	
			799 lines
		
	
	
		
			32 KiB
		
	
	
	
		
			Python
		
	
| """
 | |
| The API basically only provides one class. You can create a :class:`Script` and
 | |
| use its methods.
 | |
| 
 | |
| Additionally you can add a debug function with :func:`set_debug_function`.
 | |
| Alternatively, if you don't need a custom function and are happy with printing
 | |
| debug messages to stdout, simply call :func:`set_debug_function` without
 | |
| arguments.
 | |
| """
 | |
| import sys
 | |
| from pathlib import Path
 | |
| 
 | |
| import parso
 | |
| from parso.python import tree
 | |
| 
 | |
| from jedi.parser_utils import get_executable_nodes
 | |
| from jedi import debug
 | |
| from jedi import settings
 | |
| from jedi import cache
 | |
| 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, search_in_module
 | |
| from jedi.api.keywords import KeywordName
 | |
| from jedi.api.environment import InterpreterEnvironment
 | |
| from jedi.api.project import get_default_project, Project
 | |
| from jedi.api.errors import parso_to_jedi_errors
 | |
| from jedi.api import refactoring
 | |
| from jedi.api.refactoring.extract import extract_function, extract_variable
 | |
| from jedi.inference import InferenceState
 | |
| from jedi.inference import imports
 | |
| from jedi.inference.references import find_references
 | |
| from jedi.inference.arguments import try_iter_content
 | |
| from jedi.inference.helpers import infer_call_of_leaf
 | |
| from jedi.inference.sys_path import transform_path_to_dotted
 | |
| from jedi.inference.syntax_tree import tree_name_to_values
 | |
| from jedi.inference.value import ModuleValue
 | |
| from jedi.inference.base_value import ValueSet
 | |
| from jedi.inference.value.iterable import unpack_tuple_to_dict
 | |
| from jedi.inference.gradual.conversion import convert_names, convert_values
 | |
| from jedi.inference.gradual.utils import load_proper_stub_module
 | |
| from jedi.inference.utils import to_list
 | |
| 
 | |
| # Jedi uses lots and lots of recursion. By setting this a little bit higher, we
 | |
| # can remove some "maximum recursion depth" errors.
 | |
| sys.setrecursionlimit(3000)
 | |
| 
 | |
| 
 | |
| class Script:
 | |
|     """
 | |
|     A Script is the base for completions, goto or whatever you want to do with
 | |
|     Jedi. The counter part of this class is :class:`Interpreter`, which works
 | |
|     with actual dictionaries and can work with a REPL. This class
 | |
|     should be used when a user edits code in an editor.
 | |
| 
 | |
|     You can either use the ``code`` parameter or ``path`` to read a file.
 | |
|     Usually you're going to want to use both of them (in an editor).
 | |
| 
 | |
|     The Script's ``sys.path`` is very customizable:
 | |
| 
 | |
|     - If `project` is provided with a ``sys_path``, that is going to be used.
 | |
|     - If `environment` is provided, its ``sys.path`` will be used
 | |
|       (see :func:`Environment.get_sys_path <jedi.api.environment.Environment.get_sys_path>`);
 | |
|     - Otherwise ``sys.path`` will match that of the default environment of
 | |
|       Jedi, which typically matches the sys path that was used at the time
 | |
|       when Jedi was imported.
 | |
| 
 | |
|     Most methods have a ``line`` and a ``column`` parameter. Lines in Jedi are
 | |
|     always 1-based and columns are always zero based. To avoid repetition they
 | |
|     are not always documented. You can omit both line and column. Jedi will
 | |
|     then just do whatever action you are calling at the end of the file. If you
 | |
|     provide only the line, just will complete at the end of that line.
 | |
| 
 | |
|     .. warning:: By default :attr:`jedi.settings.fast_parser` is enabled, which means
 | |
|         that parso reuses modules (i.e. they are not immutable). With this setting
 | |
|         Jedi is **not thread safe** and it is also not safe to use multiple
 | |
|         :class:`.Script` instances and its definitions at the same time.
 | |
| 
 | |
|         If you are a normal plugin developer this should not be an issue. It is
 | |
|         an issue for people that do more complex stuff with Jedi.
 | |
| 
 | |
|         This is purely a performance optimization and works pretty well for all
 | |
|         typical usages, however consider to turn the setting off if it causes
 | |
|         you problems. See also
 | |
|         `this discussion <https://github.com/davidhalter/jedi/issues/1240>`_.
 | |
| 
 | |
|     :param code: The source code of the current file, separated by newlines.
 | |
|     :type code: str
 | |
|     :param path: The path of the file in the file system, or ``''`` if
 | |
|         it hasn't been saved yet.
 | |
|     :type path: str or pathlib.Path or None
 | |
|     :param Environment environment: Provide a predefined :ref:`Environment <environments>`
 | |
|         to work with a specific Python version or virtualenv.
 | |
|     :param Project project: Provide a :class:`.Project` to make sure finding
 | |
|         references works well, because the right folder is searched. There are
 | |
|         also ways to modify the sys path and other things.
 | |
|     """
 | |
|     def __init__(self, code=None, *, path=None, environment=None, project=None):
 | |
|         self._orig_path = path
 | |
|         if isinstance(path, str):
 | |
|             path = Path(path)
 | |
| 
 | |
|         self.path = path.absolute() if path else None
 | |
| 
 | |
|         if code is None:
 | |
|             if path is None:
 | |
|                 raise ValueError("Must provide at least one of code or path")
 | |
| 
 | |
|             # TODO add a better warning than the traceback!
 | |
|             with open(path, 'rb') as f:
 | |
|                 code = f.read()
 | |
| 
 | |
|         if project is None:
 | |
|             # Load the Python grammar of the current interpreter.
 | |
|             project = get_default_project(None if self.path is None else self.path.parent)
 | |
| 
 | |
|         self._inference_state = InferenceState(
 | |
|             project, environment=environment, script_path=self.path
 | |
|         )
 | |
|         debug.speed('init')
 | |
|         self._module_node, code = self._inference_state.parse_and_get_code(
 | |
|             code=code,
 | |
|             path=self.path,
 | |
|             use_latest_grammar=path and path.suffix == '.pyi',
 | |
|             cache=False,  # No disk cache, because the current script often changes.
 | |
|             diff_cache=settings.fast_parser,
 | |
|             cache_path=settings.cache_directory,
 | |
|         )
 | |
|         debug.speed('parsed')
 | |
|         self._code_lines = parso.split_lines(code, keepends=True)
 | |
|         self._code = code
 | |
| 
 | |
|         cache.clear_time_caches()
 | |
|         debug.reset_time()
 | |
| 
 | |
|     # Cache the module, this is mostly useful for testing, since this shouldn't
 | |
|     # be called multiple times.
 | |
|     @cache.memoize_method
 | |
|     def _get_module(self):
 | |
|         names = None
 | |
|         is_package = False
 | |
|         if self.path is not None:
 | |
|             import_names, is_p = transform_path_to_dotted(
 | |
|                 self._inference_state.get_sys_path(add_parent_paths=False),
 | |
|                 self.path
 | |
|             )
 | |
|             if import_names is not None:
 | |
|                 names = import_names
 | |
|                 is_package = is_p
 | |
| 
 | |
|         if self.path is None:
 | |
|             file_io = None
 | |
|         else:
 | |
|             file_io = KnownContentFileIO(self.path, self._code)
 | |
|         if self.path is not None and self.path.suffix == '.pyi':
 | |
|             # We are in a stub file. Try to load the stub properly.
 | |
|             stub_module = load_proper_stub_module(
 | |
|                 self._inference_state,
 | |
|                 self._inference_state.latest_grammar,
 | |
|                 file_io,
 | |
|                 names,
 | |
|                 self._module_node
 | |
|             )
 | |
|             if stub_module is not None:
 | |
|                 return stub_module
 | |
| 
 | |
|         if names is None:
 | |
|             names = ('__main__',)
 | |
| 
 | |
|         module = ModuleValue(
 | |
|             self._inference_state, self._module_node,
 | |
|             file_io=file_io,
 | |
|             string_names=names,
 | |
|             code_lines=self._code_lines,
 | |
|             is_package=is_package,
 | |
|         )
 | |
|         if names[0] not in ('builtins', 'typing'):
 | |
|             # These modules are essential for Jedi, so don't overwrite them.
 | |
|             self._inference_state.module_cache.add(names, ValueSet([module]))
 | |
|         return module
 | |
| 
 | |
|     def _get_module_context(self):
 | |
|         return self._get_module().as_context()
 | |
| 
 | |
|     def __repr__(self):
 | |
|         return '<%s: %s %r>' % (
 | |
|             self.__class__.__name__,
 | |
|             repr(self._orig_path),
 | |
|             self._inference_state.environment,
 | |
|         )
 | |
| 
 | |
|     @validate_line_column
 | |
|     def complete(self, line=None, column=None, *, fuzzy=False):
 | |
|         """
 | |
|         Completes objects under the cursor.
 | |
| 
 | |
|         Those objects contain information about the completions, more than just
 | |
|         names.
 | |
| 
 | |
|         :param fuzzy: Default False. Will return fuzzy completions, which means
 | |
|             that e.g. ``ooa`` will match ``foobar``.
 | |
|         :return: Completion objects, sorted by name. Normal names appear
 | |
|             before "private" names that start with ``_`` and those appear
 | |
|             before magic methods and name mangled names that start with ``__``.
 | |
|         :rtype: list of :class:`.Completion`
 | |
|         """
 | |
|         self._inference_state.reset_recursion_limitations()
 | |
|         with debug.increase_indent_cm('complete'):
 | |
|             completion = Completion(
 | |
|                 self._inference_state, self._get_module_context(), self._code_lines,
 | |
|                 (line, column), self.get_signatures, fuzzy=fuzzy,
 | |
|             )
 | |
|             return completion.complete()
 | |
| 
 | |
|     @validate_line_column
 | |
|     def infer(self, line=None, column=None, *, only_stubs=False, prefer_stubs=False):
 | |
|         """
 | |
|         Return the definitions of under the cursor. It is basically a wrapper
 | |
|         around Jedi's type inference.
 | |
| 
 | |
|         This method follows complicated paths and returns the end, not the
 | |
|         first 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 depending on an option you can have two different versions of a
 | |
|         function.
 | |
| 
 | |
|         :param only_stubs: Only return stubs for this method.
 | |
|         :param prefer_stubs: Prefer stubs to Python objects for this method.
 | |
|         :rtype: list of :class:`.Name`
 | |
|         """
 | |
|         self._inference_state.reset_recursion_limitations()
 | |
|         pos = line, column
 | |
|         leaf = self._module_node.get_name_of_position(pos)
 | |
|         if leaf is None:
 | |
|             leaf = self._module_node.get_leaf_for_position(pos)
 | |
|             if leaf is None or leaf.type == 'string':
 | |
|                 return []
 | |
|             if leaf.end_pos == (line, column) and leaf.type == 'operator':
 | |
|                 next_ = leaf.get_next_leaf()
 | |
|                 if next_.start_pos == leaf.end_pos \
 | |
|                         and next_.type in ('number', 'string', 'keyword'):
 | |
|                     leaf = next_
 | |
| 
 | |
|         context = self._get_module_context().create_context(leaf)
 | |
| 
 | |
|         values = helpers.infer(self._inference_state, context, leaf)
 | |
|         values = convert_values(
 | |
|             values,
 | |
|             only_stubs=only_stubs,
 | |
|             prefer_stubs=prefer_stubs,
 | |
|         )
 | |
| 
 | |
|         defs = [classes.Name(self._inference_state, c.name) for c in values]
 | |
|         # The additional set here allows the definitions to become unique in an
 | |
|         # API sense. In the internals we want to separate more things than in
 | |
|         # the API.
 | |
|         return helpers.sorted_definitions(set(defs))
 | |
| 
 | |
|     @validate_line_column
 | |
|     def goto(self, line=None, column=None, *, follow_imports=False, follow_builtin_imports=False,
 | |
|              only_stubs=False, prefer_stubs=False):
 | |
|         """
 | |
|         Goes to the name that defined the object under the cursor. Optionally
 | |
|         you can follow imports.
 | |
|         Multiple objects may be returned, depending on an if you can have two
 | |
|         different versions of a function.
 | |
| 
 | |
|         :param follow_imports: The method will follow imports.
 | |
|         :param follow_builtin_imports: If ``follow_imports`` is True will try
 | |
|             to look up names in builtins (i.e. compiled or extension modules).
 | |
|         :param only_stubs: Only return stubs for this method.
 | |
|         :param prefer_stubs: Prefer stubs to Python objects for this method.
 | |
|         :rtype: list of :class:`.Name`
 | |
|         """
 | |
|         self._inference_state.reset_recursion_limitations()
 | |
|         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.infer(line, column, only_stubs=only_stubs, prefer_stubs=prefer_stubs)
 | |
|         name = self._get_module_context().create_name(tree_name)
 | |
| 
 | |
|         # Make it possible to goto the super class function/attribute
 | |
|         # definitions, when they are overwritten.
 | |
|         names = []
 | |
|         if name.tree_name.is_definition() and name.parent_context.is_class():
 | |
|             class_node = name.parent_context.tree_node
 | |
|             class_value = self._get_module_context().create_value(class_node)
 | |
|             mro = class_value.py__mro__()
 | |
|             next(mro)  # Ignore the first entry, because it's the class itself.
 | |
|             for cls in mro:
 | |
|                 names = cls.goto(tree_name.value)
 | |
|                 if names:
 | |
|                     break
 | |
| 
 | |
|         if not names:
 | |
|             names = list(name.goto())
 | |
| 
 | |
|         if follow_imports:
 | |
|             names = helpers.filter_follow_imports(names, follow_builtin_imports)
 | |
|         names = convert_names(
 | |
|             names,
 | |
|             only_stubs=only_stubs,
 | |
|             prefer_stubs=prefer_stubs,
 | |
|         )
 | |
| 
 | |
|         defs = [classes.Name(self._inference_state, d) for d in set(names)]
 | |
|         # Avoid duplicates
 | |
|         return list(set(helpers.sorted_definitions(defs)))
 | |
| 
 | |
|     def search(self, string, *, all_scopes=False):
 | |
|         """
 | |
|         Searches a name in the current file. For a description of how the
 | |
|         search string should look like, please have a look at
 | |
|         :meth:`.Project.search`.
 | |
| 
 | |
|         :param bool all_scopes: Default False; searches not only for
 | |
|             definitions on the top level of a module level, but also in
 | |
|             functions and classes.
 | |
|         :yields: :class:`.Name`
 | |
|         """
 | |
|         return self._search_func(string, all_scopes=all_scopes)
 | |
| 
 | |
|     @to_list
 | |
|     def _search_func(self, string, all_scopes=False, complete=False, fuzzy=False):
 | |
|         names = self._names(all_scopes=all_scopes)
 | |
|         wanted_type, wanted_names = helpers.split_search_string(string)
 | |
|         return search_in_module(
 | |
|             self._inference_state,
 | |
|             self._get_module_context(),
 | |
|             names=names,
 | |
|             wanted_type=wanted_type,
 | |
|             wanted_names=wanted_names,
 | |
|             complete=complete,
 | |
|             fuzzy=fuzzy,
 | |
|         )
 | |
| 
 | |
|     def complete_search(self, string, **kwargs):
 | |
|         """
 | |
|         Like :meth:`.Script.search`, but completes that string. If you want to
 | |
|         have all possible definitions in a file you can also provide an empty
 | |
|         string.
 | |
| 
 | |
|         :param bool all_scopes: Default False; searches not only for
 | |
|             definitions on the top level of a module level, but also in
 | |
|             functions and classes.
 | |
|         :param fuzzy: Default False. Will return fuzzy completions, which means
 | |
|             that e.g. ``ooa`` will match ``foobar``.
 | |
|         :yields: :class:`.Completion`
 | |
|         """
 | |
|         return self._search_func(string, complete=True, **kwargs)
 | |
| 
 | |
|     @validate_line_column
 | |
|     def help(self, line=None, column=None):
 | |
|         """
 | |
|         Used to display a help window to users.  Uses :meth:`.Script.goto` and
 | |
|         returns additional definitions for keywords and operators.
 | |
| 
 | |
|         Typically you will want to display :meth:`.BaseName.docstring` to the
 | |
|         user for all the returned definitions.
 | |
| 
 | |
|         The additional definitions are ``Name(...).type == 'keyword'``.
 | |
|         These definitions do not have a lot of value apart from their docstring
 | |
|         attribute, which contains the output of Python's :func:`help` function.
 | |
| 
 | |
|         :rtype: list of :class:`.Name`
 | |
|         """
 | |
|         self._inference_state.reset_recursion_limitations()
 | |
|         definitions = self.goto(line, column, follow_imports=True)
 | |
|         if definitions:
 | |
|             return definitions
 | |
|         leaf = self._module_node.get_leaf_for_position((line, column))
 | |
| 
 | |
|         if leaf is not None and leaf.end_pos == (line, column) and leaf.type == 'newline':
 | |
|             next_ = leaf.get_next_leaf()
 | |
|             if next_ is not None and next_.start_pos == leaf.end_pos:
 | |
|                 leaf = next_
 | |
| 
 | |
|         if leaf is not None and leaf.type in ('keyword', 'operator', 'error_leaf'):
 | |
|             def need_pydoc():
 | |
|                 if leaf.value in ('(', ')', '[', ']'):
 | |
|                     if leaf.parent.type == 'trailer':
 | |
|                         return False
 | |
|                     if leaf.parent.type == 'atom':
 | |
|                         return False
 | |
|                 grammar = self._inference_state.grammar
 | |
|                 # This parso stuff is not public, but since I control it, this
 | |
|                 # is fine :-) ~dave
 | |
|                 reserved = grammar._pgen_grammar.reserved_syntax_strings.keys()
 | |
|                 return leaf.value in reserved
 | |
| 
 | |
|             if need_pydoc():
 | |
|                 name = KeywordName(self._inference_state, leaf.value)
 | |
|                 return [classes.Name(self._inference_state, name)]
 | |
|         return []
 | |
| 
 | |
|     @validate_line_column
 | |
|     def get_references(self, line=None, column=None, **kwargs):
 | |
|         """
 | |
|         Lists all references of a variable in a project. Since this can be
 | |
|         quite hard to do for Jedi, if it is too complicated, Jedi will stop
 | |
|         searching.
 | |
| 
 | |
|         :param include_builtins: Default ``True``. If ``False``, checks if a definition
 | |
|             is a builtin (e.g. ``sys``) and in that case does not return it.
 | |
|         :param scope: Default ``'project'``. If ``'file'``, include references in
 | |
|             the current module only.
 | |
|         :rtype: list of :class:`.Name`
 | |
|         """
 | |
|         self._inference_state.reset_recursion_limitations()
 | |
| 
 | |
|         def _references(include_builtins=True, scope='project'):
 | |
|             if scope not in ('project', 'file'):
 | |
|                 raise ValueError('Only the scopes "file" and "project" are allowed')
 | |
|             tree_name = self._module_node.get_name_of_position((line, column))
 | |
|             if tree_name is None:
 | |
|                 # Must be syntax
 | |
|                 return []
 | |
| 
 | |
|             names = find_references(self._get_module_context(), tree_name, scope == 'file')
 | |
| 
 | |
|             definitions = [classes.Name(self._inference_state, n) for n in names]
 | |
|             if not include_builtins or scope == 'file':
 | |
|                 definitions = [d for d in definitions if not d.in_builtin_module()]
 | |
|             return helpers.sorted_definitions(definitions)
 | |
|         return _references(**kwargs)
 | |
| 
 | |
|     @validate_line_column
 | |
|     def get_signatures(self, line=None, column=None):
 | |
|         """
 | |
|         Return the function object of the call under the cursor.
 | |
| 
 | |
|         E.g. if the cursor is here::
 | |
| 
 | |
|             abs(# <-- cursor is here
 | |
| 
 | |
|         This would return the ``abs`` function. On the other hand::
 | |
| 
 | |
|             abs()# <-- cursor is here
 | |
| 
 | |
|         This would return an empty list..
 | |
| 
 | |
|         :rtype: list of :class:`.Signature`
 | |
|         """
 | |
|         self._inference_state.reset_recursion_limitations()
 | |
|         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_signatures(
 | |
|             self._inference_state,
 | |
|             context,
 | |
|             call_details.bracket_leaf,
 | |
|             self._code_lines,
 | |
|             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.Signature(self._inference_state, signature, call_details)
 | |
|                 for signature in definitions.get_signatures()]
 | |
| 
 | |
|     @validate_line_column
 | |
|     def get_context(self, line=None, column=None):
 | |
|         """
 | |
|         Returns the scope context under the cursor. This basically means the
 | |
|         function, class or module where the cursor is at.
 | |
| 
 | |
|         :rtype: :class:`.Name`
 | |
|         """
 | |
|         pos = (line, column)
 | |
|         leaf = self._module_node.get_leaf_for_position(pos, include_prefixes=True)
 | |
|         if leaf.start_pos > pos or leaf.type == 'endmarker':
 | |
|             previous_leaf = leaf.get_previous_leaf()
 | |
|             if previous_leaf is not None:
 | |
|                 leaf = previous_leaf
 | |
| 
 | |
|         module_context = self._get_module_context()
 | |
| 
 | |
|         n = tree.search_ancestor(leaf, 'funcdef', 'classdef')
 | |
|         if n is not None and n.start_pos < pos <= n.children[-1].start_pos:
 | |
|             # This is a bit of a special case. The context of a function/class
 | |
|             # name/param/keyword is always it's parent context, not the
 | |
|             # function itself. Catch all the cases here where we are before the
 | |
|             # suite object, but still in the function.
 | |
|             context = module_context.create_value(n).as_context()
 | |
|         else:
 | |
|             context = module_context.create_context(leaf)
 | |
| 
 | |
|         while context.name is None:
 | |
|             context = context.parent_context  # comprehensions
 | |
| 
 | |
|         definition = classes.Name(self._inference_state, context.name)
 | |
|         while definition.type != 'module':
 | |
|             name = definition._name  # TODO private access
 | |
|             tree_name = name.tree_name
 | |
|             if tree_name is not None:  # Happens with lambdas.
 | |
|                 scope = tree_name.get_definition()
 | |
|                 if scope.start_pos[1] < column:
 | |
|                     break
 | |
|             definition = definition.parent()
 | |
|         return definition
 | |
| 
 | |
|     def _analysis(self):
 | |
|         self._inference_state.is_analysis = True
 | |
|         self._inference_state.analysis_modules = [self._module_node]
 | |
|         module = self._get_module_context()
 | |
|         try:
 | |
|             for node in get_executable_nodes(self._module_node):
 | |
|                 context = module.create_context(node)
 | |
|                 if node.type in ('funcdef', 'classdef'):
 | |
|                     # Resolve the decorators.
 | |
|                     tree_name_to_values(self._inference_state, context, node.children[1])
 | |
|                 elif isinstance(node, tree.Import):
 | |
|                     import_names = set(node.get_defined_names())
 | |
|                     if node.is_nested():
 | |
|                         import_names |= set(path[-1] for path in node.get_paths())
 | |
|                     for n in import_names:
 | |
|                         imports.infer_import(context, n)
 | |
|                 elif node.type == 'expr_stmt':
 | |
|                     types = context.infer_node(node)
 | |
|                     for testlist in node.children[:-1:2]:
 | |
|                         # Iterate tuples.
 | |
|                         unpack_tuple_to_dict(context, types, testlist)
 | |
|                 else:
 | |
|                     if node.type == 'name':
 | |
|                         defs = self._inference_state.infer(context, node)
 | |
|                     else:
 | |
|                         defs = infer_call_of_leaf(context, node)
 | |
|                     try_iter_content(defs)
 | |
|                 self._inference_state.reset_recursion_limitations()
 | |
| 
 | |
|             ana = [a for a in self._inference_state.analysis if self.path == a.path]
 | |
|             return sorted(set(ana), key=lambda x: x.line)
 | |
|         finally:
 | |
|             self._inference_state.is_analysis = False
 | |
| 
 | |
|     def get_names(self, **kwargs):
 | |
|         """
 | |
|         Returns names defined in the current file.
 | |
| 
 | |
|         :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``.
 | |
|         :rtype: list of :class:`.Name`
 | |
|         """
 | |
|         names = self._names(**kwargs)
 | |
|         return [classes.Name(self._inference_state, n) for n in names]
 | |
| 
 | |
|     def get_syntax_errors(self):
 | |
|         """
 | |
|         Lists all syntax errors in the current file.
 | |
| 
 | |
|         :rtype: list of :class:`.SyntaxError`
 | |
|         """
 | |
|         return parso_to_jedi_errors(self._inference_state.grammar, self._module_node)
 | |
| 
 | |
|     def _names(self, all_scopes=False, definitions=True, references=False):
 | |
|         self._inference_state.reset_recursion_limitations()
 | |
|         # Set line/column to a random position, because they don't matter.
 | |
|         module_context = self._get_module_context()
 | |
|         defs = [
 | |
|             module_context.create_name(name)
 | |
|             for name in helpers.get_module_names(
 | |
|                 self._module_node,
 | |
|                 all_scopes=all_scopes,
 | |
|                 definitions=definitions,
 | |
|                 references=references,
 | |
|             )
 | |
|         ]
 | |
|         return sorted(defs, key=lambda x: x.start_pos)
 | |
| 
 | |
|     def rename(self, line=None, column=None, *, new_name):
 | |
|         """
 | |
|         Renames all references of the variable under the cursor.
 | |
| 
 | |
|         :param new_name: The variable under the cursor will be renamed to this
 | |
|             string.
 | |
|         :raises: :exc:`.RefactoringError`
 | |
|         :rtype: :class:`.Refactoring`
 | |
|         """
 | |
|         definitions = self.get_references(line, column, include_builtins=False)
 | |
|         return refactoring.rename(self._inference_state, definitions, new_name)
 | |
| 
 | |
|     @validate_line_column
 | |
|     def extract_variable(self, line, column, *, new_name, until_line=None, until_column=None):
 | |
|         """
 | |
|         Moves an expression to a new statement.
 | |
| 
 | |
|         For example if you have the cursor on ``foo`` and provide a
 | |
|         ``new_name`` called ``bar``::
 | |
| 
 | |
|             foo = 3.1
 | |
|             x = int(foo + 1)
 | |
| 
 | |
|         the code above will become::
 | |
| 
 | |
|             foo = 3.1
 | |
|             bar = foo + 1
 | |
|             x = int(bar)
 | |
| 
 | |
|         :param new_name: The expression under the cursor will be renamed to
 | |
|             this string.
 | |
|         :param int until_line: The the selection range ends at this line, when
 | |
|             omitted, Jedi will be clever and try to define the range itself.
 | |
|         :param int until_column: The the selection range ends at this column, when
 | |
|             omitted, Jedi will be clever and try to define the range itself.
 | |
|         :raises: :exc:`.RefactoringError`
 | |
|         :rtype: :class:`.Refactoring`
 | |
|         """
 | |
|         if until_line is None and until_column is None:
 | |
|             until_pos = None
 | |
|         else:
 | |
|             if until_line is None:
 | |
|                 until_line = line
 | |
|             if until_column is None:
 | |
|                 until_column = len(self._code_lines[until_line - 1])
 | |
|             until_pos = until_line, until_column
 | |
|         return extract_variable(
 | |
|             self._inference_state, self.path, self._module_node,
 | |
|             new_name, (line, column), until_pos
 | |
|         )
 | |
| 
 | |
|     @validate_line_column
 | |
|     def extract_function(self, line, column, *, new_name, until_line=None, until_column=None):
 | |
|         """
 | |
|         Moves an expression to a new function.
 | |
| 
 | |
|         For example if you have the cursor on ``foo`` and provide a
 | |
|         ``new_name`` called ``bar``::
 | |
| 
 | |
|             global_var = 3
 | |
| 
 | |
|             def x():
 | |
|                 foo = 3.1
 | |
|                 x = int(foo + 1 + global_var)
 | |
| 
 | |
|         the code above will become::
 | |
| 
 | |
|             global_var = 3
 | |
| 
 | |
|             def bar(foo):
 | |
|                 return int(foo + 1 + global_var)
 | |
| 
 | |
|             def x():
 | |
|                 foo = 3.1
 | |
|                 x = bar(foo)
 | |
| 
 | |
|         :param new_name: The expression under the cursor will be replaced with
 | |
|             a function with this name.
 | |
|         :param int until_line: The the selection range ends at this line, when
 | |
|             omitted, Jedi will be clever and try to define the range itself.
 | |
|         :param int until_column: The the selection range ends at this column, when
 | |
|             omitted, Jedi will be clever and try to define the range itself.
 | |
|         :raises: :exc:`.RefactoringError`
 | |
|         :rtype: :class:`.Refactoring`
 | |
|         """
 | |
|         if until_line is None and until_column is None:
 | |
|             until_pos = None
 | |
|         else:
 | |
|             if until_line is None:
 | |
|                 until_line = line
 | |
|             if until_column is None:
 | |
|                 until_column = len(self._code_lines[until_line - 1])
 | |
|             until_pos = until_line, until_column
 | |
|         return extract_function(
 | |
|             self._inference_state, self.path, self._get_module_context(),
 | |
|             new_name, (line, column), until_pos
 | |
|         )
 | |
| 
 | |
|     def inline(self, line=None, column=None):
 | |
|         """
 | |
|         Inlines a variable under the cursor. This is basically the opposite of
 | |
|         extracting a variable. For example with the cursor on bar::
 | |
| 
 | |
|             foo = 3.1
 | |
|             bar = foo + 1
 | |
|             x = int(bar)
 | |
| 
 | |
|         the code above will become::
 | |
| 
 | |
|             foo = 3.1
 | |
|             x = int(foo + 1)
 | |
| 
 | |
|         :raises: :exc:`.RefactoringError`
 | |
|         :rtype: :class:`.Refactoring`
 | |
|         """
 | |
|         names = [d._name for d in self.get_references(line, column, include_builtins=True)]
 | |
|         return refactoring.inline(self._inference_state, names)
 | |
| 
 | |
| 
 | |
| class Interpreter(Script):
 | |
|     """
 | |
|     Jedi's API for Python REPLs.
 | |
| 
 | |
|     Implements all of the methods that are present in :class:`.Script` as well.
 | |
| 
 | |
|     In addition to completions that normal REPL completion does like
 | |
|     ``str.upper``, Jedi also supports code completion based on static code
 | |
|     analysis. For example Jedi will complete ``str().upper``.
 | |
| 
 | |
|     >>> from os.path import join
 | |
|     >>> namespace = locals()
 | |
|     >>> script = Interpreter('join("").up', [namespace])
 | |
|     >>> print(script.complete()[0].name)
 | |
|     upper
 | |
| 
 | |
|     All keyword arguments are same as the arguments for :class:`.Script`.
 | |
| 
 | |
|     :param str code: Code to parse.
 | |
|     :type namespaces: typing.List[dict]
 | |
|     :param namespaces: A list of namespace dictionaries such as the one
 | |
|         returned by :func:`globals` and :func:`locals`.
 | |
|     """
 | |
| 
 | |
|     def __init__(self, code, namespaces, *, project=None, **kwds):
 | |
|         try:
 | |
|             namespaces = [dict(n) for n in namespaces]
 | |
|         except Exception:
 | |
|             raise TypeError("namespaces must be a non-empty list of dicts.")
 | |
| 
 | |
|         environment = kwds.get('environment', None)
 | |
|         if environment is None:
 | |
|             environment = InterpreterEnvironment()
 | |
|         else:
 | |
|             if not isinstance(environment, InterpreterEnvironment):
 | |
|                 raise TypeError("The environment needs to be an InterpreterEnvironment subclass.")
 | |
| 
 | |
|         if project is None:
 | |
|             project = Project(Path.cwd())
 | |
| 
 | |
|         super().__init__(code, environment=environment, project=project, **kwds)
 | |
| 
 | |
|         self.namespaces = namespaces
 | |
|         self._inference_state.allow_unsafe_executions = \
 | |
|             settings.allow_unsafe_interpreter_executions
 | |
|         # Dynamic params search is important when we work on functions that are
 | |
|         # called by other pieces of code. However for interpreter completions
 | |
|         # this is not important at all, because the current code is always new
 | |
|         # and will never be called by something.
 | |
|         # Also sometimes this logic goes a bit too far like in
 | |
|         # https://github.com/ipython/ipython/issues/13866, where it takes
 | |
|         # seconds to do a simple completion.
 | |
|         self._inference_state.do_dynamic_params_search = False
 | |
| 
 | |
|     @cache.memoize_method
 | |
|     def _get_module_context(self):
 | |
|         if self.path is None:
 | |
|             file_io = None
 | |
|         else:
 | |
|             file_io = KnownContentFileIO(self.path, self._code)
 | |
|         tree_module_value = ModuleValue(
 | |
|             self._inference_state, self._module_node,
 | |
|             file_io=file_io,
 | |
|             string_names=('__main__',),
 | |
|             code_lines=self._code_lines,
 | |
|         )
 | |
|         return interpreter.MixedModuleContext(
 | |
|             tree_module_value,
 | |
|             self.namespaces,
 | |
|         )
 | |
| 
 | |
| 
 | |
| def preload_module(*modules):
 | |
|     """
 | |
|     Preloading modules tells Jedi to load a module now, instead of lazy parsing
 | |
|     of modules. This can be useful for IDEs, to control which modules to load
 | |
|     on startup.
 | |
| 
 | |
|     :param modules: different module names, list of string.
 | |
|     """
 | |
|     for m in modules:
 | |
|         s = "import %s as x; x." % m
 | |
|         Script(s).complete(1, len(s))
 | |
| 
 | |
| 
 | |
| def set_debug_function(func_cb=debug.print_to_stdout, warnings=True,
 | |
|                        notices=True, speed=True):
 | |
|     """
 | |
|     Define a callback debug function to get all the debug messages.
 | |
| 
 | |
|     If you don't specify any arguments, debug messages will be printed to stdout.
 | |
| 
 | |
|     :param func_cb: The callback function for debug messages.
 | |
|     """
 | |
|     debug.debug_function = func_cb
 | |
|     debug.enable_warning = warnings
 | |
|     debug.enable_notice = notices
 | |
|     debug.enable_speed = speed
 |