mirror of
https://github.com/davidhalter/jedi.git
synced 2026-08-19 13:08:01 +08:00
context -> value
This commit is contained in:
@@ -73,16 +73,16 @@ Type inference of python code (inference/__init__.py)
|
|||||||
|
|
||||||
.. automodule:: jedi.inference
|
.. automodule:: jedi.inference
|
||||||
|
|
||||||
Inference Contexts (inference/base_value.py)
|
Inference Values (inference/base_value.py)
|
||||||
++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
|
||||||
.. automodule:: jedi.inference.base_value
|
.. automodule:: jedi.inference.base_value
|
||||||
|
|
||||||
.. inheritance-diagram::
|
.. inheritance-diagram::
|
||||||
jedi.inference.context.instance.TreeInstance
|
jedi.inference.value.instance.TreeInstance
|
||||||
jedi.inference.context.klass.ClassContext
|
jedi.inference.value.klass.Classvalue
|
||||||
jedi.inference.context.function.FunctionContext
|
jedi.inference.value.function.FunctionContext
|
||||||
jedi.inference.context.function.FunctionExecutionContext
|
jedi.inference.value.function.FunctionExecutionContext
|
||||||
:parts: 1
|
:parts: 1
|
||||||
|
|
||||||
|
|
||||||
@@ -124,13 +124,13 @@ without some features.
|
|||||||
|
|
||||||
.. _iterables:
|
.. _iterables:
|
||||||
|
|
||||||
Iterables & Dynamic Arrays (inference/context/iterable.py)
|
Iterables & Dynamic Arrays (inference/value/iterable.py)
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
To understand Python on a deeper level, |jedi| needs to understand some of the
|
To understand Python on a deeper level, |jedi| needs to understand some of the
|
||||||
dynamic features of Python like lists that are filled after creation:
|
dynamic features of Python like lists that are filled after creation:
|
||||||
|
|
||||||
.. automodule:: jedi.inference.context.iterable
|
.. automodule:: jedi.inference.value.iterable
|
||||||
|
|
||||||
|
|
||||||
.. _dynamic:
|
.. _dynamic:
|
||||||
|
|||||||
+24
-24
@@ -35,11 +35,11 @@ from jedi.inference.arguments import try_iter_content
|
|||||||
from jedi.inference.helpers import get_module_names, infer_call_of_leaf
|
from jedi.inference.helpers import get_module_names, infer_call_of_leaf
|
||||||
from jedi.inference.sys_path import transform_path_to_dotted
|
from jedi.inference.sys_path import transform_path_to_dotted
|
||||||
from jedi.inference.names import TreeNameDefinition, ParamName
|
from jedi.inference.names import TreeNameDefinition, ParamName
|
||||||
from jedi.inference.syntax_tree import tree_name_to_contexts
|
from jedi.inference.syntax_tree import tree_name_to_values
|
||||||
from jedi.inference.context import ModuleContext
|
from jedi.inference.value import ModuleContext
|
||||||
from jedi.inference.base_value import ContextSet
|
from jedi.inference.base_value import ContextSet
|
||||||
from jedi.inference.context.iterable import unpack_tuple_to_dict
|
from jedi.inference.value.iterable import unpack_tuple_to_dict
|
||||||
from jedi.inference.gradual.conversion import convert_names, convert_contexts
|
from jedi.inference.gradual.conversion import convert_names, convert_values
|
||||||
from jedi.inference.gradual.utils import load_proper_stub_module
|
from jedi.inference.gradual.utils import load_proper_stub_module
|
||||||
|
|
||||||
# Jedi uses lots and lots of recursion. By setting this a little bit higher, we
|
# Jedi uses lots and lots of recursion. By setting this a little bit higher, we
|
||||||
@@ -239,16 +239,16 @@ class Script(object):
|
|||||||
if leaf is None:
|
if leaf is None:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
context = self._infer_state.create_context(self._get_module(), leaf)
|
value = self._infer_state.create_value(self._get_module(), leaf)
|
||||||
|
|
||||||
contexts = helpers.infer_goto_definition(self._infer_state, context, leaf)
|
values = helpers.infer_goto_definition(self._infer_state, value, leaf)
|
||||||
contexts = convert_contexts(
|
values = convert_values(
|
||||||
contexts,
|
values,
|
||||||
only_stubs=only_stubs,
|
only_stubs=only_stubs,
|
||||||
prefer_stubs=prefer_stubs,
|
prefer_stubs=prefer_stubs,
|
||||||
)
|
)
|
||||||
|
|
||||||
defs = [classes.Definition(self._infer_state, c.name) for c in contexts]
|
defs = [classes.Definition(self._infer_state, c.name) for c in values]
|
||||||
# The additional set here allows the definitions to become unique in an
|
# 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
|
# API sense. In the internals we want to separate more things than in
|
||||||
# the API.
|
# the API.
|
||||||
@@ -299,8 +299,8 @@ class Script(object):
|
|||||||
# Without a name we really just want to jump to the result e.g.
|
# Without a name we really just want to jump to the result e.g.
|
||||||
# executed by `foo()`, if we the cursor is after `)`.
|
# executed by `foo()`, if we the cursor is after `)`.
|
||||||
return self.goto_definitions(only_stubs=only_stubs, prefer_stubs=prefer_stubs)
|
return self.goto_definitions(only_stubs=only_stubs, prefer_stubs=prefer_stubs)
|
||||||
context = self._infer_state.create_context(self._get_module(), tree_name)
|
value = self._infer_state.create_value(self._get_module(), tree_name)
|
||||||
names = list(self._infer_state.goto(context, tree_name))
|
names = list(self._infer_state.goto(value, tree_name))
|
||||||
|
|
||||||
if follow_imports:
|
if follow_imports:
|
||||||
names = filter_follow_imports(names, lambda name: name.is_import())
|
names = filter_follow_imports(names, lambda name: name.is_import())
|
||||||
@@ -368,21 +368,21 @@ class Script(object):
|
|||||||
if call_details is None:
|
if call_details is None:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
context = self._infer_state.create_context(
|
value = self._infer_state.create_value(
|
||||||
self._get_module(),
|
self._get_module(),
|
||||||
call_details.bracket_leaf
|
call_details.bracket_leaf
|
||||||
)
|
)
|
||||||
definitions = helpers.cache_call_signatures(
|
definitions = helpers.cache_call_signatures(
|
||||||
self._infer_state,
|
self._infer_state,
|
||||||
context,
|
value,
|
||||||
call_details.bracket_leaf,
|
call_details.bracket_leaf,
|
||||||
self._code_lines,
|
self._code_lines,
|
||||||
self._pos
|
self._pos
|
||||||
)
|
)
|
||||||
debug.speed('func_call followed')
|
debug.speed('func_call followed')
|
||||||
|
|
||||||
# TODO here we use stubs instead of the actual contexts. We should use
|
# TODO here we use stubs instead of the actual values. We should use
|
||||||
# the signatures from stubs, but the actual contexts, probably?!
|
# the signatures from stubs, but the actual values, probably?!
|
||||||
return [classes.CallSignature(self._infer_state, signature, call_details)
|
return [classes.CallSignature(self._infer_state, signature, call_details)
|
||||||
for signature in definitions.get_signatures()]
|
for signature in definitions.get_signatures()]
|
||||||
|
|
||||||
@@ -392,26 +392,26 @@ class Script(object):
|
|||||||
module = self._get_module()
|
module = self._get_module()
|
||||||
try:
|
try:
|
||||||
for node in get_executable_nodes(self._module_node):
|
for node in get_executable_nodes(self._module_node):
|
||||||
context = module.create_context(node)
|
value = module.create_value(node)
|
||||||
if node.type in ('funcdef', 'classdef'):
|
if node.type in ('funcdef', 'classdef'):
|
||||||
# Resolve the decorators.
|
# Resolve the decorators.
|
||||||
tree_name_to_contexts(self._infer_state, context, node.children[1])
|
tree_name_to_values(self._infer_state, value, node.children[1])
|
||||||
elif isinstance(node, tree.Import):
|
elif isinstance(node, tree.Import):
|
||||||
import_names = set(node.get_defined_names())
|
import_names = set(node.get_defined_names())
|
||||||
if node.is_nested():
|
if node.is_nested():
|
||||||
import_names |= set(path[-1] for path in node.get_paths())
|
import_names |= set(path[-1] for path in node.get_paths())
|
||||||
for n in import_names:
|
for n in import_names:
|
||||||
imports.infer_import(context, n)
|
imports.infer_import(value, n)
|
||||||
elif node.type == 'expr_stmt':
|
elif node.type == 'expr_stmt':
|
||||||
types = context.infer_node(node)
|
types = value.infer_node(node)
|
||||||
for testlist in node.children[:-1:2]:
|
for testlist in node.children[:-1:2]:
|
||||||
# Iterate tuples.
|
# Iterate tuples.
|
||||||
unpack_tuple_to_dict(context, types, testlist)
|
unpack_tuple_to_dict(value, types, testlist)
|
||||||
else:
|
else:
|
||||||
if node.type == 'name':
|
if node.type == 'name':
|
||||||
defs = self._infer_state.goto_definitions(context, node)
|
defs = self._infer_state.goto_definitions(value, node)
|
||||||
else:
|
else:
|
||||||
defs = infer_call_of_leaf(context, node)
|
defs = infer_call_of_leaf(value, node)
|
||||||
try_iter_content(defs)
|
try_iter_content(defs)
|
||||||
self._infer_state.reset_recursion_limitations()
|
self._infer_state.reset_recursion_limitations()
|
||||||
|
|
||||||
@@ -505,13 +505,13 @@ def names(source=None, path=None, encoding='utf-8', all_scopes=False,
|
|||||||
else:
|
else:
|
||||||
cls = TreeNameDefinition
|
cls = TreeNameDefinition
|
||||||
return cls(
|
return cls(
|
||||||
module_context.create_context(name),
|
module_value.create_value(name),
|
||||||
name
|
name
|
||||||
)
|
)
|
||||||
|
|
||||||
# Set line/column to a random position, because they don't matter.
|
# 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)
|
script = Script(source, line=1, column=0, path=path, encoding=encoding, environment=environment)
|
||||||
module_context = script._get_module()
|
module_value = script._get_module()
|
||||||
defs = [
|
defs = [
|
||||||
classes.Definition(
|
classes.Definition(
|
||||||
script._infer_state,
|
script._infer_state,
|
||||||
|
|||||||
+41
-41
@@ -14,9 +14,9 @@ from jedi.cache import memoize_method
|
|||||||
from jedi.inference import imports
|
from jedi.inference import imports
|
||||||
from jedi.inference import compiled
|
from jedi.inference import compiled
|
||||||
from jedi.inference.imports import ImportName
|
from jedi.inference.imports import ImportName
|
||||||
from jedi.inference.context import FunctionExecutionContext
|
from jedi.inference.value import FunctionExecutionContext
|
||||||
from jedi.inference.gradual.typeshed import StubModuleContext
|
from jedi.inference.gradual.typeshed import StubModuleContext
|
||||||
from jedi.inference.gradual.conversion import convert_names, convert_contexts
|
from jedi.inference.gradual.conversion import convert_names, convert_values
|
||||||
from jedi.inference.base_value import ContextSet
|
from jedi.inference.base_value import ContextSet
|
||||||
from jedi.api.keywords import KeywordName
|
from jedi.api.keywords import KeywordName
|
||||||
|
|
||||||
@@ -25,20 +25,20 @@ def _sort_names_by_start_pos(names):
|
|||||||
return sorted(names, key=lambda s: s.start_pos or (0, 0))
|
return sorted(names, key=lambda s: s.start_pos or (0, 0))
|
||||||
|
|
||||||
|
|
||||||
def defined_names(infer_state, context):
|
def defined_names(infer_state, value):
|
||||||
"""
|
"""
|
||||||
List sub-definitions (e.g., methods in class).
|
List sub-definitions (e.g., methods in class).
|
||||||
|
|
||||||
:type scope: Scope
|
:type scope: Scope
|
||||||
:rtype: list of Definition
|
:rtype: list of Definition
|
||||||
"""
|
"""
|
||||||
filter = next(context.get_filters(search_global=True))
|
filter = next(value.get_filters(search_global=True))
|
||||||
names = [name for name in filter.values()]
|
names = [name for name in filter.values()]
|
||||||
return [Definition(infer_state, n) for n in _sort_names_by_start_pos(names)]
|
return [Definition(infer_state, n) for n in _sort_names_by_start_pos(names)]
|
||||||
|
|
||||||
|
|
||||||
def _contexts_to_definitions(contexts):
|
def _values_to_definitions(values):
|
||||||
return [Definition(c.infer_state, c.name) for c in contexts]
|
return [Definition(c.infer_state, c.name) for c in values]
|
||||||
|
|
||||||
|
|
||||||
class BaseDefinition(object):
|
class BaseDefinition(object):
|
||||||
@@ -75,7 +75,7 @@ class BaseDefinition(object):
|
|||||||
# This can take a while to complete, because in the worst case of
|
# This can take a while to complete, because in the worst case of
|
||||||
# imports (consider `import a` completions), we need to load all
|
# imports (consider `import a` completions), we need to load all
|
||||||
# modules starting with a first.
|
# modules starting with a first.
|
||||||
return self._name.get_root_context()
|
return self._name.get_root_value()
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def module_path(self):
|
def module_path(self):
|
||||||
@@ -167,8 +167,8 @@ class BaseDefinition(object):
|
|||||||
resolve = True
|
resolve = True
|
||||||
|
|
||||||
if isinstance(self._name, imports.SubModuleName) or resolve:
|
if isinstance(self._name, imports.SubModuleName) or resolve:
|
||||||
for context in self._name.infer():
|
for value in self._name.infer():
|
||||||
return context.api_type
|
return value.api_type
|
||||||
return self._name.api_type
|
return self._name.api_type
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@@ -188,8 +188,8 @@ class BaseDefinition(object):
|
|||||||
def in_builtin_module(self):
|
def in_builtin_module(self):
|
||||||
"""Whether this is a builtin module."""
|
"""Whether this is a builtin module."""
|
||||||
if isinstance(self._get_module(), StubModuleContext):
|
if isinstance(self._get_module(), StubModuleContext):
|
||||||
return any(isinstance(context, compiled.CompiledObject)
|
return any(isinstance(value, compiled.CompiledObject)
|
||||||
for context in self._get_module().non_stub_context_set)
|
for value in self._get_module().non_stub_value_set)
|
||||||
return isinstance(self._get_module(), compiled.CompiledObject)
|
return isinstance(self._get_module(), compiled.CompiledObject)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@@ -270,7 +270,7 @@ class BaseDefinition(object):
|
|||||||
be ``<module 'posixpath' ...>```. However most users find the latter
|
be ``<module 'posixpath' ...>```. However most users find the latter
|
||||||
more practical.
|
more practical.
|
||||||
"""
|
"""
|
||||||
if not self._name.is_context_name:
|
if not self._name.is_value_name:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
names = self._name.get_qualified_names(include_module_names=True)
|
names = self._name.get_qualified_names(include_module_names=True)
|
||||||
@@ -286,10 +286,10 @@ class BaseDefinition(object):
|
|||||||
return '.'.join(names)
|
return '.'.join(names)
|
||||||
|
|
||||||
def is_stub(self):
|
def is_stub(self):
|
||||||
if not self._name.is_context_name:
|
if not self._name.is_value_name:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
return self._name.get_root_context().is_stub()
|
return self._name.get_root_value().is_stub()
|
||||||
|
|
||||||
def goto_assignments(self, **kwargs): # Python 2...
|
def goto_assignments(self, **kwargs): # Python 2...
|
||||||
with debug.increase_indent_cm('goto for %s' % self._name):
|
with debug.increase_indent_cm('goto for %s' % self._name):
|
||||||
@@ -298,7 +298,7 @@ class BaseDefinition(object):
|
|||||||
def _goto_assignments(self, only_stubs=False, prefer_stubs=False):
|
def _goto_assignments(self, only_stubs=False, prefer_stubs=False):
|
||||||
assert not (only_stubs and prefer_stubs)
|
assert not (only_stubs and prefer_stubs)
|
||||||
|
|
||||||
if not self._name.is_context_name:
|
if not self._name.is_value_name:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
names = convert_names(
|
names = convert_names(
|
||||||
@@ -316,19 +316,19 @@ class BaseDefinition(object):
|
|||||||
def _infer(self, only_stubs=False, prefer_stubs=False):
|
def _infer(self, only_stubs=False, prefer_stubs=False):
|
||||||
assert not (only_stubs and prefer_stubs)
|
assert not (only_stubs and prefer_stubs)
|
||||||
|
|
||||||
if not self._name.is_context_name:
|
if not self._name.is_value_name:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
# First we need to make sure that we have stub names (if possible) that
|
# First we need to make sure that we have stub names (if possible) that
|
||||||
# we can follow. If we don't do that, we can end up with the inferred
|
# we can follow. If we don't do that, we can end up with the inferred
|
||||||
# results of Python objects instead of stubs.
|
# results of Python objects instead of stubs.
|
||||||
names = convert_names([self._name], prefer_stubs=True)
|
names = convert_names([self._name], prefer_stubs=True)
|
||||||
contexts = convert_contexts(
|
values = convert_values(
|
||||||
ContextSet.from_sets(n.infer() for n in names),
|
ContextSet.from_sets(n.infer() for n in names),
|
||||||
only_stubs=only_stubs,
|
only_stubs=only_stubs,
|
||||||
prefer_stubs=prefer_stubs,
|
prefer_stubs=prefer_stubs,
|
||||||
)
|
)
|
||||||
resulting_names = [c.name for c in contexts]
|
resulting_names = [c.name for c in values]
|
||||||
return [self if n == self._name else Definition(self._infer_state, n)
|
return [self if n == self._name else Definition(self._infer_state, n)
|
||||||
for n in resulting_names]
|
for n in resulting_names]
|
||||||
|
|
||||||
@@ -343,8 +343,8 @@ class BaseDefinition(object):
|
|||||||
"""
|
"""
|
||||||
# Only return the first one. There might be multiple one, especially
|
# Only return the first one. There might be multiple one, especially
|
||||||
# with overloading.
|
# with overloading.
|
||||||
for context in self._name.infer():
|
for value in self._name.infer():
|
||||||
for signature in context.get_signatures():
|
for signature in value.get_signatures():
|
||||||
return [
|
return [
|
||||||
Definition(self._infer_state, n)
|
Definition(self._infer_state, n)
|
||||||
for n in signature.get_param_names(resolve_stars=True)
|
for n in signature.get_param_names(resolve_stars=True)
|
||||||
@@ -357,16 +357,16 @@ class BaseDefinition(object):
|
|||||||
raise AttributeError('There are no params defined on this.')
|
raise AttributeError('There are no params defined on this.')
|
||||||
|
|
||||||
def parent(self):
|
def parent(self):
|
||||||
if not self._name.is_context_name:
|
if not self._name.is_value_name:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
context = self._name.parent_context
|
value = self._name.parent_value
|
||||||
if context is None:
|
if value is None:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
if isinstance(context, FunctionExecutionContext):
|
if isinstance(value, FunctionExecutionContext):
|
||||||
context = context.function_context
|
value = value.function_value
|
||||||
return Definition(self._infer_state, context.name)
|
return Definition(self._infer_state, value.name)
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "<%s %sname=%r, description=%r>" % (
|
return "<%s %sname=%r, description=%r>" % (
|
||||||
@@ -386,10 +386,10 @@ class BaseDefinition(object):
|
|||||||
:return str: Returns the line(s) of code or an empty string if it's a
|
:return str: Returns the line(s) of code or an empty string if it's a
|
||||||
builtin.
|
builtin.
|
||||||
"""
|
"""
|
||||||
if not self._name.is_context_name or self.in_builtin_module():
|
if not self._name.is_value_name or self.in_builtin_module():
|
||||||
return ''
|
return ''
|
||||||
|
|
||||||
lines = self._name.get_root_context().code_lines
|
lines = self._name.get_root_value().code_lines
|
||||||
|
|
||||||
index = self._name.start_pos[0] - 1
|
index = self._name.start_pos[0] - 1
|
||||||
start_index = max(index - before, 0)
|
start_index = max(index - before, 0)
|
||||||
@@ -399,7 +399,7 @@ class BaseDefinition(object):
|
|||||||
return [Signature(self._infer_state, s) for s in self._name.infer().get_signatures()]
|
return [Signature(self._infer_state, s) for s in self._name.infer().get_signatures()]
|
||||||
|
|
||||||
def execute(self):
|
def execute(self):
|
||||||
return _contexts_to_definitions(self._name.infer().execute_with_values())
|
return _values_to_definitions(self._name.infer().execute_with_values())
|
||||||
|
|
||||||
|
|
||||||
class Completion(BaseDefinition):
|
class Completion(BaseDefinition):
|
||||||
@@ -680,7 +680,7 @@ class ParamDefinition(Definition):
|
|||||||
"""
|
"""
|
||||||
:return list of Definition:
|
:return list of Definition:
|
||||||
"""
|
"""
|
||||||
return _contexts_to_definitions(self._name.infer_default())
|
return _values_to_definitions(self._name.infer_default())
|
||||||
|
|
||||||
def infer_annotation(self, **kwargs):
|
def infer_annotation(self, **kwargs):
|
||||||
"""
|
"""
|
||||||
@@ -689,7 +689,7 @@ class ParamDefinition(Definition):
|
|||||||
:param execute_annotation: If False, the values are not executed and
|
:param execute_annotation: If False, the values are not executed and
|
||||||
you get classes instead of instances.
|
you get classes instead of instances.
|
||||||
"""
|
"""
|
||||||
return _contexts_to_definitions(self._name.infer_annotation(**kwargs))
|
return _values_to_definitions(self._name.infer_annotation(**kwargs))
|
||||||
|
|
||||||
def to_string(self):
|
def to_string(self):
|
||||||
return self._name.to_string()
|
return self._name.to_string()
|
||||||
@@ -709,10 +709,10 @@ class ParamDefinition(Definition):
|
|||||||
return self._name.get_kind()
|
return self._name.get_kind()
|
||||||
|
|
||||||
|
|
||||||
def _format_signatures(context):
|
def _format_signatures(value):
|
||||||
return '\n'.join(
|
return '\n'.join(
|
||||||
signature.to_string()
|
signature.to_string()
|
||||||
for signature in context.get_signatures()
|
for signature in value.get_signatures()
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -725,7 +725,7 @@ class _Help(object):
|
|||||||
self._name = definition
|
self._name = definition
|
||||||
|
|
||||||
@memoize_method
|
@memoize_method
|
||||||
def _get_contexts(self, fast):
|
def _get_values(self, fast):
|
||||||
if isinstance(self._name, ImportName) and fast:
|
if isinstance(self._name, ImportName) and fast:
|
||||||
return {}
|
return {}
|
||||||
|
|
||||||
@@ -742,20 +742,20 @@ class _Help(object):
|
|||||||
"""
|
"""
|
||||||
full_doc = ''
|
full_doc = ''
|
||||||
# Using the first docstring that we see.
|
# Using the first docstring that we see.
|
||||||
for context in self._get_contexts(fast=fast):
|
for value in self._get_values(fast=fast):
|
||||||
if full_doc:
|
if full_doc:
|
||||||
# In case we have multiple contexts, just return all of them
|
# In case we have multiple values, just return all of them
|
||||||
# separated by a few dashes.
|
# separated by a few dashes.
|
||||||
full_doc += '\n' + '-' * 30 + '\n'
|
full_doc += '\n' + '-' * 30 + '\n'
|
||||||
|
|
||||||
doc = context.py__doc__()
|
doc = value.py__doc__()
|
||||||
|
|
||||||
signature_text = ''
|
signature_text = ''
|
||||||
if self._name.is_context_name:
|
if self._name.is_value_name:
|
||||||
if not raw:
|
if not raw:
|
||||||
signature_text = _format_signatures(context)
|
signature_text = _format_signatures(value)
|
||||||
if not doc and context.is_stub():
|
if not doc and value.is_stub():
|
||||||
for c in convert_contexts(ContextSet({context}), ignore_compiled=False):
|
for c in convert_values(ContextSet({value}), ignore_compiled=False):
|
||||||
doc = c.py__doc__()
|
doc = c.py__doc__()
|
||||||
if doc:
|
if doc:
|
||||||
break
|
break
|
||||||
|
|||||||
+35
-35
@@ -14,7 +14,7 @@ from jedi.api.file_name import file_name_completions
|
|||||||
from jedi.inference import imports
|
from jedi.inference import imports
|
||||||
from jedi.inference.helpers import infer_call_of_leaf, parse_dotted_names
|
from jedi.inference.helpers import infer_call_of_leaf, parse_dotted_names
|
||||||
from jedi.inference.filters import get_global_filters
|
from jedi.inference.filters import get_global_filters
|
||||||
from jedi.inference.gradual.conversion import convert_contexts
|
from jedi.inference.gradual.conversion import convert_values
|
||||||
from jedi.parser_utils import get_statement_of_position, cut_value_at_position
|
from jedi.parser_utils import get_statement_of_position, cut_value_at_position
|
||||||
|
|
||||||
|
|
||||||
@@ -52,11 +52,11 @@ def filter_names(infer_state, completion_names, stack, like_name):
|
|||||||
yield new
|
yield new
|
||||||
|
|
||||||
|
|
||||||
def get_user_scope(module_context, position):
|
def get_user_scope(module_value, position):
|
||||||
"""
|
"""
|
||||||
Returns the scope in which the user resides. This includes flows.
|
Returns the scope in which the user resides. This includes flows.
|
||||||
"""
|
"""
|
||||||
user_stmt = get_statement_of_position(module_context.tree_node, position)
|
user_stmt = get_statement_of_position(module_value.tree_node, position)
|
||||||
if user_stmt is None:
|
if user_stmt is None:
|
||||||
def scan(scope):
|
def scan(scope):
|
||||||
for s in scope.children:
|
for s in scope.children:
|
||||||
@@ -68,12 +68,12 @@ def get_user_scope(module_context, position):
|
|||||||
return scan(s)
|
return scan(s)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
scanned_node = scan(module_context.tree_node)
|
scanned_node = scan(module_value.tree_node)
|
||||||
if scanned_node:
|
if scanned_node:
|
||||||
return module_context.create_context(scanned_node, node_is_context=True)
|
return module_value.create_value(scanned_node, node_is_value=True)
|
||||||
return module_context
|
return module_value
|
||||||
else:
|
else:
|
||||||
return module_context.create_context(user_stmt)
|
return module_value.create_value(user_stmt)
|
||||||
|
|
||||||
|
|
||||||
def get_flow_scope_node(module_node, position):
|
def get_flow_scope_node(module_node, position):
|
||||||
@@ -87,7 +87,7 @@ def get_flow_scope_node(module_node, position):
|
|||||||
class Completion:
|
class Completion:
|
||||||
def __init__(self, infer_state, module, code_lines, position, call_signatures_callback):
|
def __init__(self, infer_state, module, code_lines, position, call_signatures_callback):
|
||||||
self._infer_state = infer_state
|
self._infer_state = infer_state
|
||||||
self._module_context = module
|
self._module_value = module
|
||||||
self._module_node = module.tree_node
|
self._module_node = module.tree_node
|
||||||
self._code_lines = code_lines
|
self._code_lines = code_lines
|
||||||
|
|
||||||
@@ -104,14 +104,14 @@ class Completion:
|
|||||||
string, start_leaf = _extract_string_while_in_string(leaf, self._position)
|
string, start_leaf = _extract_string_while_in_string(leaf, self._position)
|
||||||
if string is not None:
|
if string is not None:
|
||||||
completions = list(file_name_completions(
|
completions = list(file_name_completions(
|
||||||
self._infer_state, self._module_context, start_leaf, string,
|
self._infer_state, self._module_value, start_leaf, string,
|
||||||
self._like_name, self._call_signatures_callback,
|
self._like_name, self._call_signatures_callback,
|
||||||
self._code_lines, self._original_position
|
self._code_lines, self._original_position
|
||||||
))
|
))
|
||||||
if completions:
|
if completions:
|
||||||
return completions
|
return completions
|
||||||
|
|
||||||
completion_names = self._get_context_completions(leaf)
|
completion_names = self._get_value_completions(leaf)
|
||||||
|
|
||||||
completions = filter_names(self._infer_state, completion_names,
|
completions = filter_names(self._infer_state, completion_names,
|
||||||
self.stack, self._like_name)
|
self.stack, self._like_name)
|
||||||
@@ -120,9 +120,9 @@ class Completion:
|
|||||||
x.name.startswith('_'),
|
x.name.startswith('_'),
|
||||||
x.name.lower()))
|
x.name.lower()))
|
||||||
|
|
||||||
def _get_context_completions(self, leaf):
|
def _get_value_completions(self, leaf):
|
||||||
"""
|
"""
|
||||||
Analyzes the context that a completion is made in and decides what to
|
Analyzes the value that a completion is made in and decides what to
|
||||||
return.
|
return.
|
||||||
|
|
||||||
Technically this works by generating a parser stack and analysing the
|
Technically this works by generating a parser stack and analysing the
|
||||||
@@ -149,7 +149,7 @@ class Completion:
|
|||||||
# completions since this probably just confuses the user.
|
# completions since this probably just confuses the user.
|
||||||
return []
|
return []
|
||||||
|
|
||||||
# If we don't have a context, just use global completion.
|
# If we don't have a value, just use global completion.
|
||||||
return self._global_completions()
|
return self._global_completions()
|
||||||
|
|
||||||
allowed_transitions = \
|
allowed_transitions = \
|
||||||
@@ -208,7 +208,7 @@ class Completion:
|
|||||||
if nodes and nodes[-1] in ('as', 'def', 'class'):
|
if nodes and nodes[-1] in ('as', 'def', 'class'):
|
||||||
# No completions for ``with x as foo`` and ``import x as foo``.
|
# No completions for ``with x as foo`` and ``import x as foo``.
|
||||||
# Also true for defining names as a class or function.
|
# Also true for defining names as a class or function.
|
||||||
return list(self._get_class_context_completions(is_function=True))
|
return list(self._get_class_value_completions(is_function=True))
|
||||||
elif "import_stmt" in nonterminals:
|
elif "import_stmt" in nonterminals:
|
||||||
level, names = parse_dotted_names(nodes, "import_from" in nonterminals)
|
level, names = parse_dotted_names(nodes, "import_from" in nonterminals)
|
||||||
|
|
||||||
@@ -223,7 +223,7 @@ class Completion:
|
|||||||
completion_names += self._trailer_completions(dot.get_previous_leaf())
|
completion_names += self._trailer_completions(dot.get_previous_leaf())
|
||||||
else:
|
else:
|
||||||
completion_names += self._global_completions()
|
completion_names += self._global_completions()
|
||||||
completion_names += self._get_class_context_completions(is_function=False)
|
completion_names += self._get_class_value_completions(is_function=False)
|
||||||
|
|
||||||
if 'trailer' in nonterminals:
|
if 'trailer' in nonterminals:
|
||||||
call_signatures = self._call_signatures_callback()
|
call_signatures = self._call_signatures_callback()
|
||||||
@@ -237,12 +237,12 @@ class Completion:
|
|||||||
yield keywords.KeywordName(self._infer_state, k)
|
yield keywords.KeywordName(self._infer_state, k)
|
||||||
|
|
||||||
def _global_completions(self):
|
def _global_completions(self):
|
||||||
context = get_user_scope(self._module_context, self._position)
|
value = get_user_scope(self._module_value, self._position)
|
||||||
debug.dbg('global completion scope: %s', context)
|
debug.dbg('global completion scope: %s', value)
|
||||||
flow_scope_node = get_flow_scope_node(self._module_node, self._position)
|
flow_scope_node = get_flow_scope_node(self._module_node, self._position)
|
||||||
filters = get_global_filters(
|
filters = get_global_filters(
|
||||||
self._infer_state,
|
self._infer_state,
|
||||||
context,
|
value,
|
||||||
self._position,
|
self._position,
|
||||||
origin_scope=flow_scope_node
|
origin_scope=flow_scope_node
|
||||||
)
|
)
|
||||||
@@ -252,34 +252,34 @@ class Completion:
|
|||||||
return completion_names
|
return completion_names
|
||||||
|
|
||||||
def _trailer_completions(self, previous_leaf):
|
def _trailer_completions(self, previous_leaf):
|
||||||
user_context = get_user_scope(self._module_context, self._position)
|
user_value = get_user_scope(self._module_value, self._position)
|
||||||
inferred_context = self._infer_state.create_context(
|
inferred_value = self._infer_state.create_value(
|
||||||
self._module_context, previous_leaf
|
self._module_value, previous_leaf
|
||||||
)
|
)
|
||||||
contexts = infer_call_of_leaf(inferred_context, previous_leaf)
|
values = infer_call_of_leaf(inferred_value, previous_leaf)
|
||||||
completion_names = []
|
completion_names = []
|
||||||
debug.dbg('trailer completion contexts: %s', contexts, color='MAGENTA')
|
debug.dbg('trailer completion values: %s', values, color='MAGENTA')
|
||||||
for context in contexts:
|
for value in values:
|
||||||
for filter in context.get_filters(
|
for filter in value.get_filters(
|
||||||
search_global=False,
|
search_global=False,
|
||||||
origin_scope=user_context.tree_node):
|
origin_scope=user_value.tree_node):
|
||||||
completion_names += filter.values()
|
completion_names += filter.values()
|
||||||
|
|
||||||
python_contexts = convert_contexts(contexts)
|
python_values = convert_values(values)
|
||||||
for c in python_contexts:
|
for c in python_values:
|
||||||
if c not in contexts:
|
if c not in values:
|
||||||
for filter in c.get_filters(
|
for filter in c.get_filters(
|
||||||
search_global=False,
|
search_global=False,
|
||||||
origin_scope=user_context.tree_node):
|
origin_scope=user_value.tree_node):
|
||||||
completion_names += filter.values()
|
completion_names += filter.values()
|
||||||
return completion_names
|
return completion_names
|
||||||
|
|
||||||
def _get_importer_names(self, names, level=0, only_modules=True):
|
def _get_importer_names(self, names, level=0, only_modules=True):
|
||||||
names = [n.value for n in names]
|
names = [n.value for n in names]
|
||||||
i = imports.Importer(self._infer_state, names, self._module_context, level)
|
i = imports.Importer(self._infer_state, names, self._module_value, level)
|
||||||
return i.completion_names(self._infer_state, only_modules=only_modules)
|
return i.completion_names(self._infer_state, only_modules=only_modules)
|
||||||
|
|
||||||
def _get_class_context_completions(self, is_function=True):
|
def _get_class_value_completions(self, is_function=True):
|
||||||
"""
|
"""
|
||||||
Autocomplete inherited methods when overriding in child class.
|
Autocomplete inherited methods when overriding in child class.
|
||||||
"""
|
"""
|
||||||
@@ -287,9 +287,9 @@ class Completion:
|
|||||||
cls = tree.search_ancestor(leaf, 'classdef')
|
cls = tree.search_ancestor(leaf, 'classdef')
|
||||||
if isinstance(cls, (tree.Class, tree.Function)):
|
if isinstance(cls, (tree.Class, tree.Function)):
|
||||||
# Complete the methods that are defined in the super classes.
|
# Complete the methods that are defined in the super classes.
|
||||||
random_context = self._module_context.create_context(
|
random_value = self._module_value.create_value(
|
||||||
cls,
|
cls,
|
||||||
node_is_context=True
|
node_is_value=True
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
return
|
return
|
||||||
@@ -297,7 +297,7 @@ class Completion:
|
|||||||
if cls.start_pos[1] >= leaf.start_pos[1]:
|
if cls.start_pos[1] >= leaf.start_pos[1]:
|
||||||
return
|
return
|
||||||
|
|
||||||
filters = random_context.get_filters(search_global=False, is_instance=True)
|
filters = random_value.get_filters(search_global=False, is_instance=True)
|
||||||
# The first dict is the dictionary of class itself.
|
# The first dict is the dictionary of class itself.
|
||||||
next(filters)
|
next(filters)
|
||||||
for filter in filters:
|
for filter in filters:
|
||||||
|
|||||||
+17
-17
@@ -7,12 +7,12 @@ from jedi.inference.helpers import get_str_or_none
|
|||||||
from jedi.parser_utils import get_string_quote
|
from jedi.parser_utils import get_string_quote
|
||||||
|
|
||||||
|
|
||||||
def file_name_completions(infer_state, module_context, start_leaf, string,
|
def file_name_completions(infer_state, module_value, start_leaf, string,
|
||||||
like_name, call_signatures_callback, code_lines, position):
|
like_name, call_signatures_callback, code_lines, position):
|
||||||
# First we want to find out what can actually be changed as a name.
|
# First we want to find out what can actually be changed as a name.
|
||||||
like_name_length = len(os.path.basename(string) + like_name)
|
like_name_length = len(os.path.basename(string) + like_name)
|
||||||
|
|
||||||
addition = _get_string_additions(module_context, start_leaf)
|
addition = _get_string_additions(module_value, start_leaf)
|
||||||
if addition is None:
|
if addition is None:
|
||||||
return
|
return
|
||||||
string = addition + string
|
string = addition + string
|
||||||
@@ -25,7 +25,7 @@ def file_name_completions(infer_state, module_context, start_leaf, string,
|
|||||||
sigs = call_signatures_callback()
|
sigs = call_signatures_callback()
|
||||||
is_in_os_path_join = sigs and all(s.full_name == 'os.path.join' for s in sigs)
|
is_in_os_path_join = sigs and all(s.full_name == 'os.path.join' for s in sigs)
|
||||||
if is_in_os_path_join:
|
if is_in_os_path_join:
|
||||||
to_be_added = _add_os_path_join(module_context, start_leaf, sigs[0].bracket_start)
|
to_be_added = _add_os_path_join(module_value, start_leaf, sigs[0].bracket_start)
|
||||||
if to_be_added is None:
|
if to_be_added is None:
|
||||||
is_in_os_path_join = False
|
is_in_os_path_join = False
|
||||||
else:
|
else:
|
||||||
@@ -60,7 +60,7 @@ def file_name_completions(infer_state, module_context, start_leaf, string,
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def _get_string_additions(module_context, start_leaf):
|
def _get_string_additions(module_value, start_leaf):
|
||||||
def iterate_nodes():
|
def iterate_nodes():
|
||||||
node = addition.parent
|
node = addition.parent
|
||||||
was_addition = True
|
was_addition = True
|
||||||
@@ -77,18 +77,18 @@ def _get_string_additions(module_context, start_leaf):
|
|||||||
addition = start_leaf.get_previous_leaf()
|
addition = start_leaf.get_previous_leaf()
|
||||||
if addition != '+':
|
if addition != '+':
|
||||||
return ''
|
return ''
|
||||||
context = module_context.create_context(start_leaf)
|
value = module_value.create_value(start_leaf)
|
||||||
return _add_strings(context, reversed(list(iterate_nodes())))
|
return _add_strings(value, reversed(list(iterate_nodes())))
|
||||||
|
|
||||||
|
|
||||||
def _add_strings(context, nodes, add_slash=False):
|
def _add_strings(value, nodes, add_slash=False):
|
||||||
string = ''
|
string = ''
|
||||||
first = True
|
first = True
|
||||||
for child_node in nodes:
|
for child_node in nodes:
|
||||||
contexts = context.infer_node(child_node)
|
values = value.infer_node(child_node)
|
||||||
if len(contexts) != 1:
|
if len(values) != 1:
|
||||||
return None
|
return None
|
||||||
c, = contexts
|
c, = values
|
||||||
s = get_str_or_none(c)
|
s = get_str_or_none(c)
|
||||||
if s is None:
|
if s is None:
|
||||||
return None
|
return None
|
||||||
@@ -101,25 +101,25 @@ def _add_strings(context, nodes, add_slash=False):
|
|||||||
|
|
||||||
class FileName(AbstractArbitraryName):
|
class FileName(AbstractArbitraryName):
|
||||||
api_type = u'path'
|
api_type = u'path'
|
||||||
is_context_name = False
|
is_value_name = False
|
||||||
|
|
||||||
|
|
||||||
def _add_os_path_join(module_context, start_leaf, bracket_start):
|
def _add_os_path_join(module_value, start_leaf, bracket_start):
|
||||||
def check(maybe_bracket, nodes):
|
def check(maybe_bracket, nodes):
|
||||||
if maybe_bracket.start_pos != bracket_start:
|
if maybe_bracket.start_pos != bracket_start:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
if not nodes:
|
if not nodes:
|
||||||
return ''
|
return ''
|
||||||
context = module_context.create_context(nodes[0])
|
value = module_value.create_value(nodes[0])
|
||||||
return _add_strings(context, nodes, add_slash=True) or ''
|
return _add_strings(value, nodes, add_slash=True) or ''
|
||||||
|
|
||||||
if start_leaf.type == 'error_leaf':
|
if start_leaf.type == 'error_leaf':
|
||||||
# Unfinished string literal, like `join('`
|
# Unfinished string literal, like `join('`
|
||||||
context_node = start_leaf.parent
|
value_node = start_leaf.parent
|
||||||
index = context_node.children.index(start_leaf)
|
index = value_node.children.index(start_leaf)
|
||||||
if index > 0:
|
if index > 0:
|
||||||
error_node = context_node.children[index - 1]
|
error_node = value_node.children[index - 1]
|
||||||
if error_node.type == 'error_node' and len(error_node.children) >= 2:
|
if error_node.type == 'error_node' and len(error_node.children) >= 2:
|
||||||
index = -2
|
index = -2
|
||||||
if error_node.children[-1].type == 'arglist':
|
if error_node.children[-1].type == 'arglist':
|
||||||
|
|||||||
+11
-11
@@ -12,7 +12,7 @@ from jedi._compatibility import u, Parameter
|
|||||||
from jedi.inference.base_value import NO_CONTEXTS
|
from jedi.inference.base_value import NO_CONTEXTS
|
||||||
from jedi.inference.syntax_tree import infer_atom
|
from jedi.inference.syntax_tree import infer_atom
|
||||||
from jedi.inference.helpers import infer_call_of_leaf
|
from jedi.inference.helpers import infer_call_of_leaf
|
||||||
from jedi.inference.compiled import get_string_context_set
|
from jedi.inference.compiled import get_string_value_set
|
||||||
from jedi.cache import call_signature_time_cache
|
from jedi.cache import call_signature_time_cache
|
||||||
|
|
||||||
|
|
||||||
@@ -87,7 +87,7 @@ def _get_code_for_stack(code_lines, leaf, position):
|
|||||||
if is_after_newline:
|
if is_after_newline:
|
||||||
if user_stmt.start_pos[1] > position[1]:
|
if user_stmt.start_pos[1] > position[1]:
|
||||||
# This means that it's actually a dedent and that means that we
|
# This means that it's actually a dedent and that means that we
|
||||||
# start without context (part of a suite).
|
# start without value (part of a suite).
|
||||||
return u('')
|
return u('')
|
||||||
|
|
||||||
# This is basically getting the relevant lines.
|
# This is basically getting the relevant lines.
|
||||||
@@ -136,25 +136,25 @@ def get_stack_at_position(grammar, code_lines, leaf, pos):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def infer_goto_definition(infer_state, context, leaf):
|
def infer_goto_definition(infer_state, value, leaf):
|
||||||
if leaf.type == 'name':
|
if leaf.type == 'name':
|
||||||
# In case of a name we can just use goto_definition which does all the
|
# In case of a name we can just use goto_definition which does all the
|
||||||
# magic itself.
|
# magic itself.
|
||||||
return infer_state.goto_definitions(context, leaf)
|
return infer_state.goto_definitions(value, leaf)
|
||||||
|
|
||||||
parent = leaf.parent
|
parent = leaf.parent
|
||||||
definitions = NO_CONTEXTS
|
definitions = NO_CONTEXTS
|
||||||
if parent.type == 'atom':
|
if parent.type == 'atom':
|
||||||
# e.g. `(a + b)`
|
# e.g. `(a + b)`
|
||||||
definitions = context.infer_node(leaf.parent)
|
definitions = value.infer_node(leaf.parent)
|
||||||
elif parent.type == 'trailer':
|
elif parent.type == 'trailer':
|
||||||
# e.g. `a()`
|
# e.g. `a()`
|
||||||
definitions = infer_call_of_leaf(context, leaf)
|
definitions = infer_call_of_leaf(value, leaf)
|
||||||
elif isinstance(leaf, tree.Literal):
|
elif isinstance(leaf, tree.Literal):
|
||||||
# e.g. `"foo"` or `1.0`
|
# e.g. `"foo"` or `1.0`
|
||||||
return infer_atom(context, leaf)
|
return infer_atom(value, leaf)
|
||||||
elif leaf.type in ('fstring_string', 'fstring_start', 'fstring_end'):
|
elif leaf.type in ('fstring_string', 'fstring_start', 'fstring_end'):
|
||||||
return get_string_context_set(infer_state)
|
return get_string_value_set(infer_state)
|
||||||
return definitions
|
return definitions
|
||||||
|
|
||||||
|
|
||||||
@@ -376,7 +376,7 @@ def get_call_signature_details(module, position):
|
|||||||
|
|
||||||
|
|
||||||
@call_signature_time_cache("call_signatures_validity")
|
@call_signature_time_cache("call_signatures_validity")
|
||||||
def cache_call_signatures(infer_state, context, bracket_leaf, code_lines, user_pos):
|
def cache_call_signatures(infer_state, value, bracket_leaf, code_lines, user_pos):
|
||||||
"""This function calculates the cache key."""
|
"""This function calculates the cache key."""
|
||||||
line_index = user_pos[0] - 1
|
line_index = user_pos[0] - 1
|
||||||
|
|
||||||
@@ -385,13 +385,13 @@ def cache_call_signatures(infer_state, context, bracket_leaf, code_lines, user_p
|
|||||||
whole = ''.join(other_lines + [before_cursor])
|
whole = ''.join(other_lines + [before_cursor])
|
||||||
before_bracket = re.match(r'.*\(', whole, re.DOTALL)
|
before_bracket = re.match(r'.*\(', whole, re.DOTALL)
|
||||||
|
|
||||||
module_path = context.get_root_context().py__file__()
|
module_path = value.get_root_value().py__file__()
|
||||||
if module_path is None:
|
if module_path is None:
|
||||||
yield None # Don't cache!
|
yield None # Don't cache!
|
||||||
else:
|
else:
|
||||||
yield (module_path, before_bracket, bracket_leaf.start_pos)
|
yield (module_path, before_bracket, bracket_leaf.start_pos)
|
||||||
yield infer_goto_definition(
|
yield infer_goto_definition(
|
||||||
infer_state,
|
infer_state,
|
||||||
context,
|
value,
|
||||||
bracket_leaf.get_previous_leaf(),
|
bracket_leaf.get_previous_leaf(),
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
TODO Some parts of this module are still not well documented.
|
TODO Some parts of this module are still not well documented.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from jedi.inference.context import ModuleContext
|
from jedi.inference.value import ModuleContext
|
||||||
from jedi.inference import compiled
|
from jedi.inference import compiled
|
||||||
from jedi.inference.compiled import mixed
|
from jedi.inference.compiled import mixed
|
||||||
from jedi.inference.compiled.access import create_access_path
|
from jedi.inference.compiled.access import create_access_path
|
||||||
@@ -24,24 +24,24 @@ class MixedModuleContext(ContextWrapper):
|
|||||||
type = 'mixed_module'
|
type = 'mixed_module'
|
||||||
|
|
||||||
def __init__(self, infer_state, tree_module, namespaces, file_io, code_lines):
|
def __init__(self, infer_state, tree_module, namespaces, file_io, code_lines):
|
||||||
module_context = ModuleContext(
|
module_value = ModuleContext(
|
||||||
infer_state, tree_module,
|
infer_state, tree_module,
|
||||||
file_io=file_io,
|
file_io=file_io,
|
||||||
string_names=('__main__',),
|
string_names=('__main__',),
|
||||||
code_lines=code_lines
|
code_lines=code_lines
|
||||||
)
|
)
|
||||||
super(MixedModuleContext, self).__init__(module_context)
|
super(MixedModuleContext, self).__init__(module_value)
|
||||||
self._namespace_objects = [NamespaceObject(n) for n in namespaces]
|
self._namespace_objects = [NamespaceObject(n) for n in namespaces]
|
||||||
|
|
||||||
def get_filters(self, *args, **kwargs):
|
def get_filters(self, *args, **kwargs):
|
||||||
for filter in self._wrapped_context.get_filters(*args, **kwargs):
|
for filter in self._wrapped_value.get_filters(*args, **kwargs):
|
||||||
yield filter
|
yield filter
|
||||||
|
|
||||||
for namespace_obj in self._namespace_objects:
|
for namespace_obj in self._namespace_objects:
|
||||||
compiled_object = _create(self.infer_state, namespace_obj)
|
compiled_object = _create(self.infer_state, namespace_obj)
|
||||||
mixed_object = mixed.MixedObject(
|
mixed_object = mixed.MixedObject(
|
||||||
compiled_object=compiled_object,
|
compiled_object=compiled_object,
|
||||||
tree_context=self._wrapped_context
|
tree_value=self._wrapped_value
|
||||||
)
|
)
|
||||||
for filter in mixed_object.get_filters(*args, **kwargs):
|
for filter in mixed_object.get_filters(*args, **kwargs):
|
||||||
yield filter
|
yield filter
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
from jedi.common.context import BaseContextSet, BaseContext
|
from jedi.common.value import BaseContextSet, BaseContext
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ def traverse_parents(path, include_current=False):
|
|||||||
@contextmanager
|
@contextmanager
|
||||||
def monkeypatch(obj, attribute_name, new_value):
|
def monkeypatch(obj, attribute_name, new_value):
|
||||||
"""
|
"""
|
||||||
Like pytest's monkeypatch, but as a context manager.
|
Like pytest's monkeypatch, but as a value manager.
|
||||||
"""
|
"""
|
||||||
old_value = getattr(obj, attribute_name)
|
old_value = getattr(obj, attribute_name)
|
||||||
try:
|
try:
|
||||||
|
|||||||
@@ -1,21 +1,21 @@
|
|||||||
class BaseContext(object):
|
class BaseContext(object):
|
||||||
def __init__(self, infer_state, parent_context=None):
|
def __init__(self, infer_state, parent_value=None):
|
||||||
self.infer_state = infer_state
|
self.infer_state = infer_state
|
||||||
self.parent_context = parent_context
|
self.parent_value = parent_value
|
||||||
|
|
||||||
def get_root_context(self):
|
def get_root_value(self):
|
||||||
context = self
|
value = self
|
||||||
while True:
|
while True:
|
||||||
if context.parent_context is None:
|
if value.parent_value is None:
|
||||||
return context
|
return value
|
||||||
context = context.parent_context
|
value = value.parent_value
|
||||||
|
|
||||||
|
|
||||||
class BaseContextSet(object):
|
class BaseContextSet(object):
|
||||||
def __init__(self, iterable):
|
def __init__(self, iterable):
|
||||||
self._set = frozenset(iterable)
|
self._set = frozenset(iterable)
|
||||||
for context in iterable:
|
for value in iterable:
|
||||||
assert not isinstance(context, BaseContextSet)
|
assert not isinstance(value, BaseContextSet)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _from_frozen_set(cls, frozenset_):
|
def _from_frozen_set(cls, frozenset_):
|
||||||
@@ -61,8 +61,8 @@ class BaseContextSet(object):
|
|||||||
def __getattr__(self, name):
|
def __getattr__(self, name):
|
||||||
def mapper(*args, **kwargs):
|
def mapper(*args, **kwargs):
|
||||||
return self.from_sets(
|
return self.from_sets(
|
||||||
getattr(context, name)(*args, **kwargs)
|
getattr(value, name)(*args, **kwargs)
|
||||||
for context in self._set
|
for value in self._set
|
||||||
)
|
)
|
||||||
return mapper
|
return mapper
|
||||||
|
|
||||||
+67
-67
@@ -76,10 +76,10 @@ from jedi.inference.cache import infer_state_function_cache
|
|||||||
from jedi.inference import helpers
|
from jedi.inference import helpers
|
||||||
from jedi.inference.names import TreeNameDefinition, ParamName
|
from jedi.inference.names import TreeNameDefinition, ParamName
|
||||||
from jedi.inference.base_value import ContextualizedName, ContextualizedNode, \
|
from jedi.inference.base_value import ContextualizedName, ContextualizedNode, \
|
||||||
ContextSet, NO_CONTEXTS, iterate_contexts
|
ContextSet, NO_CONTEXTS, iterate_values
|
||||||
from jedi.inference.context import ClassContext, FunctionContext, \
|
from jedi.inference.value import ClassContext, FunctionContext, \
|
||||||
AnonymousInstance, BoundMethod
|
AnonymousInstance, BoundMethod
|
||||||
from jedi.inference.context.iterable import CompForContext
|
from jedi.inference.value.iterable import CompForContext
|
||||||
from jedi.inference.syntax_tree import infer_trailer, infer_expr_stmt, \
|
from jedi.inference.syntax_tree import infer_trailer, infer_expr_stmt, \
|
||||||
infer_node, check_tuple_assignments
|
infer_node, check_tuple_assignments
|
||||||
from jedi.plugins import plugin_manager
|
from jedi.plugins import plugin_manager
|
||||||
@@ -111,21 +111,21 @@ class InferState(object):
|
|||||||
self.reset_recursion_limitations()
|
self.reset_recursion_limitations()
|
||||||
self.allow_different_encoding = True
|
self.allow_different_encoding = True
|
||||||
|
|
||||||
def import_module(self, import_names, parent_module_context=None,
|
def import_module(self, import_names, parent_module_value=None,
|
||||||
sys_path=None, prefer_stubs=True):
|
sys_path=None, prefer_stubs=True):
|
||||||
if sys_path is None:
|
if sys_path is None:
|
||||||
sys_path = self.get_sys_path()
|
sys_path = self.get_sys_path()
|
||||||
return imports.import_module(self, import_names, parent_module_context,
|
return imports.import_module(self, import_names, parent_module_value,
|
||||||
sys_path, prefer_stubs=prefer_stubs)
|
sys_path, prefer_stubs=prefer_stubs)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
@plugin_manager.decorate()
|
@plugin_manager.decorate()
|
||||||
def execute(context, arguments):
|
def execute(value, arguments):
|
||||||
debug.dbg('execute: %s %s', context, arguments)
|
debug.dbg('execute: %s %s', value, arguments)
|
||||||
with debug.increase_indent_cm():
|
with debug.increase_indent_cm():
|
||||||
context_set = context.py__call__(arguments=arguments)
|
value_set = value.py__call__(arguments=arguments)
|
||||||
debug.dbg('execute result: %s in %s', context_set, context)
|
debug.dbg('execute result: %s in %s', value_set, value)
|
||||||
return context_set
|
return value_set
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@infer_state_function_cache()
|
@infer_state_function_cache()
|
||||||
@@ -150,9 +150,9 @@ class InferState(object):
|
|||||||
"""Convenience function"""
|
"""Convenience function"""
|
||||||
return self.project._get_sys_path(self, environment=self.environment, **kwargs)
|
return self.project._get_sys_path(self, environment=self.environment, **kwargs)
|
||||||
|
|
||||||
def infer_element(self, context, element):
|
def infer_element(self, value, element):
|
||||||
if isinstance(context, CompForContext):
|
if isinstance(value, CompForContext):
|
||||||
return infer_node(context, element)
|
return infer_node(value, element)
|
||||||
|
|
||||||
if_stmt = element
|
if_stmt = element
|
||||||
while if_stmt is not None:
|
while if_stmt is not None:
|
||||||
@@ -162,7 +162,7 @@ class InferState(object):
|
|||||||
if parser_utils.is_scope(if_stmt):
|
if parser_utils.is_scope(if_stmt):
|
||||||
if_stmt = None
|
if_stmt = None
|
||||||
break
|
break
|
||||||
predefined_if_name_dict = context.predefined_names.get(if_stmt)
|
predefined_if_name_dict = value.predefined_names.get(if_stmt)
|
||||||
# TODO there's a lot of issues with this one. We actually should do
|
# TODO there's a lot of issues with this one. We actually should do
|
||||||
# this in a different way. Caching should only be active in certain
|
# this in a different way. Caching should only be active in certain
|
||||||
# cases and this all sucks.
|
# cases and this all sucks.
|
||||||
@@ -171,7 +171,7 @@ class InferState(object):
|
|||||||
if_stmt_test = if_stmt.children[1]
|
if_stmt_test = if_stmt.children[1]
|
||||||
name_dicts = [{}]
|
name_dicts = [{}]
|
||||||
# If we already did a check, we don't want to do it again -> If
|
# If we already did a check, we don't want to do it again -> If
|
||||||
# context.predefined_names is filled, we stop.
|
# value.predefined_names is filled, we stop.
|
||||||
# We don't want to check the if stmt itself, it's just about
|
# We don't want to check the if stmt itself, it's just about
|
||||||
# the content.
|
# the content.
|
||||||
if element.start_pos > if_stmt_test.end_pos:
|
if element.start_pos > if_stmt_test.end_pos:
|
||||||
@@ -182,7 +182,7 @@ class InferState(object):
|
|||||||
str_element_names = [e.value for e in element_names]
|
str_element_names = [e.value for e in element_names]
|
||||||
if any(i.value in str_element_names for i in if_names):
|
if any(i.value in str_element_names for i in if_names):
|
||||||
for if_name in if_names:
|
for if_name in if_names:
|
||||||
definitions = self.goto_definitions(context, if_name)
|
definitions = self.goto_definitions(value, if_name)
|
||||||
# Every name that has multiple different definitions
|
# Every name that has multiple different definitions
|
||||||
# causes the complexity to rise. The complexity should
|
# causes the complexity to rise. The complexity should
|
||||||
# never fall below 1.
|
# never fall below 1.
|
||||||
@@ -210,65 +210,65 @@ class InferState(object):
|
|||||||
if len(name_dicts) > 1:
|
if len(name_dicts) > 1:
|
||||||
result = NO_CONTEXTS
|
result = NO_CONTEXTS
|
||||||
for name_dict in name_dicts:
|
for name_dict in name_dicts:
|
||||||
with helpers.predefine_names(context, if_stmt, name_dict):
|
with helpers.predefine_names(value, if_stmt, name_dict):
|
||||||
result |= infer_node(context, element)
|
result |= infer_node(value, element)
|
||||||
return result
|
return result
|
||||||
else:
|
else:
|
||||||
return self._infer_element_if_inferred(context, element)
|
return self._infer_element_if_inferred(value, element)
|
||||||
else:
|
else:
|
||||||
if predefined_if_name_dict:
|
if predefined_if_name_dict:
|
||||||
return infer_node(context, element)
|
return infer_node(value, element)
|
||||||
else:
|
else:
|
||||||
return self._infer_element_if_inferred(context, element)
|
return self._infer_element_if_inferred(value, element)
|
||||||
|
|
||||||
def _infer_element_if_inferred(self, context, element):
|
def _infer_element_if_inferred(self, value, element):
|
||||||
"""
|
"""
|
||||||
TODO This function is temporary: Merge with infer_element.
|
TODO This function is temporary: Merge with infer_element.
|
||||||
"""
|
"""
|
||||||
parent = element
|
parent = element
|
||||||
while parent is not None:
|
while parent is not None:
|
||||||
parent = parent.parent
|
parent = parent.parent
|
||||||
predefined_if_name_dict = context.predefined_names.get(parent)
|
predefined_if_name_dict = value.predefined_names.get(parent)
|
||||||
if predefined_if_name_dict is not None:
|
if predefined_if_name_dict is not None:
|
||||||
return infer_node(context, element)
|
return infer_node(value, element)
|
||||||
return self._infer_element_cached(context, element)
|
return self._infer_element_cached(value, element)
|
||||||
|
|
||||||
@infer_state_function_cache(default=NO_CONTEXTS)
|
@infer_state_function_cache(default=NO_CONTEXTS)
|
||||||
def _infer_element_cached(self, context, element):
|
def _infer_element_cached(self, value, element):
|
||||||
return infer_node(context, element)
|
return infer_node(value, element)
|
||||||
|
|
||||||
def goto_definitions(self, context, name):
|
def goto_definitions(self, value, name):
|
||||||
def_ = name.get_definition(import_name_always=True)
|
def_ = name.get_definition(import_name_always=True)
|
||||||
if def_ is not None:
|
if def_ is not None:
|
||||||
type_ = def_.type
|
type_ = def_.type
|
||||||
is_classdef = type_ == 'classdef'
|
is_classdef = type_ == 'classdef'
|
||||||
if is_classdef or type_ == 'funcdef':
|
if is_classdef or type_ == 'funcdef':
|
||||||
if is_classdef:
|
if is_classdef:
|
||||||
c = ClassContext(self, context, name.parent)
|
c = ClassContext(self, value, name.parent)
|
||||||
else:
|
else:
|
||||||
c = FunctionContext.from_context(context, name.parent)
|
c = FunctionContext.from_value(value, name.parent)
|
||||||
return ContextSet([c])
|
return ContextSet([c])
|
||||||
|
|
||||||
if type_ == 'expr_stmt':
|
if type_ == 'expr_stmt':
|
||||||
is_simple_name = name.parent.type not in ('power', 'trailer')
|
is_simple_name = name.parent.type not in ('power', 'trailer')
|
||||||
if is_simple_name:
|
if is_simple_name:
|
||||||
return infer_expr_stmt(context, def_, name)
|
return infer_expr_stmt(value, def_, name)
|
||||||
if type_ == 'for_stmt':
|
if type_ == 'for_stmt':
|
||||||
container_types = context.infer_node(def_.children[3])
|
container_types = value.infer_node(def_.children[3])
|
||||||
cn = ContextualizedNode(context, def_.children[3])
|
cn = ContextualizedNode(value, def_.children[3])
|
||||||
for_types = iterate_contexts(container_types, cn)
|
for_types = iterate_values(container_types, cn)
|
||||||
c_node = ContextualizedName(context, name)
|
c_node = ContextualizedName(value, name)
|
||||||
return check_tuple_assignments(self, c_node, for_types)
|
return check_tuple_assignments(self, c_node, for_types)
|
||||||
if type_ in ('import_from', 'import_name'):
|
if type_ in ('import_from', 'import_name'):
|
||||||
return imports.infer_import(context, name)
|
return imports.infer_import(value, name)
|
||||||
else:
|
else:
|
||||||
result = self._follow_error_node_imports_if_possible(context, name)
|
result = self._follow_error_node_imports_if_possible(value, name)
|
||||||
if result is not None:
|
if result is not None:
|
||||||
return result
|
return result
|
||||||
|
|
||||||
return helpers.infer_call_of_leaf(context, name)
|
return helpers.infer_call_of_leaf(value, name)
|
||||||
|
|
||||||
def _follow_error_node_imports_if_possible(self, context, name):
|
def _follow_error_node_imports_if_possible(self, value, name):
|
||||||
error_node = tree.search_ancestor(name, 'error_node')
|
error_node = tree.search_ancestor(name, 'error_node')
|
||||||
if error_node is not None:
|
if error_node is not None:
|
||||||
# Get the first command start of a started simple_stmt. The error
|
# Get the first command start of a started simple_stmt. The error
|
||||||
@@ -292,10 +292,10 @@ class InferState(object):
|
|||||||
is_import_from=is_import_from,
|
is_import_from=is_import_from,
|
||||||
until_node=name,
|
until_node=name,
|
||||||
)
|
)
|
||||||
return imports.Importer(self, names, context.get_root_context(), level).follow()
|
return imports.Importer(self, names, value.get_root_value(), level).follow()
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def goto(self, context, name):
|
def goto(self, value, name):
|
||||||
definition = name.get_definition(import_name_always=True)
|
definition = name.get_definition(import_name_always=True)
|
||||||
if definition is not None:
|
if definition is not None:
|
||||||
type_ = definition.type
|
type_ = definition.type
|
||||||
@@ -304,18 +304,18 @@ class InferState(object):
|
|||||||
# a name it's something you can "goto" again.
|
# a name it's something you can "goto" again.
|
||||||
is_simple_name = name.parent.type not in ('power', 'trailer')
|
is_simple_name = name.parent.type not in ('power', 'trailer')
|
||||||
if is_simple_name:
|
if is_simple_name:
|
||||||
return [TreeNameDefinition(context, name)]
|
return [TreeNameDefinition(value, name)]
|
||||||
elif type_ == 'param':
|
elif type_ == 'param':
|
||||||
return [ParamName(context, name)]
|
return [ParamName(value, name)]
|
||||||
elif type_ in ('import_from', 'import_name'):
|
elif type_ in ('import_from', 'import_name'):
|
||||||
module_names = imports.infer_import(context, name, is_goto=True)
|
module_names = imports.infer_import(value, name, is_goto=True)
|
||||||
return module_names
|
return module_names
|
||||||
else:
|
else:
|
||||||
return [TreeNameDefinition(context, name)]
|
return [TreeNameDefinition(value, name)]
|
||||||
else:
|
else:
|
||||||
contexts = self._follow_error_node_imports_if_possible(context, name)
|
values = self._follow_error_node_imports_if_possible(value, name)
|
||||||
if contexts is not None:
|
if values is not None:
|
||||||
return [context.name for context in contexts]
|
return [value.name for value in values]
|
||||||
|
|
||||||
par = name.parent
|
par = name.parent
|
||||||
node_type = par.type
|
node_type = par.type
|
||||||
@@ -326,18 +326,18 @@ class InferState(object):
|
|||||||
trailer = trailer.parent
|
trailer = trailer.parent
|
||||||
if trailer.type != 'classdef':
|
if trailer.type != 'classdef':
|
||||||
if trailer.type == 'decorator':
|
if trailer.type == 'decorator':
|
||||||
context_set = context.infer_node(trailer.children[1])
|
value_set = value.infer_node(trailer.children[1])
|
||||||
else:
|
else:
|
||||||
i = trailer.parent.children.index(trailer)
|
i = trailer.parent.children.index(trailer)
|
||||||
to_infer = trailer.parent.children[:i]
|
to_infer = trailer.parent.children[:i]
|
||||||
if to_infer[0] == 'await':
|
if to_infer[0] == 'await':
|
||||||
to_infer.pop(0)
|
to_infer.pop(0)
|
||||||
context_set = context.infer_node(to_infer[0])
|
value_set = value.infer_node(to_infer[0])
|
||||||
for trailer in to_infer[1:]:
|
for trailer in to_infer[1:]:
|
||||||
context_set = infer_trailer(context, context_set, trailer)
|
value_set = infer_trailer(value, value_set, trailer)
|
||||||
param_names = []
|
param_names = []
|
||||||
for context in context_set:
|
for value in value_set:
|
||||||
for signature in context.get_signatures():
|
for signature in value.get_signatures():
|
||||||
for param_name in signature.get_param_names():
|
for param_name in signature.get_param_names():
|
||||||
if param_name.string_name == name.value:
|
if param_name.string_name == name.value:
|
||||||
param_names.append(param_name)
|
param_names.append(param_name)
|
||||||
@@ -347,28 +347,28 @@ class InferState(object):
|
|||||||
if index > 0:
|
if index > 0:
|
||||||
new_dotted = helpers.deep_ast_copy(par)
|
new_dotted = helpers.deep_ast_copy(par)
|
||||||
new_dotted.children[index - 1:] = []
|
new_dotted.children[index - 1:] = []
|
||||||
values = context.infer_node(new_dotted)
|
values = value.infer_node(new_dotted)
|
||||||
return unite(
|
return unite(
|
||||||
value.py__getattribute__(name, name_context=context, is_goto=True)
|
value.py__getattribute__(name, name_value=value, is_goto=True)
|
||||||
for value in values
|
for value in values
|
||||||
)
|
)
|
||||||
|
|
||||||
if node_type == 'trailer' and par.children[0] == '.':
|
if node_type == 'trailer' and par.children[0] == '.':
|
||||||
values = helpers.infer_call_of_leaf(context, name, cut_own_trailer=True)
|
values = helpers.infer_call_of_leaf(value, name, cut_own_trailer=True)
|
||||||
return values.py__getattribute__(name, name_context=context, is_goto=True)
|
return values.py__getattribute__(name, name_value=value, is_goto=True)
|
||||||
else:
|
else:
|
||||||
stmt = tree.search_ancestor(
|
stmt = tree.search_ancestor(
|
||||||
name, 'expr_stmt', 'lambdef'
|
name, 'expr_stmt', 'lambdef'
|
||||||
) or name
|
) or name
|
||||||
if stmt.type == 'lambdef':
|
if stmt.type == 'lambdef':
|
||||||
stmt = name
|
stmt = name
|
||||||
return context.py__getattribute__(
|
return value.py__getattribute__(
|
||||||
name,
|
name,
|
||||||
position=stmt.start_pos,
|
position=stmt.start_pos,
|
||||||
search_global=True, is_goto=True
|
search_global=True, is_goto=True
|
||||||
)
|
)
|
||||||
|
|
||||||
def create_context(self, base_value, node, node_is_context=False, node_is_object=False):
|
def create_value(self, base_value, node, node_is_value=False, node_is_object=False):
|
||||||
def parent_scope(node):
|
def parent_scope(node):
|
||||||
while True:
|
while True:
|
||||||
node = node.parent
|
node = node.parent
|
||||||
@@ -390,13 +390,13 @@ class InferState(object):
|
|||||||
|
|
||||||
is_funcdef = scope_node.type in ('funcdef', 'lambdef')
|
is_funcdef = scope_node.type in ('funcdef', 'lambdef')
|
||||||
parent_scope = parser_utils.get_parent_scope(scope_node)
|
parent_scope = parser_utils.get_parent_scope(scope_node)
|
||||||
parent_context = from_scope_node(parent_scope)
|
parent_value = from_scope_node(parent_scope)
|
||||||
|
|
||||||
if is_funcdef:
|
if is_funcdef:
|
||||||
func = FunctionContext.from_context(parent_context, scope_node)
|
func = FunctionContext.from_value(parent_value, scope_node)
|
||||||
if parent_context.is_class():
|
if parent_value.is_class():
|
||||||
instance = AnonymousInstance(
|
instance = AnonymousInstance(
|
||||||
self, parent_context.parent_context, parent_context)
|
self, parent_value.parent_value, parent_value)
|
||||||
func = BoundMethod(
|
func = BoundMethod(
|
||||||
instance=instance,
|
instance=instance,
|
||||||
function=func
|
function=func
|
||||||
@@ -406,16 +406,16 @@ class InferState(object):
|
|||||||
return func.get_function_execution()
|
return func.get_function_execution()
|
||||||
return func
|
return func
|
||||||
elif scope_node.type == 'classdef':
|
elif scope_node.type == 'classdef':
|
||||||
return ClassContext(self, parent_context, scope_node)
|
return ClassContext(self, parent_value, scope_node)
|
||||||
elif scope_node.type in ('comp_for', 'sync_comp_for'):
|
elif scope_node.type in ('comp_for', 'sync_comp_for'):
|
||||||
if node.start_pos >= scope_node.children[-1].start_pos:
|
if node.start_pos >= scope_node.children[-1].start_pos:
|
||||||
return parent_context
|
return parent_value
|
||||||
return CompForContext.from_comp_for(parent_context, scope_node)
|
return CompForContext.from_comp_for(parent_value, scope_node)
|
||||||
raise Exception("There's a scope that was not managed.")
|
raise Exception("There's a scope that was not managed.")
|
||||||
|
|
||||||
base_node = base_value.tree_node
|
base_node = base_value.tree_node
|
||||||
|
|
||||||
if node_is_context and parser_utils.is_scope(node):
|
if node_is_value and parser_utils.is_scope(node):
|
||||||
scope_node = node
|
scope_node = node
|
||||||
else:
|
else:
|
||||||
scope_node = parent_scope(node)
|
scope_node = parent_scope(node)
|
||||||
|
|||||||
+27
-27
@@ -77,17 +77,17 @@ class Warning(Error):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
def add(node_context, error_name, node, message=None, typ=Error, payload=None):
|
def add(node_value, error_name, node, message=None, typ=Error, payload=None):
|
||||||
exception = CODES[error_name][1]
|
exception = CODES[error_name][1]
|
||||||
if _check_for_exception_catch(node_context, node, exception, payload):
|
if _check_for_exception_catch(node_value, node, exception, payload):
|
||||||
return
|
return
|
||||||
|
|
||||||
# TODO this path is probably not right
|
# TODO this path is probably not right
|
||||||
module_context = node_context.get_root_context()
|
module_value = node_value.get_root_value()
|
||||||
module_path = module_context.py__file__()
|
module_path = module_value.py__file__()
|
||||||
issue_instance = typ(error_name, module_path, node.start_pos, message)
|
issue_instance = typ(error_name, module_path, node.start_pos, message)
|
||||||
debug.warning(str(issue_instance), format=False)
|
debug.warning(str(issue_instance), format=False)
|
||||||
node_context.infer_state.analysis.append(issue_instance)
|
node_value.infer_state.analysis.append(issue_instance)
|
||||||
return issue_instance
|
return issue_instance
|
||||||
|
|
||||||
|
|
||||||
@@ -95,7 +95,7 @@ def _check_for_setattr(instance):
|
|||||||
"""
|
"""
|
||||||
Check if there's any setattr method inside an instance. If so, return True.
|
Check if there's any setattr method inside an instance. If so, return True.
|
||||||
"""
|
"""
|
||||||
module = instance.get_root_context()
|
module = instance.get_root_value()
|
||||||
node = module.tree_node
|
node = module.tree_node
|
||||||
if node is None:
|
if node is None:
|
||||||
# If it's a compiled module or doesn't have a tree_node
|
# If it's a compiled module or doesn't have a tree_node
|
||||||
@@ -112,30 +112,30 @@ def _check_for_setattr(instance):
|
|||||||
for n in stmt_names)
|
for n in stmt_names)
|
||||||
|
|
||||||
|
|
||||||
def add_attribute_error(name_context, lookup_context, name):
|
def add_attribute_error(name_value, lookup_value, name):
|
||||||
message = ('AttributeError: %s has no attribute %s.' % (lookup_context, name))
|
message = ('AttributeError: %s has no attribute %s.' % (lookup_value, name))
|
||||||
from jedi.inference.context.instance import CompiledInstanceName
|
from jedi.inference.value.instance import CompiledInstanceName
|
||||||
# Check for __getattr__/__getattribute__ existance and issue a warning
|
# Check for __getattr__/__getattribute__ existance and issue a warning
|
||||||
# instead of an error, if that happens.
|
# instead of an error, if that happens.
|
||||||
typ = Error
|
typ = Error
|
||||||
if lookup_context.is_instance() and not lookup_context.is_compiled():
|
if lookup_value.is_instance() and not lookup_value.is_compiled():
|
||||||
slot_names = lookup_context.get_function_slot_names(u'__getattr__') + \
|
slot_names = lookup_value.get_function_slot_names(u'__getattr__') + \
|
||||||
lookup_context.get_function_slot_names(u'__getattribute__')
|
lookup_value.get_function_slot_names(u'__getattribute__')
|
||||||
for n in slot_names:
|
for n in slot_names:
|
||||||
# TODO do we even get here?
|
# TODO do we even get here?
|
||||||
if isinstance(name, CompiledInstanceName) and \
|
if isinstance(name, CompiledInstanceName) and \
|
||||||
n.parent_context.obj == object:
|
n.parent_value.obj == object:
|
||||||
typ = Warning
|
typ = Warning
|
||||||
break
|
break
|
||||||
|
|
||||||
if _check_for_setattr(lookup_context):
|
if _check_for_setattr(lookup_value):
|
||||||
typ = Warning
|
typ = Warning
|
||||||
|
|
||||||
payload = lookup_context, name
|
payload = lookup_value, name
|
||||||
add(name_context, 'attribute-error', name, message, typ, payload)
|
add(name_value, 'attribute-error', name, message, typ, payload)
|
||||||
|
|
||||||
|
|
||||||
def _check_for_exception_catch(node_context, jedi_name, exception, payload=None):
|
def _check_for_exception_catch(node_value, jedi_name, exception, payload=None):
|
||||||
"""
|
"""
|
||||||
Checks if a jedi object (e.g. `Statement`) sits inside a try/catch and
|
Checks if a jedi object (e.g. `Statement`) sits inside a try/catch and
|
||||||
doesn't count as an error (if equal to `exception`).
|
doesn't count as an error (if equal to `exception`).
|
||||||
@@ -149,7 +149,7 @@ def _check_for_exception_catch(node_context, jedi_name, exception, payload=None)
|
|||||||
|
|
||||||
for python_cls in exception.mro():
|
for python_cls in exception.mro():
|
||||||
if cls.py__name__() == python_cls.__name__ \
|
if cls.py__name__() == python_cls.__name__ \
|
||||||
and cls.parent_context == cls.infer_state.builtins_module:
|
and cls.parent_value == cls.infer_state.builtins_module:
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@@ -167,14 +167,14 @@ def _check_for_exception_catch(node_context, jedi_name, exception, payload=None)
|
|||||||
if node is None:
|
if node is None:
|
||||||
return True # An exception block that catches everything.
|
return True # An exception block that catches everything.
|
||||||
else:
|
else:
|
||||||
except_classes = node_context.infer_node(node)
|
except_classes = node_value.infer_node(node)
|
||||||
for cls in except_classes:
|
for cls in except_classes:
|
||||||
from jedi.inference.context import iterable
|
from jedi.inference.value import iterable
|
||||||
if isinstance(cls, iterable.Sequence) and \
|
if isinstance(cls, iterable.Sequence) and \
|
||||||
cls.array_type == 'tuple':
|
cls.array_type == 'tuple':
|
||||||
# multiple exceptions
|
# multiple exceptions
|
||||||
for lazy_context in cls.py__iter__():
|
for lazy_value in cls.py__iter__():
|
||||||
for typ in lazy_context.infer():
|
for typ in lazy_value.infer():
|
||||||
if check_match(typ, exception):
|
if check_match(typ, exception):
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
@@ -192,19 +192,19 @@ def _check_for_exception_catch(node_context, jedi_name, exception, payload=None)
|
|||||||
arglist = trailer.children[1]
|
arglist = trailer.children[1]
|
||||||
assert arglist.type == 'arglist'
|
assert arglist.type == 'arglist'
|
||||||
from jedi.inference.arguments import TreeArguments
|
from jedi.inference.arguments import TreeArguments
|
||||||
args = list(TreeArguments(node_context.infer_state, node_context, arglist).unpack())
|
args = list(TreeArguments(node_value.infer_state, node_value, arglist).unpack())
|
||||||
# Arguments should be very simple
|
# Arguments should be very simple
|
||||||
assert len(args) == 2
|
assert len(args) == 2
|
||||||
|
|
||||||
# Check name
|
# Check name
|
||||||
key, lazy_context = args[1]
|
key, lazy_value = args[1]
|
||||||
names = list(lazy_context.infer())
|
names = list(lazy_value.infer())
|
||||||
assert len(names) == 1 and is_string(names[0])
|
assert len(names) == 1 and is_string(names[0])
|
||||||
assert force_unicode(names[0].get_safe_value()) == payload[1].value
|
assert force_unicode(names[0].get_safe_value()) == payload[1].value
|
||||||
|
|
||||||
# Check objects
|
# Check objects
|
||||||
key, lazy_context = args[0]
|
key, lazy_value = args[0]
|
||||||
objects = lazy_context.infer()
|
objects = lazy_value.infer()
|
||||||
return payload[0] in objects
|
return payload[0] in objects
|
||||||
except AssertionError:
|
except AssertionError:
|
||||||
return False
|
return False
|
||||||
|
|||||||
+46
-46
@@ -6,11 +6,11 @@ from jedi._compatibility import zip_longest
|
|||||||
from jedi import debug
|
from jedi import debug
|
||||||
from jedi.inference.utils import PushBackIterator
|
from jedi.inference.utils import PushBackIterator
|
||||||
from jedi.inference import analysis
|
from jedi.inference import analysis
|
||||||
from jedi.inference.lazy_context import LazyKnownContext, LazyKnownContexts, \
|
from jedi.inference.lazy_value import LazyKnownContext, LazyKnownContexts, \
|
||||||
LazyTreeContext, get_merged_lazy_context
|
LazyTreeContext, get_merged_lazy_value
|
||||||
from jedi.inference.names import ParamName, TreeNameDefinition
|
from jedi.inference.names import ParamName, TreeNameDefinition
|
||||||
from jedi.inference.base_value import NO_CONTEXTS, ContextSet, ContextualizedNode
|
from jedi.inference.base_value import NO_CONTEXTS, ContextSet, ContextualizedNode
|
||||||
from jedi.inference.context import iterable
|
from jedi.inference.value import iterable
|
||||||
from jedi.inference.cache import infer_state_as_method_param_cache
|
from jedi.inference.cache import infer_state_as_method_param_cache
|
||||||
from jedi.inference.param import get_executed_params_and_issues, ExecutedParam
|
from jedi.inference.param import get_executed_params_and_issues, ExecutedParam
|
||||||
|
|
||||||
@@ -28,8 +28,8 @@ def try_iter_content(types, depth=0):
|
|||||||
except AttributeError:
|
except AttributeError:
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
for lazy_context in f():
|
for lazy_value in f():
|
||||||
try_iter_content(lazy_context.infer(), depth + 1)
|
try_iter_content(lazy_value.infer(), depth + 1)
|
||||||
|
|
||||||
|
|
||||||
class ParamIssue(Exception):
|
class ParamIssue(Exception):
|
||||||
@@ -50,7 +50,7 @@ def repack_with_argument_clinic(string, keep_arguments_param=False, keep_callbac
|
|||||||
clinic_args = list(_parse_argument_clinic(string))
|
clinic_args = list(_parse_argument_clinic(string))
|
||||||
|
|
||||||
def decorator(func):
|
def decorator(func):
|
||||||
def wrapper(context, *args, **kwargs):
|
def wrapper(value, *args, **kwargs):
|
||||||
if keep_arguments_param:
|
if keep_arguments_param:
|
||||||
arguments = kwargs['arguments']
|
arguments = kwargs['arguments']
|
||||||
else:
|
else:
|
||||||
@@ -59,14 +59,14 @@ def repack_with_argument_clinic(string, keep_arguments_param=False, keep_callbac
|
|||||||
kwargs.pop('callback', None)
|
kwargs.pop('callback', None)
|
||||||
try:
|
try:
|
||||||
args += tuple(_iterate_argument_clinic(
|
args += tuple(_iterate_argument_clinic(
|
||||||
context.infer_state,
|
value.infer_state,
|
||||||
arguments,
|
arguments,
|
||||||
clinic_args
|
clinic_args
|
||||||
))
|
))
|
||||||
except ParamIssue:
|
except ParamIssue:
|
||||||
return NO_CONTEXTS
|
return NO_CONTEXTS
|
||||||
else:
|
else:
|
||||||
return func(context, *args, **kwargs)
|
return func(value, *args, **kwargs)
|
||||||
|
|
||||||
return wrapper
|
return wrapper
|
||||||
return decorator
|
return decorator
|
||||||
@@ -77,15 +77,15 @@ def _iterate_argument_clinic(infer_state, arguments, parameters):
|
|||||||
iterator = PushBackIterator(arguments.unpack())
|
iterator = PushBackIterator(arguments.unpack())
|
||||||
for i, (name, optional, allow_kwargs, stars) in enumerate(parameters):
|
for i, (name, optional, allow_kwargs, stars) in enumerate(parameters):
|
||||||
if stars == 1:
|
if stars == 1:
|
||||||
lazy_contexts = []
|
lazy_values = []
|
||||||
for key, argument in iterator:
|
for key, argument in iterator:
|
||||||
if key is not None:
|
if key is not None:
|
||||||
iterator.push_back((key, argument))
|
iterator.push_back((key, argument))
|
||||||
break
|
break
|
||||||
|
|
||||||
lazy_contexts.append(argument)
|
lazy_values.append(argument)
|
||||||
yield ContextSet([iterable.FakeSequence(infer_state, u'tuple', lazy_contexts)])
|
yield ContextSet([iterable.FakeSequence(infer_state, u'tuple', lazy_values)])
|
||||||
lazy_contexts
|
lazy_values
|
||||||
continue
|
continue
|
||||||
elif stars == 2:
|
elif stars == 2:
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
@@ -98,15 +98,15 @@ def _iterate_argument_clinic(infer_state, arguments, parameters):
|
|||||||
name, len(parameters), i)
|
name, len(parameters), i)
|
||||||
raise ParamIssue
|
raise ParamIssue
|
||||||
|
|
||||||
context_set = NO_CONTEXTS if argument is None else argument.infer()
|
value_set = NO_CONTEXTS if argument is None else argument.infer()
|
||||||
|
|
||||||
if not context_set and not optional:
|
if not value_set and not optional:
|
||||||
# For the stdlib we always want values. If we don't get them,
|
# For the stdlib we always want values. If we don't get them,
|
||||||
# that's ok, maybe something is too hard to resolve, however,
|
# that's ok, maybe something is too hard to resolve, however,
|
||||||
# we will not proceed with the type inference of that function.
|
# we will not proceed with the type inference of that function.
|
||||||
debug.warning('argument_clinic "%s" not resolvable.', name)
|
debug.warning('argument_clinic "%s" not resolvable.', name)
|
||||||
raise ParamIssue
|
raise ParamIssue
|
||||||
yield context_set
|
yield value_set
|
||||||
|
|
||||||
|
|
||||||
def _parse_argument_clinic(string):
|
def _parse_argument_clinic(string):
|
||||||
@@ -137,33 +137,33 @@ class _AbstractArgumentsMixin(object):
|
|||||||
Inferes all arguments as a support for static analysis
|
Inferes all arguments as a support for static analysis
|
||||||
(normally Jedi).
|
(normally Jedi).
|
||||||
"""
|
"""
|
||||||
for key, lazy_context in self.unpack():
|
for key, lazy_value in self.unpack():
|
||||||
types = lazy_context.infer()
|
types = lazy_value.infer()
|
||||||
try_iter_content(types)
|
try_iter_content(types)
|
||||||
|
|
||||||
def unpack(self, funcdef=None):
|
def unpack(self, funcdef=None):
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
def get_executed_params_and_issues(self, execution_context):
|
def get_executed_params_and_issues(self, execution_value):
|
||||||
return get_executed_params_and_issues(execution_context, self)
|
return get_executed_params_and_issues(execution_value, self)
|
||||||
|
|
||||||
def get_calling_nodes(self):
|
def get_calling_nodes(self):
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
|
||||||
class AbstractArguments(_AbstractArgumentsMixin):
|
class AbstractArguments(_AbstractArgumentsMixin):
|
||||||
context = None
|
value = None
|
||||||
argument_node = None
|
argument_node = None
|
||||||
trailer = None
|
trailer = None
|
||||||
|
|
||||||
|
|
||||||
class AnonymousArguments(AbstractArguments):
|
class AnonymousArguments(AbstractArguments):
|
||||||
def get_executed_params_and_issues(self, execution_context):
|
def get_executed_params_and_issues(self, execution_value):
|
||||||
from jedi.inference.dynamic import search_params
|
from jedi.inference.dynamic import search_params
|
||||||
return search_params(
|
return search_params(
|
||||||
execution_context.infer_state,
|
execution_value.infer_state,
|
||||||
execution_context,
|
execution_value,
|
||||||
execution_context.tree_node
|
execution_value.tree_node
|
||||||
), []
|
), []
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
@@ -198,12 +198,12 @@ def unpack_arglist(arglist):
|
|||||||
|
|
||||||
|
|
||||||
class TreeArguments(AbstractArguments):
|
class TreeArguments(AbstractArguments):
|
||||||
def __init__(self, infer_state, context, argument_node, trailer=None):
|
def __init__(self, infer_state, value, argument_node, trailer=None):
|
||||||
"""
|
"""
|
||||||
:param argument_node: May be an argument_node or a list of nodes.
|
:param argument_node: May be an argument_node or a list of nodes.
|
||||||
"""
|
"""
|
||||||
self.argument_node = argument_node
|
self.argument_node = argument_node
|
||||||
self.context = context
|
self.value = value
|
||||||
self._infer_state = infer_state
|
self._infer_state = infer_state
|
||||||
self.trailer = trailer # Can be None, e.g. in a class definition.
|
self.trailer = trailer # Can be None, e.g. in a class definition.
|
||||||
|
|
||||||
@@ -216,25 +216,25 @@ class TreeArguments(AbstractArguments):
|
|||||||
named_args = []
|
named_args = []
|
||||||
for star_count, el in unpack_arglist(self.argument_node):
|
for star_count, el in unpack_arglist(self.argument_node):
|
||||||
if star_count == 1:
|
if star_count == 1:
|
||||||
arrays = self.context.infer_node(el)
|
arrays = self.value.infer_node(el)
|
||||||
iterators = [_iterate_star_args(self.context, a, el, funcdef)
|
iterators = [_iterate_star_args(self.value, a, el, funcdef)
|
||||||
for a in arrays]
|
for a in arrays]
|
||||||
for values in list(zip_longest(*iterators)):
|
for values in list(zip_longest(*iterators)):
|
||||||
# TODO zip_longest yields None, that means this would raise
|
# TODO zip_longest yields None, that means this would raise
|
||||||
# an exception?
|
# an exception?
|
||||||
yield None, get_merged_lazy_context(
|
yield None, get_merged_lazy_value(
|
||||||
[v for v in values if v is not None]
|
[v for v in values if v is not None]
|
||||||
)
|
)
|
||||||
elif star_count == 2:
|
elif star_count == 2:
|
||||||
arrays = self.context.infer_node(el)
|
arrays = self.value.infer_node(el)
|
||||||
for dct in arrays:
|
for dct in arrays:
|
||||||
for key, values in _star_star_dict(self.context, dct, el, funcdef):
|
for key, values in _star_star_dict(self.value, dct, el, funcdef):
|
||||||
yield key, values
|
yield key, values
|
||||||
else:
|
else:
|
||||||
if el.type == 'argument':
|
if el.type == 'argument':
|
||||||
c = el.children
|
c = el.children
|
||||||
if len(c) == 3: # Keyword argument.
|
if len(c) == 3: # Keyword argument.
|
||||||
named_args.append((c[0].value, LazyTreeContext(self.context, c[2]),))
|
named_args.append((c[0].value, LazyTreeContext(self.value, c[2]),))
|
||||||
else: # Generator comprehension.
|
else: # Generator comprehension.
|
||||||
# Include the brackets with the parent.
|
# Include the brackets with the parent.
|
||||||
sync_comp_for = el.children[1]
|
sync_comp_for = el.children[1]
|
||||||
@@ -242,13 +242,13 @@ class TreeArguments(AbstractArguments):
|
|||||||
sync_comp_for = sync_comp_for.children[1]
|
sync_comp_for = sync_comp_for.children[1]
|
||||||
comp = iterable.GeneratorComprehension(
|
comp = iterable.GeneratorComprehension(
|
||||||
self._infer_state,
|
self._infer_state,
|
||||||
defining_context=self.context,
|
defining_value=self.value,
|
||||||
sync_comp_for_node=sync_comp_for,
|
sync_comp_for_node=sync_comp_for,
|
||||||
entry_node=el.children[0],
|
entry_node=el.children[0],
|
||||||
)
|
)
|
||||||
yield None, LazyKnownContext(comp)
|
yield None, LazyKnownContext(comp)
|
||||||
else:
|
else:
|
||||||
yield None, LazyTreeContext(self.context, el)
|
yield None, LazyTreeContext(self.value, el)
|
||||||
|
|
||||||
# Reordering arguments is necessary, because star args sometimes appear
|
# Reordering arguments is necessary, because star args sometimes appear
|
||||||
# after named argument, but in the actual order it's prepended.
|
# after named argument, but in the actual order it's prepended.
|
||||||
@@ -269,7 +269,7 @@ class TreeArguments(AbstractArguments):
|
|||||||
if not star_count or not isinstance(name, tree.Name):
|
if not star_count or not isinstance(name, tree.Name):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
yield TreeNameDefinition(self.context, name)
|
yield TreeNameDefinition(self.value, name)
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return '<%s: %s>' % (self.__class__.__name__, self.argument_node)
|
return '<%s: %s>' % (self.__class__.__name__, self.argument_node)
|
||||||
@@ -302,9 +302,9 @@ class TreeArguments(AbstractArguments):
|
|||||||
break
|
break
|
||||||
|
|
||||||
if arguments.argument_node is not None:
|
if arguments.argument_node is not None:
|
||||||
return [ContextualizedNode(arguments.context, arguments.argument_node)]
|
return [ContextualizedNode(arguments.value, arguments.argument_node)]
|
||||||
if arguments.trailer is not None:
|
if arguments.trailer is not None:
|
||||||
return [ContextualizedNode(arguments.context, arguments.trailer)]
|
return [ContextualizedNode(arguments.value, arguments.trailer)]
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
|
||||||
@@ -325,8 +325,8 @@ class TreeArgumentsWrapper(_AbstractArgumentsMixin):
|
|||||||
self._wrapped_arguments = arguments
|
self._wrapped_arguments = arguments
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def context(self):
|
def value(self):
|
||||||
return self._wrapped_arguments.context
|
return self._wrapped_arguments.value
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def argument_node(self):
|
def argument_node(self):
|
||||||
@@ -346,24 +346,24 @@ class TreeArgumentsWrapper(_AbstractArgumentsMixin):
|
|||||||
return '<%s: %s>' % (self.__class__.__name__, self._wrapped_arguments)
|
return '<%s: %s>' % (self.__class__.__name__, self._wrapped_arguments)
|
||||||
|
|
||||||
|
|
||||||
def _iterate_star_args(context, array, input_node, funcdef=None):
|
def _iterate_star_args(value, array, input_node, funcdef=None):
|
||||||
if not array.py__getattribute__('__iter__'):
|
if not array.py__getattribute__('__iter__'):
|
||||||
if funcdef is not None:
|
if funcdef is not None:
|
||||||
# TODO this funcdef should not be needed.
|
# TODO this funcdef should not be needed.
|
||||||
m = "TypeError: %s() argument after * must be a sequence, not %s" \
|
m = "TypeError: %s() argument after * must be a sequence, not %s" \
|
||||||
% (funcdef.name.value, array)
|
% (funcdef.name.value, array)
|
||||||
analysis.add(context, 'type-error-star', input_node, message=m)
|
analysis.add(value, 'type-error-star', input_node, message=m)
|
||||||
try:
|
try:
|
||||||
iter_ = array.py__iter__
|
iter_ = array.py__iter__
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
for lazy_context in iter_():
|
for lazy_value in iter_():
|
||||||
yield lazy_context
|
yield lazy_value
|
||||||
|
|
||||||
|
|
||||||
def _star_star_dict(context, array, input_node, funcdef):
|
def _star_star_dict(value, array, input_node, funcdef):
|
||||||
from jedi.inference.context.instance import CompiledInstance
|
from jedi.inference.value.instance import CompiledInstance
|
||||||
if isinstance(array, CompiledInstance) and array.name.string_name == 'dict':
|
if isinstance(array, CompiledInstance) and array.name.string_name == 'dict':
|
||||||
# For now ignore this case. In the future add proper iterators and just
|
# For now ignore this case. In the future add proper iterators and just
|
||||||
# make one call without crazy isinstance checks.
|
# make one call without crazy isinstance checks.
|
||||||
@@ -374,5 +374,5 @@ def _star_star_dict(context, array, input_node, funcdef):
|
|||||||
if funcdef is not None:
|
if funcdef is not None:
|
||||||
m = "TypeError: %s argument after ** must be a mapping, not %s" \
|
m = "TypeError: %s argument after ** must be a mapping, not %s" \
|
||||||
% (funcdef.name.value, array)
|
% (funcdef.name.value, array)
|
||||||
analysis.add(context, 'type-error-star-star', input_node, message=m)
|
analysis.add(value, 'type-error-star-star', input_node, message=m)
|
||||||
return {}
|
return {}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
"""
|
"""
|
||||||
Contexts are the "values" that Python would return. However Contexts are at the
|
Contexts are the "values" that Python would return. However Contexts are at the
|
||||||
same time also the "contexts" that a user is currently sitting in.
|
same time also the "values" that a user is currently sitting in.
|
||||||
|
|
||||||
A ContextSet is typically used to specify the return of a function or any other
|
A ContextSet is typically used to specify the return of a function or any other
|
||||||
static analysis operation. In jedi there are always multiple returns and not
|
static analysis operation. In jedi there are always multiple returns and not
|
||||||
@@ -23,12 +23,12 @@ _sentinel = object()
|
|||||||
|
|
||||||
|
|
||||||
class HelperContextMixin(object):
|
class HelperContextMixin(object):
|
||||||
def get_root_context(self):
|
def get_root_value(self):
|
||||||
context = self
|
value = self
|
||||||
while True:
|
while True:
|
||||||
if context.parent_context is None:
|
if value.parent_value is None:
|
||||||
return context
|
return value
|
||||||
context = context.parent_context
|
value = value.parent_value
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@infer_state_as_method_param_cache()
|
@infer_state_as_method_param_cache()
|
||||||
@@ -49,22 +49,22 @@ class HelperContextMixin(object):
|
|||||||
def gather_annotation_classes(self):
|
def gather_annotation_classes(self):
|
||||||
return ContextSet([self])
|
return ContextSet([self])
|
||||||
|
|
||||||
def merge_types_of_iterate(self, contextualized_node=None, is_async=False):
|
def merge_types_of_iterate(self, valueualized_node=None, is_async=False):
|
||||||
return ContextSet.from_sets(
|
return ContextSet.from_sets(
|
||||||
lazy_context.infer()
|
lazy_value.infer()
|
||||||
for lazy_context in self.iterate(contextualized_node, is_async)
|
for lazy_value in self.iterate(valueualized_node, is_async)
|
||||||
)
|
)
|
||||||
|
|
||||||
def py__getattribute__(self, name_or_str, name_context=None, position=None,
|
def py__getattribute__(self, name_or_str, name_value=None, position=None,
|
||||||
search_global=False, is_goto=False,
|
search_global=False, is_goto=False,
|
||||||
analysis_errors=True):
|
analysis_errors=True):
|
||||||
"""
|
"""
|
||||||
:param position: Position of the last statement -> tuple of line, column
|
:param position: Position of the last statement -> tuple of line, column
|
||||||
"""
|
"""
|
||||||
if name_context is None:
|
if name_value is None:
|
||||||
name_context = self
|
name_value = self
|
||||||
from jedi.inference import finder
|
from jedi.inference import finder
|
||||||
f = finder.NameFinder(self.infer_state, self, name_context, name_or_str,
|
f = finder.NameFinder(self.infer_state, self, name_value, name_or_str,
|
||||||
position, analysis_errors=analysis_errors)
|
position, analysis_errors=analysis_errors)
|
||||||
filters = f.get_filters(search_global)
|
filters = f.get_filters(search_global)
|
||||||
if is_goto:
|
if is_goto:
|
||||||
@@ -72,22 +72,22 @@ class HelperContextMixin(object):
|
|||||||
return f.find(filters, attribute_lookup=not search_global)
|
return f.find(filters, attribute_lookup=not search_global)
|
||||||
|
|
||||||
def py__await__(self):
|
def py__await__(self):
|
||||||
await_context_set = self.py__getattribute__(u"__await__")
|
await_value_set = self.py__getattribute__(u"__await__")
|
||||||
if not await_context_set:
|
if not await_value_set:
|
||||||
debug.warning('Tried to run __await__ on context %s', self)
|
debug.warning('Tried to run __await__ on value %s', self)
|
||||||
return await_context_set.execute_with_values()
|
return await_value_set.execute_with_values()
|
||||||
|
|
||||||
def infer_node(self, node):
|
def infer_node(self, node):
|
||||||
return self.infer_state.infer_element(self, node)
|
return self.infer_state.infer_element(self, node)
|
||||||
|
|
||||||
def create_context(self, node, node_is_context=False, node_is_object=False):
|
def create_value(self, node, node_is_value=False, node_is_object=False):
|
||||||
return self.infer_state.create_context(self, node, node_is_context, node_is_object)
|
return self.infer_state.create_value(self, node, node_is_value, node_is_object)
|
||||||
|
|
||||||
def iterate(self, contextualized_node=None, is_async=False):
|
def iterate(self, valueualized_node=None, is_async=False):
|
||||||
debug.dbg('iterate %s', self)
|
debug.dbg('iterate %s', self)
|
||||||
if is_async:
|
if is_async:
|
||||||
from jedi.inference.lazy_context import LazyKnownContexts
|
from jedi.inference.lazy_value import LazyKnownContexts
|
||||||
# TODO if no __aiter__ contexts are there, error should be:
|
# TODO if no __aiter__ values are there, error should be:
|
||||||
# TypeError: 'async for' requires an object with __aiter__ method, got int
|
# TypeError: 'async for' requires an object with __aiter__ method, got int
|
||||||
return iter([
|
return iter([
|
||||||
LazyKnownContexts(
|
LazyKnownContexts(
|
||||||
@@ -97,11 +97,11 @@ class HelperContextMixin(object):
|
|||||||
.py__stop_iteration_returns()
|
.py__stop_iteration_returns()
|
||||||
) # noqa
|
) # noqa
|
||||||
])
|
])
|
||||||
return self.py__iter__(contextualized_node)
|
return self.py__iter__(valueualized_node)
|
||||||
|
|
||||||
def is_sub_class_of(self, class_context):
|
def is_sub_class_of(self, class_value):
|
||||||
for cls in self.py__mro__():
|
for cls in self.py__mro__():
|
||||||
if cls.is_same_class(class_context):
|
if cls.is_same_class(class_value):
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@@ -128,24 +128,24 @@ class Context(HelperContextMixin, BaseContext):
|
|||||||
# overwritten.
|
# overwritten.
|
||||||
return self.__class__.__name__.lower()
|
return self.__class__.__name__.lower()
|
||||||
|
|
||||||
def py__getitem__(self, index_context_set, contextualized_node):
|
def py__getitem__(self, index_value_set, valueualized_node):
|
||||||
from jedi.inference import analysis
|
from jedi.inference import analysis
|
||||||
# TODO this context is probably not right.
|
# TODO this value is probably not right.
|
||||||
analysis.add(
|
analysis.add(
|
||||||
contextualized_node.context,
|
valueualized_node.value,
|
||||||
'type-error-not-subscriptable',
|
'type-error-not-subscriptable',
|
||||||
contextualized_node.node,
|
valueualized_node.node,
|
||||||
message="TypeError: '%s' object is not subscriptable" % self
|
message="TypeError: '%s' object is not subscriptable" % self
|
||||||
)
|
)
|
||||||
return NO_CONTEXTS
|
return NO_CONTEXTS
|
||||||
|
|
||||||
def py__iter__(self, contextualized_node=None):
|
def py__iter__(self, valueualized_node=None):
|
||||||
if contextualized_node is not None:
|
if valueualized_node is not None:
|
||||||
from jedi.inference import analysis
|
from jedi.inference import analysis
|
||||||
analysis.add(
|
analysis.add(
|
||||||
contextualized_node.context,
|
valueualized_node.value,
|
||||||
'type-error-not-iterable',
|
'type-error-not-iterable',
|
||||||
contextualized_node.node,
|
valueualized_node.node,
|
||||||
message="TypeError: '%s' object is not iterable" % self)
|
message="TypeError: '%s' object is not iterable" % self)
|
||||||
return iter([])
|
return iter([])
|
||||||
|
|
||||||
@@ -191,7 +191,7 @@ class Context(HelperContextMixin, BaseContext):
|
|||||||
|
|
||||||
def get_safe_value(self, default=_sentinel):
|
def get_safe_value(self, default=_sentinel):
|
||||||
if default is _sentinel:
|
if default is _sentinel:
|
||||||
raise ValueError("There exists no safe value for context %s" % self)
|
raise ValueError("There exists no safe value for value %s" % self)
|
||||||
return default
|
return default
|
||||||
|
|
||||||
def py__call__(self, arguments):
|
def py__call__(self, arguments):
|
||||||
@@ -207,18 +207,18 @@ class Context(HelperContextMixin, BaseContext):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
def is_stub(self):
|
def is_stub(self):
|
||||||
# The root context knows if it's a stub or not.
|
# The root value knows if it's a stub or not.
|
||||||
return self.parent_context.is_stub()
|
return self.parent_value.is_stub()
|
||||||
|
|
||||||
|
|
||||||
def iterate_contexts(contexts, contextualized_node=None, is_async=False):
|
def iterate_values(values, valueualized_node=None, is_async=False):
|
||||||
"""
|
"""
|
||||||
Calls `iterate`, on all contexts but ignores the ordering and just returns
|
Calls `iterate`, on all values but ignores the ordering and just returns
|
||||||
all contexts that the iterate functions yield.
|
all values that the iterate functions yield.
|
||||||
"""
|
"""
|
||||||
return ContextSet.from_sets(
|
return ContextSet.from_sets(
|
||||||
lazy_context.infer()
|
lazy_value.infer()
|
||||||
for lazy_context in contexts.iterate(contextualized_node, is_async=is_async)
|
for lazy_value in values.iterate(valueualized_node, is_async=is_async)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -228,7 +228,7 @@ class _ContextWrapperBase(HelperContextMixin):
|
|||||||
@safe_property
|
@safe_property
|
||||||
def name(self):
|
def name(self):
|
||||||
from jedi.inference.names import ContextName
|
from jedi.inference.names import ContextName
|
||||||
wrapped_name = self._wrapped_context.name
|
wrapped_name = self._wrapped_value.name
|
||||||
if wrapped_name.tree_name is not None:
|
if wrapped_name.tree_name is not None:
|
||||||
return ContextName(self, wrapped_name.tree_name)
|
return ContextName(self, wrapped_name.tree_name)
|
||||||
else:
|
else:
|
||||||
@@ -241,35 +241,35 @@ class _ContextWrapperBase(HelperContextMixin):
|
|||||||
return cls(*args, **kwargs)
|
return cls(*args, **kwargs)
|
||||||
|
|
||||||
def __getattr__(self, name):
|
def __getattr__(self, name):
|
||||||
assert name != '_wrapped_context', 'Problem with _get_wrapped_context'
|
assert name != '_wrapped_value', 'Problem with _get_wrapped_value'
|
||||||
return getattr(self._wrapped_context, name)
|
return getattr(self._wrapped_value, name)
|
||||||
|
|
||||||
|
|
||||||
class LazyContextWrapper(_ContextWrapperBase):
|
class LazyContextWrapper(_ContextWrapperBase):
|
||||||
@safe_property
|
@safe_property
|
||||||
@memoize_method
|
@memoize_method
|
||||||
def _wrapped_context(self):
|
def _wrapped_value(self):
|
||||||
with debug.increase_indent_cm('Resolve lazy context wrapper'):
|
with debug.increase_indent_cm('Resolve lazy value wrapper'):
|
||||||
return self._get_wrapped_context()
|
return self._get_wrapped_value()
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return '<%s>' % (self.__class__.__name__)
|
return '<%s>' % (self.__class__.__name__)
|
||||||
|
|
||||||
def _get_wrapped_context(self):
|
def _get_wrapped_value(self):
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
|
|
||||||
class ContextWrapper(_ContextWrapperBase):
|
class ContextWrapper(_ContextWrapperBase):
|
||||||
def __init__(self, wrapped_context):
|
def __init__(self, wrapped_value):
|
||||||
self._wrapped_context = wrapped_context
|
self._wrapped_value = wrapped_value
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return '%s(%s)' % (self.__class__.__name__, self._wrapped_context)
|
return '%s(%s)' % (self.__class__.__name__, self._wrapped_value)
|
||||||
|
|
||||||
|
|
||||||
class TreeContext(Context):
|
class TreeContext(Context):
|
||||||
def __init__(self, infer_state, parent_context, tree_node):
|
def __init__(self, infer_state, parent_value, tree_node):
|
||||||
super(TreeContext, self).__init__(infer_state, parent_context)
|
super(TreeContext, self).__init__(infer_state, parent_value)
|
||||||
self.predefined_names = {}
|
self.predefined_names = {}
|
||||||
self.tree_node = tree_node
|
self.tree_node = tree_node
|
||||||
|
|
||||||
@@ -278,18 +278,18 @@ class TreeContext(Context):
|
|||||||
|
|
||||||
|
|
||||||
class ContextualizedNode(object):
|
class ContextualizedNode(object):
|
||||||
def __init__(self, context, node):
|
def __init__(self, value, node):
|
||||||
self.context = context
|
self.value = value
|
||||||
self.node = node
|
self.node = node
|
||||||
|
|
||||||
def get_root_context(self):
|
def get_root_value(self):
|
||||||
return self.context.get_root_context()
|
return self.value.get_root_value()
|
||||||
|
|
||||||
def infer(self):
|
def infer(self):
|
||||||
return self.context.infer_node(self.node)
|
return self.value.infer_node(self.node)
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return '<%s: %s in %s>' % (self.__class__.__name__, self.node, self.context)
|
return '<%s: %s in %s>' % (self.__class__.__name__, self.node, self.value)
|
||||||
|
|
||||||
|
|
||||||
class ContextualizedName(ContextualizedNode):
|
class ContextualizedName(ContextualizedNode):
|
||||||
@@ -340,18 +340,18 @@ class ContextualizedName(ContextualizedNode):
|
|||||||
return indexes
|
return indexes
|
||||||
|
|
||||||
|
|
||||||
def _getitem(context, index_contexts, contextualized_node):
|
def _getitem(value, index_values, valueualized_node):
|
||||||
from jedi.inference.context.iterable import Slice
|
from jedi.inference.value.iterable import Slice
|
||||||
|
|
||||||
# The actual getitem call.
|
# The actual getitem call.
|
||||||
simple_getitem = getattr(context, 'py__simple_getitem__', None)
|
simple_getitem = getattr(value, 'py__simple_getitem__', None)
|
||||||
|
|
||||||
result = NO_CONTEXTS
|
result = NO_CONTEXTS
|
||||||
unused_contexts = set()
|
unused_values = set()
|
||||||
for index_context in index_contexts:
|
for index_value in index_values:
|
||||||
if simple_getitem is not None:
|
if simple_getitem is not None:
|
||||||
index = index_context
|
index = index_value
|
||||||
if isinstance(index_context, Slice):
|
if isinstance(index_value, Slice):
|
||||||
index = index.obj
|
index = index.obj
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@@ -368,15 +368,15 @@ def _getitem(context, index_contexts, contextualized_node):
|
|||||||
except SimpleGetItemNotFound:
|
except SimpleGetItemNotFound:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
unused_contexts.add(index_context)
|
unused_values.add(index_value)
|
||||||
|
|
||||||
# The index was somehow not good enough or simply a wrong type.
|
# The index was somehow not good enough or simply a wrong type.
|
||||||
# Therefore we now iterate through all the contexts and just take
|
# Therefore we now iterate through all the values and just take
|
||||||
# all results.
|
# all results.
|
||||||
if unused_contexts or not index_contexts:
|
if unused_values or not index_values:
|
||||||
result |= context.py__getitem__(
|
result |= value.py__getitem__(
|
||||||
ContextSet(unused_contexts),
|
ContextSet(unused_values),
|
||||||
contextualized_node
|
valueualized_node
|
||||||
)
|
)
|
||||||
debug.dbg('py__getitem__ result: %s', result)
|
debug.dbg('py__getitem__ result: %s', result)
|
||||||
return result
|
return result
|
||||||
@@ -386,12 +386,12 @@ class ContextSet(BaseContextSet):
|
|||||||
def py__class__(self):
|
def py__class__(self):
|
||||||
return ContextSet(c.py__class__() for c in self._set)
|
return ContextSet(c.py__class__() for c in self._set)
|
||||||
|
|
||||||
def iterate(self, contextualized_node=None, is_async=False):
|
def iterate(self, valueualized_node=None, is_async=False):
|
||||||
from jedi.inference.lazy_context import get_merged_lazy_context
|
from jedi.inference.lazy_value import get_merged_lazy_value
|
||||||
type_iters = [c.iterate(contextualized_node, is_async=is_async) for c in self._set]
|
type_iters = [c.iterate(valueualized_node, is_async=is_async) for c in self._set]
|
||||||
for lazy_contexts in zip_longest(*type_iters):
|
for lazy_values in zip_longest(*type_iters):
|
||||||
yield get_merged_lazy_context(
|
yield get_merged_lazy_value(
|
||||||
[l for l in lazy_contexts if l is not None]
|
[l for l in lazy_values if l is not None]
|
||||||
)
|
)
|
||||||
|
|
||||||
def execute(self, arguments):
|
def execute(self, arguments):
|
||||||
@@ -409,15 +409,15 @@ class ContextSet(BaseContextSet):
|
|||||||
return ContextSet.from_sets(_getitem(c, *args, **kwargs) for c in self._set)
|
return ContextSet.from_sets(_getitem(c, *args, **kwargs) for c in self._set)
|
||||||
|
|
||||||
def try_merge(self, function_name):
|
def try_merge(self, function_name):
|
||||||
context_set = self.__class__([])
|
value_set = self.__class__([])
|
||||||
for c in self._set:
|
for c in self._set:
|
||||||
try:
|
try:
|
||||||
method = getattr(c, function_name)
|
method = getattr(c, function_name)
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
context_set |= method()
|
value_set |= method()
|
||||||
return context_set
|
return value_set
|
||||||
|
|
||||||
def gather_annotation_classes(self):
|
def gather_annotation_classes(self):
|
||||||
return ContextSet.from_sets([c.gather_annotation_classes() for c in self._set])
|
return ContextSet.from_sets([c.gather_annotation_classes() for c in self._set])
|
||||||
@@ -429,7 +429,7 @@ class ContextSet(BaseContextSet):
|
|||||||
NO_CONTEXTS = ContextSet([])
|
NO_CONTEXTS = ContextSet([])
|
||||||
|
|
||||||
|
|
||||||
def iterator_to_context_set(func):
|
def iterator_to_value_set(func):
|
||||||
def wrapper(*args, **kwargs):
|
def wrapper(*args, **kwargs):
|
||||||
return ContextSet(func(*args, **kwargs))
|
return ContextSet(func(*args, **kwargs))
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
from jedi._compatibility import unicode
|
from jedi._compatibility import unicode
|
||||||
from jedi.inference.compiled.context import CompiledObject, CompiledName, \
|
from jedi.inference.compiled.value import CompiledObject, CompiledName, \
|
||||||
CompiledObjectFilter, CompiledContextName, create_from_access_path
|
CompiledObjectFilter, CompiledContextName, create_from_access_path
|
||||||
from jedi.inference.base_value import ContextWrapper, LazyContextWrapper
|
from jedi.inference.base_value import ContextWrapper, LazyContextWrapper
|
||||||
|
|
||||||
@@ -7,13 +7,13 @@ from jedi.inference.base_value import ContextWrapper, LazyContextWrapper
|
|||||||
def builtin_from_name(infer_state, string):
|
def builtin_from_name(infer_state, string):
|
||||||
typing_builtins_module = infer_state.builtins_module
|
typing_builtins_module = infer_state.builtins_module
|
||||||
if string in ('None', 'True', 'False'):
|
if string in ('None', 'True', 'False'):
|
||||||
builtins, = typing_builtins_module.non_stub_context_set
|
builtins, = typing_builtins_module.non_stub_value_set
|
||||||
filter_ = next(builtins.get_filters())
|
filter_ = next(builtins.get_filters())
|
||||||
else:
|
else:
|
||||||
filter_ = next(typing_builtins_module.get_filters())
|
filter_ = next(typing_builtins_module.get_filters())
|
||||||
name, = filter_.get(string)
|
name, = filter_.get(string)
|
||||||
context, = name.infer()
|
value, = name.infer()
|
||||||
return context
|
return value
|
||||||
|
|
||||||
|
|
||||||
class CompiledValue(LazyContextWrapper):
|
class CompiledValue(LazyContextWrapper):
|
||||||
@@ -27,7 +27,7 @@ class CompiledValue(LazyContextWrapper):
|
|||||||
return getattr(self._compiled_obj, name)
|
return getattr(self._compiled_obj, name)
|
||||||
return super(CompiledValue, self).__getattribute__(name)
|
return super(CompiledValue, self).__getattribute__(name)
|
||||||
|
|
||||||
def _get_wrapped_context(self):
|
def _get_wrapped_value(self):
|
||||||
instance, = builtin_from_name(
|
instance, = builtin_from_name(
|
||||||
self.infer_state, self._compiled_obj.name.string_name).execute_with_values()
|
self.infer_state, self._compiled_obj.name.string_name).execute_with_values()
|
||||||
return instance
|
return instance
|
||||||
@@ -49,7 +49,7 @@ def create_simple_object(infer_state, obj):
|
|||||||
return CompiledValue(compiled_obj)
|
return CompiledValue(compiled_obj)
|
||||||
|
|
||||||
|
|
||||||
def get_string_context_set(infer_state):
|
def get_string_value_set(infer_state):
|
||||||
return builtin_from_name(infer_state, u'str').execute_with_values()
|
return builtin_from_name(infer_state, u'str').execute_with_values()
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -109,7 +109,7 @@ def compiled_objects_cache(attribute_name):
|
|||||||
Caching the id has the advantage that an object doesn't need to be
|
Caching the id has the advantage that an object doesn't need to be
|
||||||
hashable.
|
hashable.
|
||||||
"""
|
"""
|
||||||
def wrapper(infer_state, obj, parent_context=None):
|
def wrapper(infer_state, obj, parent_value=None):
|
||||||
cache = getattr(infer_state, attribute_name)
|
cache = getattr(infer_state, attribute_name)
|
||||||
# Do a very cheap form of caching here.
|
# Do a very cheap form of caching here.
|
||||||
key = id(obj)
|
key = id(obj)
|
||||||
@@ -119,11 +119,11 @@ def compiled_objects_cache(attribute_name):
|
|||||||
except KeyError:
|
except KeyError:
|
||||||
# TODO wuaaaarrghhhhhhhh
|
# TODO wuaaaarrghhhhhhhh
|
||||||
if attribute_name == 'mixed_cache':
|
if attribute_name == 'mixed_cache':
|
||||||
result = func(infer_state, obj, parent_context)
|
result = func(infer_state, obj, parent_value)
|
||||||
else:
|
else:
|
||||||
result = func(infer_state, obj)
|
result = func(infer_state, obj)
|
||||||
# Need to cache all of them, otherwise the id could be overwritten.
|
# Need to cache all of them, otherwise the id could be overwritten.
|
||||||
cache[key] = result, obj, parent_context
|
cache[key] = result, obj, parent_value
|
||||||
return result
|
return result
|
||||||
return wrapper
|
return wrapper
|
||||||
|
|
||||||
|
|||||||
@@ -14,12 +14,12 @@ from jedi.cache import underscore_memoization
|
|||||||
from jedi.file_io import FileIO
|
from jedi.file_io import FileIO
|
||||||
from jedi.inference.base_value import ContextSet, ContextWrapper
|
from jedi.inference.base_value import ContextSet, ContextWrapper
|
||||||
from jedi.inference.helpers import SimpleGetItemNotFound
|
from jedi.inference.helpers import SimpleGetItemNotFound
|
||||||
from jedi.inference.context import ModuleContext
|
from jedi.inference.value import ModuleContext
|
||||||
from jedi.inference.cache import infer_state_function_cache
|
from jedi.inference.cache import infer_state_function_cache
|
||||||
from jedi.inference.compiled.getattr_static import getattr_static
|
from jedi.inference.compiled.getattr_static import getattr_static
|
||||||
from jedi.inference.compiled.access import compiled_objects_cache, \
|
from jedi.inference.compiled.access import compiled_objects_cache, \
|
||||||
ALLOWED_GETITEM_TYPES, get_api_type
|
ALLOWED_GETITEM_TYPES, get_api_type
|
||||||
from jedi.inference.compiled.context import create_cached_compiled_object
|
from jedi.inference.compiled.value import create_cached_compiled_object
|
||||||
from jedi.inference.gradual.conversion import to_stub
|
from jedi.inference.gradual.conversion import to_stub
|
||||||
|
|
||||||
_sentinel = object()
|
_sentinel = object()
|
||||||
@@ -42,8 +42,8 @@ class MixedObject(ContextWrapper):
|
|||||||
fewer special cases, because we in Python you don't have the same freedoms
|
fewer special cases, because we in Python you don't have the same freedoms
|
||||||
to modify the runtime.
|
to modify the runtime.
|
||||||
"""
|
"""
|
||||||
def __init__(self, compiled_object, tree_context):
|
def __init__(self, compiled_object, tree_value):
|
||||||
super(MixedObject, self).__init__(tree_context)
|
super(MixedObject, self).__init__(tree_value)
|
||||||
self.compiled_object = compiled_object
|
self.compiled_object = compiled_object
|
||||||
self.access_handle = compiled_object.access_handle
|
self.access_handle = compiled_object.access_handle
|
||||||
|
|
||||||
@@ -56,7 +56,7 @@ class MixedObject(ContextWrapper):
|
|||||||
return self.compiled_object.get_signatures()
|
return self.compiled_object.get_signatures()
|
||||||
|
|
||||||
def py__call__(self, arguments):
|
def py__call__(self, arguments):
|
||||||
return (to_stub(self._wrapped_context) or self._wrapped_context).py__call__(arguments)
|
return (to_stub(self._wrapped_value) or self._wrapped_value).py__call__(arguments)
|
||||||
|
|
||||||
def get_safe_value(self, default=_sentinel):
|
def get_safe_value(self, default=_sentinel):
|
||||||
if default is _sentinel:
|
if default is _sentinel:
|
||||||
@@ -83,11 +83,11 @@ class MixedName(compiled.CompiledName):
|
|||||||
"""
|
"""
|
||||||
@property
|
@property
|
||||||
def start_pos(self):
|
def start_pos(self):
|
||||||
contexts = list(self.infer())
|
values = list(self.infer())
|
||||||
if not contexts:
|
if not values:
|
||||||
# This means a start_pos that doesn't exist (compiled objects).
|
# This means a start_pos that doesn't exist (compiled objects).
|
||||||
return 0, 0
|
return 0, 0
|
||||||
return contexts[0].name.start_pos
|
return values[0].name.start_pos
|
||||||
|
|
||||||
@start_pos.setter
|
@start_pos.setter
|
||||||
def start_pos(self, value):
|
def start_pos(self, value):
|
||||||
@@ -97,20 +97,20 @@ class MixedName(compiled.CompiledName):
|
|||||||
@underscore_memoization
|
@underscore_memoization
|
||||||
def infer(self):
|
def infer(self):
|
||||||
# TODO use logic from compiled.CompiledObjectFilter
|
# TODO use logic from compiled.CompiledObjectFilter
|
||||||
access_paths = self.parent_context.access_handle.getattr_paths(
|
access_paths = self.parent_value.access_handle.getattr_paths(
|
||||||
self.string_name,
|
self.string_name,
|
||||||
default=None
|
default=None
|
||||||
)
|
)
|
||||||
assert len(access_paths)
|
assert len(access_paths)
|
||||||
contexts = [None]
|
values = [None]
|
||||||
for access in access_paths:
|
for access in access_paths:
|
||||||
contexts = ContextSet.from_sets(
|
values = ContextSet.from_sets(
|
||||||
_create(self._infer_state, access, parent_context=c)
|
_create(self._infer_state, access, parent_value=c)
|
||||||
if c is None or isinstance(c, MixedObject)
|
if c is None or isinstance(c, MixedObject)
|
||||||
else ContextSet({create_cached_compiled_object(c.infer_state, access, c)})
|
else ContextSet({create_cached_compiled_object(c.infer_state, access, c)})
|
||||||
for c in contexts
|
for c in values
|
||||||
)
|
)
|
||||||
return contexts
|
return values
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def api_type(self):
|
def api_type(self):
|
||||||
@@ -230,11 +230,11 @@ def _find_syntax_node_name(infer_state, python_object):
|
|||||||
|
|
||||||
|
|
||||||
@compiled_objects_cache('mixed_cache')
|
@compiled_objects_cache('mixed_cache')
|
||||||
def _create(infer_state, access_handle, parent_context, *args):
|
def _create(infer_state, access_handle, parent_value, *args):
|
||||||
compiled_object = create_cached_compiled_object(
|
compiled_object = create_cached_compiled_object(
|
||||||
infer_state,
|
infer_state,
|
||||||
access_handle,
|
access_handle,
|
||||||
parent_context=parent_context and parent_context.compiled_object
|
parent_value=parent_value and parent_value.compiled_object
|
||||||
)
|
)
|
||||||
|
|
||||||
# TODO accessing this is bad, but it probably doesn't matter that much,
|
# TODO accessing this is bad, but it probably doesn't matter that much,
|
||||||
@@ -246,17 +246,17 @@ def _create(infer_state, access_handle, parent_context, *args):
|
|||||||
if type(python_object) in (dict, list, tuple):
|
if type(python_object) in (dict, list, tuple):
|
||||||
return ContextSet({compiled_object})
|
return ContextSet({compiled_object})
|
||||||
|
|
||||||
tree_contexts = to_stub(compiled_object)
|
tree_values = to_stub(compiled_object)
|
||||||
if not tree_contexts:
|
if not tree_values:
|
||||||
return ContextSet({compiled_object})
|
return ContextSet({compiled_object})
|
||||||
else:
|
else:
|
||||||
module_node, tree_node, file_io, code_lines = result
|
module_node, tree_node, file_io, code_lines = result
|
||||||
|
|
||||||
if parent_context is None:
|
if parent_value is None:
|
||||||
# TODO this __name__ is probably wrong.
|
# TODO this __name__ is probably wrong.
|
||||||
name = compiled_object.get_root_context().py__name__()
|
name = compiled_object.get_root_value().py__name__()
|
||||||
string_names = tuple(name.split('.'))
|
string_names = tuple(name.split('.'))
|
||||||
module_context = ModuleContext(
|
module_value = ModuleContext(
|
||||||
infer_state, module_node,
|
infer_state, module_node,
|
||||||
file_io=file_io,
|
file_io=file_io,
|
||||||
string_names=string_names,
|
string_names=string_names,
|
||||||
@@ -264,28 +264,28 @@ def _create(infer_state, access_handle, parent_context, *args):
|
|||||||
is_package=hasattr(compiled_object, 'py__path__'),
|
is_package=hasattr(compiled_object, 'py__path__'),
|
||||||
)
|
)
|
||||||
if name is not None:
|
if name is not None:
|
||||||
infer_state.module_cache.add(string_names, ContextSet([module_context]))
|
infer_state.module_cache.add(string_names, ContextSet([module_value]))
|
||||||
else:
|
else:
|
||||||
if parent_context.tree_node.get_root_node() != module_node:
|
if parent_value.tree_node.get_root_node() != module_node:
|
||||||
# This happens e.g. when __module__ is wrong, or when using
|
# This happens e.g. when __module__ is wrong, or when using
|
||||||
# TypeVar('foo'), where Jedi uses 'foo' as the name and
|
# TypeVar('foo'), where Jedi uses 'foo' as the name and
|
||||||
# Python's TypeVar('foo').__module__ will be typing.
|
# Python's TypeVar('foo').__module__ will be typing.
|
||||||
return ContextSet({compiled_object})
|
return ContextSet({compiled_object})
|
||||||
module_context = parent_context.get_root_context()
|
module_value = parent_value.get_root_value()
|
||||||
|
|
||||||
tree_contexts = ContextSet({
|
tree_values = ContextSet({
|
||||||
module_context.create_context(
|
module_value.create_value(
|
||||||
tree_node,
|
tree_node,
|
||||||
node_is_context=True,
|
node_is_value=True,
|
||||||
node_is_object=True
|
node_is_object=True
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
if tree_node.type == 'classdef':
|
if tree_node.type == 'classdef':
|
||||||
if not access_handle.is_class():
|
if not access_handle.is_class():
|
||||||
# Is an instance, not a class.
|
# Is an instance, not a class.
|
||||||
tree_contexts = tree_contexts.execute_with_values()
|
tree_values = tree_values.execute_with_values()
|
||||||
|
|
||||||
return ContextSet(
|
return ContextSet(
|
||||||
MixedObject(compiled_object, tree_context=tree_context)
|
MixedObject(compiled_object, tree_value=tree_value)
|
||||||
for tree_context in tree_contexts
|
for tree_value in tree_values
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ from jedi.inference.filters import AbstractFilter
|
|||||||
from jedi.inference.names import AbstractNameDefinition, ContextNameMixin, \
|
from jedi.inference.names import AbstractNameDefinition, ContextNameMixin, \
|
||||||
ParamNameInterface
|
ParamNameInterface
|
||||||
from jedi.inference.base_value import Context, ContextSet, NO_CONTEXTS
|
from jedi.inference.base_value import Context, ContextSet, NO_CONTEXTS
|
||||||
from jedi.inference.lazy_context import LazyKnownContext
|
from jedi.inference.lazy_value import LazyKnownContext
|
||||||
from jedi.inference.compiled.access import _sentinel
|
from jedi.inference.compiled.access import _sentinel
|
||||||
from jedi.inference.cache import infer_state_function_cache
|
from jedi.inference.cache import infer_state_function_cache
|
||||||
from jedi.inference.helpers import reraise_getitem_errors
|
from jedi.inference.helpers import reraise_getitem_errors
|
||||||
@@ -41,8 +41,8 @@ class CheckAttribute(object):
|
|||||||
|
|
||||||
|
|
||||||
class CompiledObject(Context):
|
class CompiledObject(Context):
|
||||||
def __init__(self, infer_state, access_handle, parent_context=None):
|
def __init__(self, infer_state, access_handle, parent_value=None):
|
||||||
super(CompiledObject, self).__init__(infer_state, parent_context)
|
super(CompiledObject, self).__init__(infer_state, parent_value)
|
||||||
self.access_handle = access_handle
|
self.access_handle = access_handle
|
||||||
|
|
||||||
def py__call__(self, arguments):
|
def py__call__(self, arguments):
|
||||||
@@ -57,9 +57,9 @@ class CompiledObject(Context):
|
|||||||
return super(CompiledObject, self).py__call__(arguments)
|
return super(CompiledObject, self).py__call__(arguments)
|
||||||
else:
|
else:
|
||||||
if self.access_handle.is_class():
|
if self.access_handle.is_class():
|
||||||
from jedi.inference.context import CompiledInstance
|
from jedi.inference.value import CompiledInstance
|
||||||
return ContextSet([
|
return ContextSet([
|
||||||
CompiledInstance(self.infer_state, self.parent_context, self, arguments)
|
CompiledInstance(self.infer_state, self.parent_value, self, arguments)
|
||||||
])
|
])
|
||||||
else:
|
else:
|
||||||
return ContextSet(self._execute_function(arguments))
|
return ContextSet(self._execute_function(arguments))
|
||||||
@@ -189,24 +189,24 @@ class CompiledObject(Context):
|
|||||||
|
|
||||||
return ContextSet([create_from_access_path(self.infer_state, access)])
|
return ContextSet([create_from_access_path(self.infer_state, access)])
|
||||||
|
|
||||||
def py__getitem__(self, index_context_set, contextualized_node):
|
def py__getitem__(self, index_value_set, valueualized_node):
|
||||||
all_access_paths = self.access_handle.py__getitem__all_values()
|
all_access_paths = self.access_handle.py__getitem__all_values()
|
||||||
if all_access_paths is None:
|
if all_access_paths is None:
|
||||||
# This means basically that no __getitem__ has been defined on this
|
# This means basically that no __getitem__ has been defined on this
|
||||||
# object.
|
# object.
|
||||||
return super(CompiledObject, self).py__getitem__(index_context_set, contextualized_node)
|
return super(CompiledObject, self).py__getitem__(index_value_set, valueualized_node)
|
||||||
return ContextSet(
|
return ContextSet(
|
||||||
create_from_access_path(self.infer_state, access)
|
create_from_access_path(self.infer_state, access)
|
||||||
for access in all_access_paths
|
for access in all_access_paths
|
||||||
)
|
)
|
||||||
|
|
||||||
def py__iter__(self, contextualized_node=None):
|
def py__iter__(self, valueualized_node=None):
|
||||||
# Python iterators are a bit strange, because there's no need for
|
# Python iterators are a bit strange, because there's no need for
|
||||||
# the __iter__ function as long as __getitem__ is defined (it will
|
# the __iter__ function as long as __getitem__ is defined (it will
|
||||||
# just start with __getitem__(0). This is especially true for
|
# just start with __getitem__(0). This is especially true for
|
||||||
# Python 2 strings, where `str.__iter__` is not even defined.
|
# Python 2 strings, where `str.__iter__` is not even defined.
|
||||||
if not self.access_handle.has_iter():
|
if not self.access_handle.has_iter():
|
||||||
for x in super(CompiledObject, self).py__iter__(contextualized_node):
|
for x in super(CompiledObject, self).py__iter__(valueualized_node):
|
||||||
yield x
|
yield x
|
||||||
|
|
||||||
access_path_list = self.access_handle.py__iter__list()
|
access_path_list = self.access_handle.py__iter__list()
|
||||||
@@ -269,18 +269,18 @@ class CompiledObject(Context):
|
|||||||
|
|
||||||
|
|
||||||
class CompiledName(AbstractNameDefinition):
|
class CompiledName(AbstractNameDefinition):
|
||||||
def __init__(self, infer_state, parent_context, name):
|
def __init__(self, infer_state, parent_value, name):
|
||||||
self._infer_state = infer_state
|
self._infer_state = infer_state
|
||||||
self.parent_context = parent_context
|
self.parent_value = parent_value
|
||||||
self.string_name = name
|
self.string_name = name
|
||||||
|
|
||||||
def _get_qualified_names(self):
|
def _get_qualified_names(self):
|
||||||
parent_qualified_names = self.parent_context.get_qualified_names()
|
parent_qualified_names = self.parent_value.get_qualified_names()
|
||||||
return parent_qualified_names + (self.string_name,)
|
return parent_qualified_names + (self.string_name,)
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
try:
|
try:
|
||||||
name = self.parent_context.name # __name__ is not defined all the time
|
name = self.parent_value.name # __name__ is not defined all the time
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
name = None
|
name = None
|
||||||
return '<%s: (%s).%s>' % (self.__class__.__name__, name, self.string_name)
|
return '<%s: (%s).%s>' % (self.__class__.__name__, name, self.string_name)
|
||||||
@@ -296,13 +296,13 @@ class CompiledName(AbstractNameDefinition):
|
|||||||
@underscore_memoization
|
@underscore_memoization
|
||||||
def infer(self):
|
def infer(self):
|
||||||
return ContextSet([_create_from_name(
|
return ContextSet([_create_from_name(
|
||||||
self._infer_state, self.parent_context, self.string_name
|
self._infer_state, self.parent_value, self.string_name
|
||||||
)])
|
)])
|
||||||
|
|
||||||
|
|
||||||
class SignatureParamName(ParamNameInterface, AbstractNameDefinition):
|
class SignatureParamName(ParamNameInterface, AbstractNameDefinition):
|
||||||
def __init__(self, compiled_obj, signature_param):
|
def __init__(self, compiled_obj, signature_param):
|
||||||
self.parent_context = compiled_obj.parent_context
|
self.parent_value = compiled_obj.parent_value
|
||||||
self._signature_param = signature_param
|
self._signature_param = signature_param
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@@ -322,19 +322,19 @@ class SignatureParamName(ParamNameInterface, AbstractNameDefinition):
|
|||||||
|
|
||||||
def infer(self):
|
def infer(self):
|
||||||
p = self._signature_param
|
p = self._signature_param
|
||||||
infer_state = self.parent_context.infer_state
|
infer_state = self.parent_value.infer_state
|
||||||
contexts = NO_CONTEXTS
|
values = NO_CONTEXTS
|
||||||
if p.has_default:
|
if p.has_default:
|
||||||
contexts = ContextSet([create_from_access_path(infer_state, p.default)])
|
values = ContextSet([create_from_access_path(infer_state, p.default)])
|
||||||
if p.has_annotation:
|
if p.has_annotation:
|
||||||
annotation = create_from_access_path(infer_state, p.annotation)
|
annotation = create_from_access_path(infer_state, p.annotation)
|
||||||
contexts |= annotation.execute_with_values()
|
values |= annotation.execute_with_values()
|
||||||
return contexts
|
return values
|
||||||
|
|
||||||
|
|
||||||
class UnresolvableParamName(ParamNameInterface, AbstractNameDefinition):
|
class UnresolvableParamName(ParamNameInterface, AbstractNameDefinition):
|
||||||
def __init__(self, compiled_obj, name, default):
|
def __init__(self, compiled_obj, name, default):
|
||||||
self.parent_context = compiled_obj.parent_context
|
self.parent_value = compiled_obj.parent_value
|
||||||
self.string_name = name
|
self.string_name = name
|
||||||
self._default = default
|
self._default = default
|
||||||
|
|
||||||
@@ -352,10 +352,10 @@ class UnresolvableParamName(ParamNameInterface, AbstractNameDefinition):
|
|||||||
|
|
||||||
|
|
||||||
class CompiledContextName(ContextNameMixin, AbstractNameDefinition):
|
class CompiledContextName(ContextNameMixin, AbstractNameDefinition):
|
||||||
def __init__(self, context, name):
|
def __init__(self, value, name):
|
||||||
self.string_name = name
|
self.string_name = name
|
||||||
self._context = context
|
self._value = value
|
||||||
self.parent_context = context.parent_context
|
self.parent_value = value.parent_value
|
||||||
|
|
||||||
|
|
||||||
class EmptyCompiledName(AbstractNameDefinition):
|
class EmptyCompiledName(AbstractNameDefinition):
|
||||||
@@ -365,7 +365,7 @@ class EmptyCompiledName(AbstractNameDefinition):
|
|||||||
nothing.
|
nothing.
|
||||||
"""
|
"""
|
||||||
def __init__(self, infer_state, name):
|
def __init__(self, infer_state, name):
|
||||||
self.parent_context = infer_state.builtins_module
|
self.parent_value = infer_state.builtins_module
|
||||||
self.string_name = name
|
self.string_name = name
|
||||||
|
|
||||||
def infer(self):
|
def infer(self):
|
||||||
@@ -509,33 +509,33 @@ def _parse_function_doc(doc):
|
|||||||
|
|
||||||
def _create_from_name(infer_state, compiled_object, name):
|
def _create_from_name(infer_state, compiled_object, name):
|
||||||
access_paths = compiled_object.access_handle.getattr_paths(name, default=None)
|
access_paths = compiled_object.access_handle.getattr_paths(name, default=None)
|
||||||
parent_context = compiled_object
|
parent_value = compiled_object
|
||||||
if parent_context.is_class():
|
if parent_value.is_class():
|
||||||
parent_context = parent_context.parent_context
|
parent_value = parent_value.parent_value
|
||||||
|
|
||||||
context = None
|
value = None
|
||||||
for access_path in access_paths:
|
for access_path in access_paths:
|
||||||
context = create_cached_compiled_object(
|
value = create_cached_compiled_object(
|
||||||
infer_state, access_path, parent_context=context
|
infer_state, access_path, parent_value=value
|
||||||
)
|
)
|
||||||
return context
|
return value
|
||||||
|
|
||||||
|
|
||||||
def _normalize_create_args(func):
|
def _normalize_create_args(func):
|
||||||
"""The cache doesn't care about keyword vs. normal args."""
|
"""The cache doesn't care about keyword vs. normal args."""
|
||||||
def wrapper(infer_state, obj, parent_context=None):
|
def wrapper(infer_state, obj, parent_value=None):
|
||||||
return func(infer_state, obj, parent_context)
|
return func(infer_state, obj, parent_value)
|
||||||
return wrapper
|
return wrapper
|
||||||
|
|
||||||
|
|
||||||
def create_from_access_path(infer_state, access_path):
|
def create_from_access_path(infer_state, access_path):
|
||||||
parent_context = None
|
parent_value = None
|
||||||
for name, access in access_path.accesses:
|
for name, access in access_path.accesses:
|
||||||
parent_context = create_cached_compiled_object(infer_state, access, parent_context)
|
parent_value = create_cached_compiled_object(infer_state, access, parent_value)
|
||||||
return parent_context
|
return parent_value
|
||||||
|
|
||||||
|
|
||||||
@_normalize_create_args
|
@_normalize_create_args
|
||||||
@infer_state_function_cache()
|
@infer_state_function_cache()
|
||||||
def create_cached_compiled_object(infer_state, access_handle, parent_context):
|
def create_cached_compiled_object(infer_state, access_handle, parent_value):
|
||||||
return CompiledObject(infer_state, access_handle, parent_context)
|
return CompiledObject(infer_state, access_handle, parent_value)
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
from jedi.inference.context.module import ModuleContext
|
|
||||||
from jedi.inference.context.klass import ClassContext
|
|
||||||
from jedi.inference.context.function import FunctionContext, \
|
|
||||||
MethodContext, FunctionExecutionContext
|
|
||||||
from jedi.inference.context.instance import AnonymousInstance, BoundMethod, \
|
|
||||||
CompiledInstance, AbstractInstanceContext, TreeInstance
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
'''
|
|
||||||
Decorators are not really contexts, however we need some wrappers to improve
|
|
||||||
docstrings and other things around decorators.
|
|
||||||
'''
|
|
||||||
|
|
||||||
from jedi.inference.base_value import ContextWrapper
|
|
||||||
|
|
||||||
|
|
||||||
class Decoratee(ContextWrapper):
|
|
||||||
def __init__(self, wrapped_context, original_context):
|
|
||||||
self._wrapped_context = wrapped_context
|
|
||||||
self._original_context = original_context
|
|
||||||
|
|
||||||
def py__doc__(self):
|
|
||||||
return self._original_context.py__doc__()
|
|
||||||
@@ -25,9 +25,9 @@ from jedi._compatibility import u
|
|||||||
from jedi import debug
|
from jedi import debug
|
||||||
from jedi.inference.utils import indent_block
|
from jedi.inference.utils import indent_block
|
||||||
from jedi.inference.cache import infer_state_method_cache
|
from jedi.inference.cache import infer_state_method_cache
|
||||||
from jedi.inference.base_value import iterator_to_context_set, ContextSet, \
|
from jedi.inference.base_value import iterator_to_value_set, ContextSet, \
|
||||||
NO_CONTEXTS
|
NO_CONTEXTS
|
||||||
from jedi.inference.lazy_context import LazyKnownContexts
|
from jedi.inference.lazy_value import LazyKnownContexts
|
||||||
|
|
||||||
|
|
||||||
DOCSTRING_PARAM_PATTERNS = [
|
DOCSTRING_PARAM_PATTERNS = [
|
||||||
@@ -183,7 +183,7 @@ def _strip_rst_role(type_str):
|
|||||||
return type_str
|
return type_str
|
||||||
|
|
||||||
|
|
||||||
def _infer_for_statement_string(module_context, string):
|
def _infer_for_statement_string(module_value, string):
|
||||||
code = dedent(u("""
|
code = dedent(u("""
|
||||||
def pseudo_docstring_stuff():
|
def pseudo_docstring_stuff():
|
||||||
'''
|
'''
|
||||||
@@ -205,7 +205,7 @@ def _infer_for_statement_string(module_context, string):
|
|||||||
# will be impossible to use `...` (Ellipsis) as a token. Docstring types
|
# will be impossible to use `...` (Ellipsis) as a token. Docstring types
|
||||||
# don't need to conform with the current grammar.
|
# don't need to conform with the current grammar.
|
||||||
debug.dbg('Parse docstring code %s', string, color='BLUE')
|
debug.dbg('Parse docstring code %s', string, color='BLUE')
|
||||||
grammar = module_context.infer_state.latest_grammar
|
grammar = module_value.infer_state.latest_grammar
|
||||||
try:
|
try:
|
||||||
module = grammar.parse(code.format(indent_block(string)), error_recovery=False)
|
module = grammar.parse(code.format(indent_block(string)), error_recovery=False)
|
||||||
except ParserSyntaxError:
|
except ParserSyntaxError:
|
||||||
@@ -221,29 +221,29 @@ def _infer_for_statement_string(module_context, string):
|
|||||||
if stmt.type not in ('name', 'atom', 'atom_expr'):
|
if stmt.type not in ('name', 'atom', 'atom_expr'):
|
||||||
return []
|
return []
|
||||||
|
|
||||||
from jedi.inference.context import FunctionContext
|
from jedi.inference.value import FunctionContext
|
||||||
function_context = FunctionContext(
|
function_value = FunctionContext(
|
||||||
module_context.infer_state,
|
module_value.infer_state,
|
||||||
module_context,
|
module_value,
|
||||||
funcdef
|
funcdef
|
||||||
)
|
)
|
||||||
func_execution_context = function_context.get_function_execution()
|
func_execution_value = function_value.get_function_execution()
|
||||||
# Use the module of the param.
|
# Use the module of the param.
|
||||||
# TODO this module is not the module of the param in case of a function
|
# TODO this module is not the module of the param in case of a function
|
||||||
# call. In that case it's the module of the function call.
|
# call. In that case it's the module of the function call.
|
||||||
# stuffed with content from a function call.
|
# stuffed with content from a function call.
|
||||||
return list(_execute_types_in_stmt(func_execution_context, stmt))
|
return list(_execute_types_in_stmt(func_execution_value, stmt))
|
||||||
|
|
||||||
|
|
||||||
def _execute_types_in_stmt(module_context, stmt):
|
def _execute_types_in_stmt(module_value, stmt):
|
||||||
"""
|
"""
|
||||||
Executing all types or general elements that we find in a statement. This
|
Executing all types or general elements that we find in a statement. This
|
||||||
doesn't include tuple, list and dict literals, because the stuff they
|
doesn't include tuple, list and dict literals, because the stuff they
|
||||||
contain is executed. (Used as type information).
|
contain is executed. (Used as type information).
|
||||||
"""
|
"""
|
||||||
definitions = module_context.infer_node(stmt)
|
definitions = module_value.infer_node(stmt)
|
||||||
return ContextSet.from_sets(
|
return ContextSet.from_sets(
|
||||||
_execute_array_values(module_context.infer_state, d)
|
_execute_array_values(module_value.infer_state, d)
|
||||||
for d in definitions
|
for d in definitions
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -253,13 +253,13 @@ def _execute_array_values(infer_state, array):
|
|||||||
Tuples indicate that there's not just one return value, but the listed
|
Tuples indicate that there's not just one return value, but the listed
|
||||||
ones. `(str, int)` means that it returns a tuple with both types.
|
ones. `(str, int)` means that it returns a tuple with both types.
|
||||||
"""
|
"""
|
||||||
from jedi.inference.context.iterable import SequenceLiteralContext, FakeSequence
|
from jedi.inference.value.iterable import SequenceLiteralContext, FakeSequence
|
||||||
if isinstance(array, SequenceLiteralContext):
|
if isinstance(array, SequenceLiteralContext):
|
||||||
values = []
|
values = []
|
||||||
for lazy_context in array.py__iter__():
|
for lazy_value in array.py__iter__():
|
||||||
objects = ContextSet.from_sets(
|
objects = ContextSet.from_sets(
|
||||||
_execute_array_values(infer_state, typ)
|
_execute_array_values(infer_state, typ)
|
||||||
for typ in lazy_context.infer()
|
for typ in lazy_value.infer()
|
||||||
)
|
)
|
||||||
values.append(LazyKnownContexts(objects))
|
values.append(LazyKnownContexts(objects))
|
||||||
return {FakeSequence(infer_state, array.array_type, values)}
|
return {FakeSequence(infer_state, array.array_type, values)}
|
||||||
@@ -268,35 +268,35 @@ def _execute_array_values(infer_state, array):
|
|||||||
|
|
||||||
|
|
||||||
@infer_state_method_cache()
|
@infer_state_method_cache()
|
||||||
def infer_param(execution_context, param):
|
def infer_param(execution_value, param):
|
||||||
from jedi.inference.context.instance import InstanceArguments
|
from jedi.inference.value.instance import InstanceArguments
|
||||||
from jedi.inference.context import FunctionExecutionContext
|
from jedi.inference.value import FunctionExecutionContext
|
||||||
|
|
||||||
def infer_docstring(docstring):
|
def infer_docstring(docstring):
|
||||||
return ContextSet(
|
return ContextSet(
|
||||||
p
|
p
|
||||||
for param_str in _search_param_in_docstr(docstring, param.name.value)
|
for param_str in _search_param_in_docstr(docstring, param.name.value)
|
||||||
for p in _infer_for_statement_string(module_context, param_str)
|
for p in _infer_for_statement_string(module_value, param_str)
|
||||||
)
|
)
|
||||||
module_context = execution_context.get_root_context()
|
module_value = execution_value.get_root_value()
|
||||||
func = param.get_parent_function()
|
func = param.get_parent_function()
|
||||||
if func.type == 'lambdef':
|
if func.type == 'lambdef':
|
||||||
return NO_CONTEXTS
|
return NO_CONTEXTS
|
||||||
|
|
||||||
types = infer_docstring(execution_context.py__doc__())
|
types = infer_docstring(execution_value.py__doc__())
|
||||||
if isinstance(execution_context, FunctionExecutionContext) \
|
if isinstance(execution_value, FunctionExecutionContext) \
|
||||||
and isinstance(execution_context.var_args, InstanceArguments) \
|
and isinstance(execution_value.var_args, InstanceArguments) \
|
||||||
and execution_context.function_context.py__name__() == '__init__':
|
and execution_value.function_value.py__name__() == '__init__':
|
||||||
class_context = execution_context.var_args.instance.class_context
|
class_value = execution_value.var_args.instance.class_value
|
||||||
types |= infer_docstring(class_context.py__doc__())
|
types |= infer_docstring(class_value.py__doc__())
|
||||||
|
|
||||||
debug.dbg('Found param types for docstring: %s', types, color='BLUE')
|
debug.dbg('Found param types for docstring: %s', types, color='BLUE')
|
||||||
return types
|
return types
|
||||||
|
|
||||||
|
|
||||||
@infer_state_method_cache()
|
@infer_state_method_cache()
|
||||||
@iterator_to_context_set
|
@iterator_to_value_set
|
||||||
def infer_return_types(function_context):
|
def infer_return_types(function_value):
|
||||||
def search_return_in_docstr(code):
|
def search_return_in_docstr(code):
|
||||||
for p in DOCSTRING_RETURN_PATTERNS:
|
for p in DOCSTRING_RETURN_PATTERNS:
|
||||||
match = p.search(code)
|
match = p.search(code)
|
||||||
@@ -306,6 +306,6 @@ def infer_return_types(function_context):
|
|||||||
for type_ in _search_return_in_numpydocstr(code):
|
for type_ in _search_return_in_numpydocstr(code):
|
||||||
yield type_
|
yield type_
|
||||||
|
|
||||||
for type_str in search_return_in_docstr(function_context.py__doc__()):
|
for type_str in search_return_in_docstr(function_value.py__doc__()):
|
||||||
for context in _infer_for_statement_string(function_context.get_root_context(), type_str):
|
for value in _infer_for_statement_string(function_value.get_root_value(), type_str):
|
||||||
yield context
|
yield value
|
||||||
|
|||||||
+33
-33
@@ -26,7 +26,7 @@ from jedi.inference.param import create_default_params
|
|||||||
from jedi.inference.helpers import is_stdlib_path
|
from jedi.inference.helpers import is_stdlib_path
|
||||||
from jedi.inference.utils import to_list
|
from jedi.inference.utils import to_list
|
||||||
from jedi.parser_utils import get_parent_scope
|
from jedi.parser_utils import get_parent_scope
|
||||||
from jedi.inference.context import ModuleContext, instance
|
from jedi.inference.value import ModuleContext, instance
|
||||||
from jedi.inference.base_value import ContextSet, NO_CONTEXTS
|
from jedi.inference.base_value import ContextSet, NO_CONTEXTS
|
||||||
from jedi.inference import recursion
|
from jedi.inference import recursion
|
||||||
|
|
||||||
@@ -54,7 +54,7 @@ class DynamicExecutedParams(object):
|
|||||||
|
|
||||||
|
|
||||||
@debug.increase_indent
|
@debug.increase_indent
|
||||||
def search_params(infer_state, execution_context, funcdef):
|
def search_params(infer_state, execution_value, funcdef):
|
||||||
"""
|
"""
|
||||||
A dynamic search for param values. If you try to complete a type:
|
A dynamic search for param values. If you try to complete a type:
|
||||||
|
|
||||||
@@ -68,31 +68,31 @@ def search_params(infer_state, execution_context, funcdef):
|
|||||||
is.
|
is.
|
||||||
"""
|
"""
|
||||||
if not settings.dynamic_params:
|
if not settings.dynamic_params:
|
||||||
return create_default_params(execution_context, funcdef)
|
return create_default_params(execution_value, funcdef)
|
||||||
|
|
||||||
infer_state.dynamic_params_depth += 1
|
infer_state.dynamic_params_depth += 1
|
||||||
try:
|
try:
|
||||||
path = execution_context.get_root_context().py__file__()
|
path = execution_value.get_root_value().py__file__()
|
||||||
if path is not None and is_stdlib_path(path):
|
if path is not None and is_stdlib_path(path):
|
||||||
# We don't want to search for usages in the stdlib. Usually people
|
# We don't want to search for usages in the stdlib. Usually people
|
||||||
# don't work with it (except if you are a core maintainer, sorry).
|
# don't work with it (except if you are a core maintainer, sorry).
|
||||||
# This makes everything slower. Just disable it and run the tests,
|
# This makes everything slower. Just disable it and run the tests,
|
||||||
# you will see the slowdown, especially in 3.6.
|
# you will see the slowdown, especially in 3.6.
|
||||||
return create_default_params(execution_context, funcdef)
|
return create_default_params(execution_value, funcdef)
|
||||||
|
|
||||||
if funcdef.type == 'lambdef':
|
if funcdef.type == 'lambdef':
|
||||||
string_name = _get_lambda_name(funcdef)
|
string_name = _get_lambda_name(funcdef)
|
||||||
if string_name is None:
|
if string_name is None:
|
||||||
return create_default_params(execution_context, funcdef)
|
return create_default_params(execution_value, funcdef)
|
||||||
else:
|
else:
|
||||||
string_name = funcdef.name.value
|
string_name = funcdef.name.value
|
||||||
debug.dbg('Dynamic param search in %s.', string_name, color='MAGENTA')
|
debug.dbg('Dynamic param search in %s.', string_name, color='MAGENTA')
|
||||||
|
|
||||||
try:
|
try:
|
||||||
module_context = execution_context.get_root_context()
|
module_value = execution_value.get_root_value()
|
||||||
function_executions = _search_function_executions(
|
function_executions = _search_function_executions(
|
||||||
infer_state,
|
infer_state,
|
||||||
module_context,
|
module_value,
|
||||||
funcdef,
|
funcdef,
|
||||||
string_name=string_name,
|
string_name=string_name,
|
||||||
)
|
)
|
||||||
@@ -105,7 +105,7 @@ def search_params(infer_state, execution_context, funcdef):
|
|||||||
for executed_params in zipped_params]
|
for executed_params in zipped_params]
|
||||||
# Inferes the ExecutedParams to types.
|
# Inferes the ExecutedParams to types.
|
||||||
else:
|
else:
|
||||||
return create_default_params(execution_context, funcdef)
|
return create_default_params(execution_value, funcdef)
|
||||||
finally:
|
finally:
|
||||||
debug.dbg('Dynamic param result finished', color='MAGENTA')
|
debug.dbg('Dynamic param result finished', color='MAGENTA')
|
||||||
return params
|
return params
|
||||||
@@ -115,7 +115,7 @@ def search_params(infer_state, execution_context, funcdef):
|
|||||||
|
|
||||||
@infer_state_function_cache(default=None)
|
@infer_state_function_cache(default=None)
|
||||||
@to_list
|
@to_list
|
||||||
def _search_function_executions(infer_state, module_context, funcdef, string_name):
|
def _search_function_executions(infer_state, module_value, funcdef, string_name):
|
||||||
"""
|
"""
|
||||||
Returns a list of param names.
|
Returns a list of param names.
|
||||||
"""
|
"""
|
||||||
@@ -128,11 +128,11 @@ def _search_function_executions(infer_state, module_context, funcdef, string_nam
|
|||||||
|
|
||||||
found_executions = False
|
found_executions = False
|
||||||
i = 0
|
i = 0
|
||||||
for for_mod_context in imports.get_modules_containing_name(
|
for for_mod_value in imports.get_modules_containing_name(
|
||||||
infer_state, [module_context], string_name):
|
infer_state, [module_value], string_name):
|
||||||
if not isinstance(module_context, ModuleContext):
|
if not isinstance(module_value, ModuleContext):
|
||||||
return
|
return
|
||||||
for name, trailer in _get_possible_nodes(for_mod_context, string_name):
|
for name, trailer in _get_possible_nodes(for_mod_value, string_name):
|
||||||
i += 1
|
i += 1
|
||||||
|
|
||||||
# This is a simple way to stop Jedi's dynamic param recursion
|
# This is a simple way to stop Jedi's dynamic param recursion
|
||||||
@@ -141,9 +141,9 @@ def _search_function_executions(infer_state, module_context, funcdef, string_nam
|
|||||||
if i * infer_state.dynamic_params_depth > MAX_PARAM_SEARCHES:
|
if i * infer_state.dynamic_params_depth > MAX_PARAM_SEARCHES:
|
||||||
return
|
return
|
||||||
|
|
||||||
random_context = infer_state.create_context(for_mod_context, name)
|
random_value = infer_state.create_value(for_mod_value, name)
|
||||||
for function_execution in _check_name_for_execution(
|
for function_execution in _check_name_for_execution(
|
||||||
infer_state, random_context, compare_node, name, trailer):
|
infer_state, random_value, compare_node, name, trailer):
|
||||||
found_executions = True
|
found_executions = True
|
||||||
yield function_execution
|
yield function_execution
|
||||||
|
|
||||||
@@ -165,9 +165,9 @@ def _get_lambda_name(node):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def _get_possible_nodes(module_context, func_string_name):
|
def _get_possible_nodes(module_value, func_string_name):
|
||||||
try:
|
try:
|
||||||
names = module_context.tree_node.get_used_names()[func_string_name]
|
names = module_value.tree_node.get_used_names()[func_string_name]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
return
|
return
|
||||||
|
|
||||||
@@ -178,51 +178,51 @@ def _get_possible_nodes(module_context, func_string_name):
|
|||||||
yield name, trailer
|
yield name, trailer
|
||||||
|
|
||||||
|
|
||||||
def _check_name_for_execution(infer_state, context, compare_node, name, trailer):
|
def _check_name_for_execution(infer_state, value, compare_node, name, trailer):
|
||||||
from jedi.inference.context.function import FunctionExecutionContext
|
from jedi.inference.value.function import FunctionExecutionContext
|
||||||
|
|
||||||
def create_func_excs():
|
def create_func_excs():
|
||||||
arglist = trailer.children[1]
|
arglist = trailer.children[1]
|
||||||
if arglist == ')':
|
if arglist == ')':
|
||||||
arglist = None
|
arglist = None
|
||||||
args = TreeArguments(infer_state, context, arglist, trailer)
|
args = TreeArguments(infer_state, value, arglist, trailer)
|
||||||
if value_node.type == 'classdef':
|
if value_node.type == 'classdef':
|
||||||
created_instance = instance.TreeInstance(
|
created_instance = instance.TreeInstance(
|
||||||
infer_state,
|
infer_state,
|
||||||
value.parent_context,
|
v.parent_value,
|
||||||
value,
|
v,
|
||||||
args
|
args
|
||||||
)
|
)
|
||||||
for execution in created_instance.create_init_executions():
|
for execution in created_instance.create_init_executions():
|
||||||
yield execution
|
yield execution
|
||||||
else:
|
else:
|
||||||
yield value.get_function_execution(args)
|
yield v.get_function_execution(args)
|
||||||
|
|
||||||
for value in infer_state.goto_definitions(context, name):
|
for v in infer_state.goto_definitions(value, name):
|
||||||
value_node = value.tree_node
|
value_node = v.tree_node
|
||||||
if compare_node == value_node:
|
if compare_node == value_node:
|
||||||
for func_execution in create_func_excs():
|
for func_execution in create_func_excs():
|
||||||
yield func_execution
|
yield func_execution
|
||||||
elif isinstance(value.parent_context, FunctionExecutionContext) and \
|
elif isinstance(v.parent_value, FunctionExecutionContext) and \
|
||||||
compare_node.type == 'funcdef':
|
compare_node.type == 'funcdef':
|
||||||
# Here we're trying to find decorators by checking the first
|
# Here we're trying to find decorators by checking the first
|
||||||
# parameter. It's not very generic though. Should find a better
|
# parameter. It's not very generic though. Should find a better
|
||||||
# solution that also applies to nested decorators.
|
# solution that also applies to nested decorators.
|
||||||
params, _ = value.parent_context.get_executed_params_and_issues()
|
params, _ = v.parent_value.get_executed_params_and_issues()
|
||||||
if len(params) != 1:
|
if len(params) != 1:
|
||||||
continue
|
continue
|
||||||
values = params[0].infer()
|
values = params[0].infer()
|
||||||
nodes = [v.tree_node for v in values]
|
nodes = [v.tree_node for v in values]
|
||||||
if nodes == [compare_node]:
|
if nodes == [compare_node]:
|
||||||
# Found a decorator.
|
# Found a decorator.
|
||||||
module_context = context.get_root_context()
|
module_value = value.get_root_value()
|
||||||
execution_context = next(create_func_excs())
|
execution_value = next(create_func_excs())
|
||||||
for name, trailer in _get_possible_nodes(module_context, params[0].string_name):
|
for name, trailer in _get_possible_nodes(module_value, params[0].string_name):
|
||||||
if value_node.start_pos < name.start_pos < value_node.end_pos:
|
if value_node.start_pos < name.start_pos < value_node.end_pos:
|
||||||
random_context = infer_state.create_context(execution_context, name)
|
random_value = infer_state.create_value(execution_value, name)
|
||||||
iterator = _check_name_for_execution(
|
iterator = _check_name_for_execution(
|
||||||
infer_state,
|
infer_state,
|
||||||
random_context,
|
random_value,
|
||||||
compare_node,
|
compare_node,
|
||||||
name,
|
name,
|
||||||
trailer
|
trailer
|
||||||
|
|||||||
+47
-47
@@ -68,11 +68,11 @@ def _get_definition_names(used_names, name_key):
|
|||||||
class AbstractUsedNamesFilter(AbstractFilter):
|
class AbstractUsedNamesFilter(AbstractFilter):
|
||||||
name_class = TreeNameDefinition
|
name_class = TreeNameDefinition
|
||||||
|
|
||||||
def __init__(self, context, parser_scope):
|
def __init__(self, value, parser_scope):
|
||||||
self._parser_scope = parser_scope
|
self._parser_scope = parser_scope
|
||||||
self._module_node = self._parser_scope.get_root_node()
|
self._module_node = self._parser_scope.get_root_node()
|
||||||
self._used_names = self._module_node.get_used_names()
|
self._used_names = self._module_node.get_used_names()
|
||||||
self.context = context
|
self.value = value
|
||||||
|
|
||||||
def get(self, name, **filter_kwargs):
|
def get(self, name, **filter_kwargs):
|
||||||
return self._convert_names(self._filter(
|
return self._convert_names(self._filter(
|
||||||
@@ -81,7 +81,7 @@ class AbstractUsedNamesFilter(AbstractFilter):
|
|||||||
))
|
))
|
||||||
|
|
||||||
def _convert_names(self, names):
|
def _convert_names(self, names):
|
||||||
return [self.name_class(self.context, name) for name in names]
|
return [self.name_class(self.value, name) for name in names]
|
||||||
|
|
||||||
def values(self, **filter_kwargs):
|
def values(self, **filter_kwargs):
|
||||||
return self._convert_names(
|
return self._convert_names(
|
||||||
@@ -94,23 +94,23 @@ class AbstractUsedNamesFilter(AbstractFilter):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return '<%s: %s>' % (self.__class__.__name__, self.context)
|
return '<%s: %s>' % (self.__class__.__name__, self.value)
|
||||||
|
|
||||||
|
|
||||||
class ParserTreeFilter(AbstractUsedNamesFilter):
|
class ParserTreeFilter(AbstractUsedNamesFilter):
|
||||||
# TODO remove infer_state as an argument, it's not used.
|
# TODO remove infer_state as an argument, it's not used.
|
||||||
def __init__(self, infer_state, context, node_context=None, until_position=None,
|
def __init__(self, infer_state, value, node_value=None, until_position=None,
|
||||||
origin_scope=None):
|
origin_scope=None):
|
||||||
"""
|
"""
|
||||||
node_context is an option to specify a second context for use cases
|
node_value is an option to specify a second value for use cases
|
||||||
like the class mro where the parent class of a new name would be the
|
like the class mro where the parent class of a new name would be the
|
||||||
context, but for some type inference it's important to have a local
|
value, but for some type inference it's important to have a local
|
||||||
context of the other classes.
|
value of the other classes.
|
||||||
"""
|
"""
|
||||||
if node_context is None:
|
if node_value is None:
|
||||||
node_context = context
|
node_value = value
|
||||||
super(ParserTreeFilter, self).__init__(context, node_context.tree_node)
|
super(ParserTreeFilter, self).__init__(value, node_value.tree_node)
|
||||||
self._node_context = node_context
|
self._node_value = node_value
|
||||||
self._origin_scope = origin_scope
|
self._origin_scope = origin_scope
|
||||||
self._until_position = until_position
|
self._until_position = until_position
|
||||||
|
|
||||||
@@ -129,8 +129,8 @@ class ParserTreeFilter(AbstractUsedNamesFilter):
|
|||||||
def _check_flows(self, names):
|
def _check_flows(self, names):
|
||||||
for name in sorted(names, key=lambda name: name.start_pos, reverse=True):
|
for name in sorted(names, key=lambda name: name.start_pos, reverse=True):
|
||||||
check = flow_analysis.reachability_check(
|
check = flow_analysis.reachability_check(
|
||||||
context=self._node_context,
|
value=self._node_value,
|
||||||
context_scope=self._parser_scope,
|
value_scope=self._parser_scope,
|
||||||
node=name,
|
node=name,
|
||||||
origin_scope=self._origin_scope
|
origin_scope=self._origin_scope
|
||||||
)
|
)
|
||||||
@@ -144,12 +144,12 @@ class ParserTreeFilter(AbstractUsedNamesFilter):
|
|||||||
class FunctionExecutionFilter(ParserTreeFilter):
|
class FunctionExecutionFilter(ParserTreeFilter):
|
||||||
param_name = ParamName
|
param_name = ParamName
|
||||||
|
|
||||||
def __init__(self, infer_state, context, node_context=None,
|
def __init__(self, infer_state, value, node_value=None,
|
||||||
until_position=None, origin_scope=None):
|
until_position=None, origin_scope=None):
|
||||||
super(FunctionExecutionFilter, self).__init__(
|
super(FunctionExecutionFilter, self).__init__(
|
||||||
infer_state,
|
infer_state,
|
||||||
context,
|
value,
|
||||||
node_context,
|
node_value,
|
||||||
until_position,
|
until_position,
|
||||||
origin_scope
|
origin_scope
|
||||||
)
|
)
|
||||||
@@ -159,14 +159,14 @@ class FunctionExecutionFilter(ParserTreeFilter):
|
|||||||
for name in names:
|
for name in names:
|
||||||
param = search_ancestor(name, 'param')
|
param = search_ancestor(name, 'param')
|
||||||
if param:
|
if param:
|
||||||
yield self.param_name(self.context, name)
|
yield self.param_name(self.value, name)
|
||||||
else:
|
else:
|
||||||
yield TreeNameDefinition(self.context, name)
|
yield TreeNameDefinition(self.value, name)
|
||||||
|
|
||||||
|
|
||||||
class GlobalNameFilter(AbstractUsedNamesFilter):
|
class GlobalNameFilter(AbstractUsedNamesFilter):
|
||||||
def __init__(self, context, parser_scope):
|
def __init__(self, value, parser_scope):
|
||||||
super(GlobalNameFilter, self).__init__(context, parser_scope)
|
super(GlobalNameFilter, self).__init__(value, parser_scope)
|
||||||
|
|
||||||
def get(self, name):
|
def get(self, name):
|
||||||
try:
|
try:
|
||||||
@@ -235,17 +235,17 @@ class _BuiltinMappedMethod(Context):
|
|||||||
"""``Generator.__next__`` ``dict.values`` methods and so on."""
|
"""``Generator.__next__`` ``dict.values`` methods and so on."""
|
||||||
api_type = u'function'
|
api_type = u'function'
|
||||||
|
|
||||||
def __init__(self, builtin_context, method, builtin_func):
|
def __init__(self, builtin_value, method, builtin_func):
|
||||||
super(_BuiltinMappedMethod, self).__init__(
|
super(_BuiltinMappedMethod, self).__init__(
|
||||||
builtin_context.infer_state,
|
builtin_value.infer_state,
|
||||||
parent_context=builtin_context
|
parent_value=builtin_value
|
||||||
)
|
)
|
||||||
self._method = method
|
self._method = method
|
||||||
self._builtin_func = builtin_func
|
self._builtin_func = builtin_func
|
||||||
|
|
||||||
def py__call__(self, arguments):
|
def py__call__(self, arguments):
|
||||||
# TODO add TypeError if params are given/or not correct.
|
# TODO add TypeError if params are given/or not correct.
|
||||||
return self._method(self.parent_context)
|
return self._method(self.parent_value)
|
||||||
|
|
||||||
def __getattr__(self, name):
|
def __getattr__(self, name):
|
||||||
return getattr(self._builtin_func, name)
|
return getattr(self._builtin_func, name)
|
||||||
@@ -259,19 +259,19 @@ class SpecialMethodFilter(DictFilter):
|
|||||||
class SpecialMethodName(AbstractNameDefinition):
|
class SpecialMethodName(AbstractNameDefinition):
|
||||||
api_type = u'function'
|
api_type = u'function'
|
||||||
|
|
||||||
def __init__(self, parent_context, string_name, value, builtin_context):
|
def __init__(self, parent_value, string_name, value, builtin_value):
|
||||||
callable_, python_version = value
|
callable_, python_version = value
|
||||||
if python_version is not None and \
|
if python_version is not None and \
|
||||||
python_version != parent_context.infer_state.environment.version_info.major:
|
python_version != parent_value.infer_state.environment.version_info.major:
|
||||||
raise KeyError
|
raise KeyError
|
||||||
|
|
||||||
self.parent_context = parent_context
|
self.parent_value = parent_value
|
||||||
self.string_name = string_name
|
self.string_name = string_name
|
||||||
self._callable = callable_
|
self._callable = callable_
|
||||||
self._builtin_context = builtin_context
|
self._builtin_value = builtin_value
|
||||||
|
|
||||||
def infer(self):
|
def infer(self):
|
||||||
for filter in self._builtin_context.get_filters():
|
for filter in self._builtin_value.get_filters():
|
||||||
# We can take the first index, because on builtin methods there's
|
# We can take the first index, because on builtin methods there's
|
||||||
# always only going to be one name. The same is true for the
|
# always only going to be one name. The same is true for the
|
||||||
# inferred values.
|
# inferred values.
|
||||||
@@ -282,22 +282,22 @@ class SpecialMethodFilter(DictFilter):
|
|||||||
continue
|
continue
|
||||||
break
|
break
|
||||||
return ContextSet([
|
return ContextSet([
|
||||||
_BuiltinMappedMethod(self.parent_context, self._callable, builtin_func)
|
_BuiltinMappedMethod(self.parent_value, self._callable, builtin_func)
|
||||||
])
|
])
|
||||||
|
|
||||||
def __init__(self, context, dct, builtin_context):
|
def __init__(self, value, dct, builtin_value):
|
||||||
super(SpecialMethodFilter, self).__init__(dct)
|
super(SpecialMethodFilter, self).__init__(dct)
|
||||||
self.context = context
|
self.value = value
|
||||||
self._builtin_context = builtin_context
|
self._builtin_value = builtin_value
|
||||||
"""
|
"""
|
||||||
This context is what will be used to introspect the name, where as the
|
This value is what will be used to introspect the name, where as the
|
||||||
other context will be used to execute the function.
|
other value will be used to execute the function.
|
||||||
|
|
||||||
We distinguish, because we have to.
|
We distinguish, because we have to.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def _convert(self, name, value):
|
def _convert(self, name, value):
|
||||||
return self.SpecialMethodName(self.context, name, value, self._builtin_context)
|
return self.SpecialMethodName(self.value, name, value, self._builtin_value)
|
||||||
|
|
||||||
|
|
||||||
class _OverwriteMeta(type):
|
class _OverwriteMeta(type):
|
||||||
@@ -321,9 +321,9 @@ class _OverwriteMeta(type):
|
|||||||
|
|
||||||
class _AttributeOverwriteMixin(object):
|
class _AttributeOverwriteMixin(object):
|
||||||
def get_filters(self, search_global=False, *args, **kwargs):
|
def get_filters(self, search_global=False, *args, **kwargs):
|
||||||
yield SpecialMethodFilter(self, self.overwritten_methods, self._wrapped_context)
|
yield SpecialMethodFilter(self, self.overwritten_methods, self._wrapped_value)
|
||||||
|
|
||||||
for filter in self._wrapped_context.get_filters(search_global):
|
for filter in self._wrapped_value.get_filters(search_global):
|
||||||
yield filter
|
yield filter
|
||||||
|
|
||||||
|
|
||||||
@@ -346,7 +346,7 @@ def publish_method(method_name, python_version_match=None):
|
|||||||
return decorator
|
return decorator
|
||||||
|
|
||||||
|
|
||||||
def get_global_filters(infer_state, context, until_position, origin_scope):
|
def get_global_filters(infer_state, value, until_position, origin_scope):
|
||||||
"""
|
"""
|
||||||
Returns all filters in order of priority for name resolution.
|
Returns all filters in order of priority for name resolution.
|
||||||
|
|
||||||
@@ -364,8 +364,8 @@ def get_global_filters(infer_state, context, until_position, origin_scope):
|
|||||||
>>> scope = next(module_node.iter_funcdefs())
|
>>> scope = next(module_node.iter_funcdefs())
|
||||||
>>> scope
|
>>> scope
|
||||||
<Function: func@3-5>
|
<Function: func@3-5>
|
||||||
>>> context = script._get_module().create_context(scope)
|
>>> value = script._get_module().create_value(scope)
|
||||||
>>> filters = list(get_global_filters(context.infer_state, context, (4, 0), None))
|
>>> filters = list(get_global_filters(value.infer_state, value, (4, 0), None))
|
||||||
|
|
||||||
First we get the names from the function scope.
|
First we get the names from the function scope.
|
||||||
|
|
||||||
@@ -394,19 +394,19 @@ def get_global_filters(infer_state, context, until_position, origin_scope):
|
|||||||
>>> list(filters[3].values()) # doctest: +ELLIPSIS
|
>>> list(filters[3].values()) # doctest: +ELLIPSIS
|
||||||
[...]
|
[...]
|
||||||
"""
|
"""
|
||||||
from jedi.inference.context.function import FunctionExecutionContext
|
from jedi.inference.value.function import FunctionExecutionContext
|
||||||
while context is not None:
|
while value is not None:
|
||||||
# Names in methods cannot be resolved within the class.
|
# Names in methods cannot be resolved within the class.
|
||||||
for filter in context.get_filters(
|
for filter in value.get_filters(
|
||||||
search_global=True,
|
search_global=True,
|
||||||
until_position=until_position,
|
until_position=until_position,
|
||||||
origin_scope=origin_scope):
|
origin_scope=origin_scope):
|
||||||
yield filter
|
yield filter
|
||||||
if isinstance(context, FunctionExecutionContext):
|
if isinstance(value, FunctionExecutionContext):
|
||||||
# The position should be reset if the current scope is a function.
|
# The position should be reset if the current scope is a function.
|
||||||
until_position = None
|
until_position = None
|
||||||
|
|
||||||
context = context.parent_context
|
value = value.parent_value
|
||||||
|
|
||||||
# Add builtins to the global scope.
|
# Add builtins to the global scope.
|
||||||
yield next(infer_state.builtins_module.get_filters())
|
yield next(infer_state.builtins_module.get_filters())
|
||||||
|
|||||||
+43
-43
@@ -24,21 +24,21 @@ from jedi.inference import analysis
|
|||||||
from jedi.inference import flow_analysis
|
from jedi.inference import flow_analysis
|
||||||
from jedi.inference.arguments import TreeArguments
|
from jedi.inference.arguments import TreeArguments
|
||||||
from jedi.inference import helpers
|
from jedi.inference import helpers
|
||||||
from jedi.inference.context import iterable
|
from jedi.inference.value import iterable
|
||||||
from jedi.inference.filters import get_global_filters
|
from jedi.inference.filters import get_global_filters
|
||||||
from jedi.inference.names import TreeNameDefinition
|
from jedi.inference.names import TreeNameDefinition
|
||||||
from jedi.inference.base_value import ContextSet, NO_CONTEXTS
|
from jedi.inference.base_value import ContextSet, NO_CONTEXTS
|
||||||
from jedi.parser_utils import is_scope, get_parent_scope
|
from jedi.parser_utils import is_scope, get_parent_scope
|
||||||
from jedi.inference.gradual.conversion import convert_contexts
|
from jedi.inference.gradual.conversion import convert_values
|
||||||
|
|
||||||
|
|
||||||
class NameFinder(object):
|
class NameFinder(object):
|
||||||
def __init__(self, infer_state, context, name_context, name_or_str,
|
def __init__(self, infer_state, value, name_value, name_or_str,
|
||||||
position=None, analysis_errors=True):
|
position=None, analysis_errors=True):
|
||||||
self._infer_state = infer_state
|
self._infer_state = infer_state
|
||||||
# Make sure that it's not just a syntax tree node.
|
# Make sure that it's not just a syntax tree node.
|
||||||
self._context = context
|
self._value = value
|
||||||
self._name_context = name_context
|
self._name_value = name_value
|
||||||
self._name = name_or_str
|
self._name = name_or_str
|
||||||
if isinstance(name_or_str, tree.Name):
|
if isinstance(name_or_str, tree.Name):
|
||||||
self._string_name = name_or_str.value
|
self._string_name = name_or_str.value
|
||||||
@@ -56,8 +56,8 @@ class NameFinder(object):
|
|||||||
names = self.filter_name(filters)
|
names = self.filter_name(filters)
|
||||||
if self._found_predefined_types is not None and names:
|
if self._found_predefined_types is not None and names:
|
||||||
check = flow_analysis.reachability_check(
|
check = flow_analysis.reachability_check(
|
||||||
context=self._context,
|
value=self._value,
|
||||||
context_scope=self._context.tree_node,
|
value_scope=self._value.tree_node,
|
||||||
node=self._name,
|
node=self._name,
|
||||||
)
|
)
|
||||||
if check is flow_analysis.UNREACHABLE:
|
if check is flow_analysis.UNREACHABLE:
|
||||||
@@ -72,11 +72,11 @@ class NameFinder(object):
|
|||||||
if isinstance(self._name, tree.Name):
|
if isinstance(self._name, tree.Name):
|
||||||
if attribute_lookup:
|
if attribute_lookup:
|
||||||
analysis.add_attribute_error(
|
analysis.add_attribute_error(
|
||||||
self._name_context, self._context, self._name)
|
self._name_value, self._value, self._name)
|
||||||
else:
|
else:
|
||||||
message = ("NameError: name '%s' is not defined."
|
message = ("NameError: name '%s' is not defined."
|
||||||
% self._string_name)
|
% self._string_name)
|
||||||
analysis.add(self._name_context, 'name-error', self._name, message)
|
analysis.add(self._name_value, 'name-error', self._name, message)
|
||||||
|
|
||||||
return types
|
return types
|
||||||
|
|
||||||
@@ -98,7 +98,7 @@ class NameFinder(object):
|
|||||||
position = self._position
|
position = self._position
|
||||||
|
|
||||||
# For functions and classes the defaults don't belong to the
|
# For functions and classes the defaults don't belong to the
|
||||||
# function and get inferred in the context before the function. So
|
# function and get inferred in the value before the function. So
|
||||||
# make sure to exclude the function/class name.
|
# make sure to exclude the function/class name.
|
||||||
if origin_scope is not None:
|
if origin_scope is not None:
|
||||||
ancestor = search_ancestor(origin_scope, 'funcdef', 'classdef', 'lambdef')
|
ancestor = search_ancestor(origin_scope, 'funcdef', 'classdef', 'lambdef')
|
||||||
@@ -114,16 +114,16 @@ class NameFinder(object):
|
|||||||
if lambdef is None or position < lambdef.children[-2].start_pos:
|
if lambdef is None or position < lambdef.children[-2].start_pos:
|
||||||
position = ancestor.start_pos
|
position = ancestor.start_pos
|
||||||
|
|
||||||
return get_global_filters(self._infer_state, self._context, position, origin_scope)
|
return get_global_filters(self._infer_state, self._value, position, origin_scope)
|
||||||
else:
|
else:
|
||||||
return self._get_context_filters(origin_scope)
|
return self._get_value_filters(origin_scope)
|
||||||
|
|
||||||
def _get_context_filters(self, origin_scope):
|
def _get_value_filters(self, origin_scope):
|
||||||
for f in self._context.get_filters(False, self._position, origin_scope=origin_scope):
|
for f in self._value.get_filters(False, self._position, origin_scope=origin_scope):
|
||||||
yield f
|
yield f
|
||||||
# This covers the case where a stub files are incomplete.
|
# This covers the case where a stub files are incomplete.
|
||||||
if self._context.is_stub():
|
if self._value.is_stub():
|
||||||
for c in convert_contexts(ContextSet({self._context})):
|
for c in convert_values(ContextSet({self._value})):
|
||||||
for f in c.get_filters():
|
for f in c.get_filters():
|
||||||
yield f
|
yield f
|
||||||
|
|
||||||
@@ -135,13 +135,13 @@ class NameFinder(object):
|
|||||||
names = []
|
names = []
|
||||||
# This paragraph is currently needed for proper branch type inference
|
# This paragraph is currently needed for proper branch type inference
|
||||||
# (static analysis).
|
# (static analysis).
|
||||||
if self._context.predefined_names and isinstance(self._name, tree.Name):
|
if self._value.predefined_names and isinstance(self._name, tree.Name):
|
||||||
node = self._name
|
node = self._name
|
||||||
while node is not None and not is_scope(node):
|
while node is not None and not is_scope(node):
|
||||||
node = node.parent
|
node = node.parent
|
||||||
if node.type in ("if_stmt", "for_stmt", "comp_for", 'sync_comp_for'):
|
if node.type in ("if_stmt", "for_stmt", "comp_for", 'sync_comp_for'):
|
||||||
try:
|
try:
|
||||||
name_dict = self._context.predefined_names[node]
|
name_dict = self._value.predefined_names[node]
|
||||||
types = name_dict[self._string_name]
|
types = name_dict[self._string_name]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
continue
|
continue
|
||||||
@@ -167,7 +167,7 @@ class NameFinder(object):
|
|||||||
break
|
break
|
||||||
|
|
||||||
debug.dbg('finder.filter_name %s in (%s): %s@%s',
|
debug.dbg('finder.filter_name %s in (%s): %s@%s',
|
||||||
self._string_name, self._context, names, self._position)
|
self._string_name, self._value, names, self._position)
|
||||||
return list(names)
|
return list(names)
|
||||||
|
|
||||||
def _check_getattr(self, inst):
|
def _check_getattr(self, inst):
|
||||||
@@ -187,33 +187,33 @@ class NameFinder(object):
|
|||||||
return inst.execute_function_slots(names, name)
|
return inst.execute_function_slots(names, name)
|
||||||
|
|
||||||
def _names_to_types(self, names, attribute_lookup):
|
def _names_to_types(self, names, attribute_lookup):
|
||||||
contexts = ContextSet.from_sets(name.infer() for name in names)
|
values = ContextSet.from_sets(name.infer() for name in names)
|
||||||
|
|
||||||
debug.dbg('finder._names_to_types: %s -> %s', names, contexts)
|
debug.dbg('finder._names_to_types: %s -> %s', names, values)
|
||||||
if not names and self._context.is_instance() and not self._context.is_compiled():
|
if not names and self._value.is_instance() and not self._value.is_compiled():
|
||||||
# handling __getattr__ / __getattribute__
|
# handling __getattr__ / __getattribute__
|
||||||
return self._check_getattr(self._context)
|
return self._check_getattr(self._value)
|
||||||
|
|
||||||
# Add isinstance and other if/assert knowledge.
|
# Add isinstance and other if/assert knowledge.
|
||||||
if not contexts and isinstance(self._name, tree.Name) and \
|
if not values and isinstance(self._name, tree.Name) and \
|
||||||
not self._name_context.is_instance() and not self._context.is_compiled():
|
not self._name_value.is_instance() and not self._value.is_compiled():
|
||||||
flow_scope = self._name
|
flow_scope = self._name
|
||||||
base_nodes = [self._name_context.tree_node]
|
base_nodes = [self._name_value.tree_node]
|
||||||
|
|
||||||
if any(b.type in ('comp_for', 'sync_comp_for') for b in base_nodes):
|
if any(b.type in ('comp_for', 'sync_comp_for') for b in base_nodes):
|
||||||
return contexts
|
return values
|
||||||
while True:
|
while True:
|
||||||
flow_scope = get_parent_scope(flow_scope, include_flows=True)
|
flow_scope = get_parent_scope(flow_scope, include_flows=True)
|
||||||
n = _check_flow_information(self._name_context, flow_scope,
|
n = _check_flow_information(self._name_value, flow_scope,
|
||||||
self._name, self._position)
|
self._name, self._position)
|
||||||
if n is not None:
|
if n is not None:
|
||||||
return n
|
return n
|
||||||
if flow_scope in base_nodes:
|
if flow_scope in base_nodes:
|
||||||
break
|
break
|
||||||
return contexts
|
return values
|
||||||
|
|
||||||
|
|
||||||
def _check_flow_information(context, flow, search_name, pos):
|
def _check_flow_information(value, flow, search_name, pos):
|
||||||
""" Try to find out the type of a variable just with the information that
|
""" Try to find out the type of a variable just with the information that
|
||||||
is given by the flows: e.g. It is also responsible for assert checks.::
|
is given by the flows: e.g. It is also responsible for assert checks.::
|
||||||
|
|
||||||
@@ -241,7 +241,7 @@ def _check_flow_information(context, flow, search_name, pos):
|
|||||||
for name in names:
|
for name in names:
|
||||||
ass = search_ancestor(name, 'assert_stmt')
|
ass = search_ancestor(name, 'assert_stmt')
|
||||||
if ass is not None:
|
if ass is not None:
|
||||||
result = _check_isinstance_type(context, ass.assertion, search_name)
|
result = _check_isinstance_type(value, ass.assertion, search_name)
|
||||||
if result is not None:
|
if result is not None:
|
||||||
return result
|
return result
|
||||||
|
|
||||||
@@ -249,11 +249,11 @@ def _check_flow_information(context, flow, search_name, pos):
|
|||||||
potential_ifs = [c for c in flow.children[1::4] if c != ':']
|
potential_ifs = [c for c in flow.children[1::4] if c != ':']
|
||||||
for if_test in reversed(potential_ifs):
|
for if_test in reversed(potential_ifs):
|
||||||
if search_name.start_pos > if_test.end_pos:
|
if search_name.start_pos > if_test.end_pos:
|
||||||
return _check_isinstance_type(context, if_test, search_name)
|
return _check_isinstance_type(value, if_test, search_name)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
def _check_isinstance_type(context, element, search_name):
|
def _check_isinstance_type(value, element, search_name):
|
||||||
try:
|
try:
|
||||||
assert element.type in ('power', 'atom_expr')
|
assert element.type in ('power', 'atom_expr')
|
||||||
# this might be removed if we analyze and, etc
|
# this might be removed if we analyze and, etc
|
||||||
@@ -265,26 +265,26 @@ def _check_isinstance_type(context, element, search_name):
|
|||||||
|
|
||||||
# arglist stuff
|
# arglist stuff
|
||||||
arglist = trailer.children[1]
|
arglist = trailer.children[1]
|
||||||
args = TreeArguments(context.infer_state, context, arglist, trailer)
|
args = TreeArguments(value.infer_state, value, arglist, trailer)
|
||||||
param_list = list(args.unpack())
|
param_list = list(args.unpack())
|
||||||
# Disallow keyword arguments
|
# Disallow keyword arguments
|
||||||
assert len(param_list) == 2
|
assert len(param_list) == 2
|
||||||
(key1, lazy_context_object), (key2, lazy_context_cls) = param_list
|
(key1, lazy_value_object), (key2, lazy_value_cls) = param_list
|
||||||
assert key1 is None and key2 is None
|
assert key1 is None and key2 is None
|
||||||
call = helpers.call_of_leaf(search_name)
|
call = helpers.call_of_leaf(search_name)
|
||||||
is_instance_call = helpers.call_of_leaf(lazy_context_object.data)
|
is_instance_call = helpers.call_of_leaf(lazy_value_object.data)
|
||||||
# Do a simple get_code comparison. They should just have the same code,
|
# Do a simple get_code comparison. They should just have the same code,
|
||||||
# and everything will be all right.
|
# and everything will be all right.
|
||||||
normalize = context.infer_state.grammar._normalize
|
normalize = value.infer_state.grammar._normalize
|
||||||
assert normalize(is_instance_call) == normalize(call)
|
assert normalize(is_instance_call) == normalize(call)
|
||||||
except AssertionError:
|
except AssertionError:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
context_set = NO_CONTEXTS
|
value_set = NO_CONTEXTS
|
||||||
for cls_or_tup in lazy_context_cls.infer():
|
for cls_or_tup in lazy_value_cls.infer():
|
||||||
if isinstance(cls_or_tup, iterable.Sequence) and cls_or_tup.array_type == 'tuple':
|
if isinstance(cls_or_tup, iterable.Sequence) and cls_or_tup.array_type == 'tuple':
|
||||||
for lazy_context in cls_or_tup.py__iter__():
|
for lazy_value in cls_or_tup.py__iter__():
|
||||||
context_set |= lazy_context.infer().execute_with_values()
|
value_set |= lazy_value.infer().execute_with_values()
|
||||||
else:
|
else:
|
||||||
context_set |= cls_or_tup.execute_with_values()
|
value_set |= cls_or_tup.execute_with_values()
|
||||||
return context_set
|
return value_set
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ def _get_flow_scopes(node):
|
|||||||
yield node
|
yield node
|
||||||
|
|
||||||
|
|
||||||
def reachability_check(context, context_scope, node, origin_scope=None):
|
def reachability_check(value, value_scope, node, origin_scope=None):
|
||||||
first_flow_scope = get_parent_scope(node, include_flows=True)
|
first_flow_scope = get_parent_scope(node, include_flows=True)
|
||||||
if origin_scope is not None:
|
if origin_scope is not None:
|
||||||
origin_flow_scopes = list(_get_flow_scopes(origin_scope))
|
origin_flow_scopes = list(_get_flow_scopes(origin_scope))
|
||||||
@@ -75,22 +75,22 @@ def reachability_check(context, context_scope, node, origin_scope=None):
|
|||||||
return REACHABLE
|
return REACHABLE
|
||||||
origin_scope = origin_scope.parent
|
origin_scope = origin_scope.parent
|
||||||
|
|
||||||
return _break_check(context, context_scope, first_flow_scope, node)
|
return _break_check(value, value_scope, first_flow_scope, node)
|
||||||
|
|
||||||
|
|
||||||
def _break_check(context, context_scope, flow_scope, node):
|
def _break_check(value, value_scope, flow_scope, node):
|
||||||
reachable = REACHABLE
|
reachable = REACHABLE
|
||||||
if flow_scope.type == 'if_stmt':
|
if flow_scope.type == 'if_stmt':
|
||||||
if flow_scope.is_node_after_else(node):
|
if flow_scope.is_node_after_else(node):
|
||||||
for check_node in flow_scope.get_test_nodes():
|
for check_node in flow_scope.get_test_nodes():
|
||||||
reachable = _check_if(context, check_node)
|
reachable = _check_if(value, check_node)
|
||||||
if reachable in (REACHABLE, UNSURE):
|
if reachable in (REACHABLE, UNSURE):
|
||||||
break
|
break
|
||||||
reachable = reachable.invert()
|
reachable = reachable.invert()
|
||||||
else:
|
else:
|
||||||
flow_node = flow_scope.get_corresponding_test_node(node)
|
flow_node = flow_scope.get_corresponding_test_node(node)
|
||||||
if flow_node is not None:
|
if flow_node is not None:
|
||||||
reachable = _check_if(context, flow_node)
|
reachable = _check_if(value, flow_node)
|
||||||
elif flow_scope.type in ('try_stmt', 'while_stmt'):
|
elif flow_scope.type in ('try_stmt', 'while_stmt'):
|
||||||
return UNSURE
|
return UNSURE
|
||||||
|
|
||||||
@@ -98,19 +98,19 @@ def _break_check(context, context_scope, flow_scope, node):
|
|||||||
if reachable in (UNREACHABLE, UNSURE):
|
if reachable in (UNREACHABLE, UNSURE):
|
||||||
return reachable
|
return reachable
|
||||||
|
|
||||||
if context_scope != flow_scope and context_scope != flow_scope.parent:
|
if value_scope != flow_scope and value_scope != flow_scope.parent:
|
||||||
flow_scope = get_parent_scope(flow_scope, include_flows=True)
|
flow_scope = get_parent_scope(flow_scope, include_flows=True)
|
||||||
return reachable & _break_check(context, context_scope, flow_scope, node)
|
return reachable & _break_check(value, value_scope, flow_scope, node)
|
||||||
else:
|
else:
|
||||||
return reachable
|
return reachable
|
||||||
|
|
||||||
|
|
||||||
def _check_if(context, node):
|
def _check_if(value, node):
|
||||||
with execution_allowed(context.infer_state, node) as allowed:
|
with execution_allowed(value.infer_state, node) as allowed:
|
||||||
if not allowed:
|
if not allowed:
|
||||||
return UNSURE
|
return UNSURE
|
||||||
|
|
||||||
types = context.infer_node(node)
|
types = value.infer_node(node)
|
||||||
values = set(x.py__bool__() for x in types)
|
values = set(x.py__bool__() for x in types)
|
||||||
if len(values) == 1:
|
if len(values) == 1:
|
||||||
return Status.lookup_table[values.pop()]
|
return Status.lookup_table[values.pop()]
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ from jedi import debug
|
|||||||
from jedi import parser_utils
|
from jedi import parser_utils
|
||||||
|
|
||||||
|
|
||||||
def infer_annotation(context, annotation):
|
def infer_annotation(value, annotation):
|
||||||
"""
|
"""
|
||||||
Inferes an annotation node. This means that it inferes the part of
|
Inferes an annotation node. This means that it inferes the part of
|
||||||
`int` here:
|
`int` here:
|
||||||
@@ -30,37 +30,37 @@ def infer_annotation(context, annotation):
|
|||||||
|
|
||||||
Also checks for forward references (strings)
|
Also checks for forward references (strings)
|
||||||
"""
|
"""
|
||||||
context_set = context.infer_node(annotation)
|
value_set = value.infer_node(annotation)
|
||||||
if len(context_set) != 1:
|
if len(value_set) != 1:
|
||||||
debug.warning("Inferred typing index %s should lead to 1 object, "
|
debug.warning("Inferred typing index %s should lead to 1 object, "
|
||||||
" not %s" % (annotation, context_set))
|
" not %s" % (annotation, value_set))
|
||||||
return context_set
|
return value_set
|
||||||
|
|
||||||
inferred_context = list(context_set)[0]
|
inferred_value = list(value_set)[0]
|
||||||
if is_string(inferred_context):
|
if is_string(inferred_value):
|
||||||
result = _get_forward_reference_node(context, inferred_context.get_safe_value())
|
result = _get_forward_reference_node(value, inferred_value.get_safe_value())
|
||||||
if result is not None:
|
if result is not None:
|
||||||
return context.infer_node(result)
|
return value.infer_node(result)
|
||||||
return context_set
|
return value_set
|
||||||
|
|
||||||
|
|
||||||
def _infer_annotation_string(context, string, index=None):
|
def _infer_annotation_string(value, string, index=None):
|
||||||
node = _get_forward_reference_node(context, string)
|
node = _get_forward_reference_node(value, string)
|
||||||
if node is None:
|
if node is None:
|
||||||
return NO_CONTEXTS
|
return NO_CONTEXTS
|
||||||
|
|
||||||
context_set = context.infer_node(node)
|
value_set = value.infer_node(node)
|
||||||
if index is not None:
|
if index is not None:
|
||||||
context_set = context_set.filter(
|
value_set = value_set.filter(
|
||||||
lambda context: context.array_type == u'tuple' # noqa
|
lambda value: value.array_type == u'tuple' # noqa
|
||||||
and len(list(context.py__iter__())) >= index
|
and len(list(value.py__iter__())) >= index
|
||||||
).py__simple_getitem__(index)
|
).py__simple_getitem__(index)
|
||||||
return context_set
|
return value_set
|
||||||
|
|
||||||
|
|
||||||
def _get_forward_reference_node(context, string):
|
def _get_forward_reference_node(value, string):
|
||||||
try:
|
try:
|
||||||
new_node = context.infer_state.grammar.parse(
|
new_node = value.infer_state.grammar.parse(
|
||||||
force_unicode(string),
|
force_unicode(string),
|
||||||
start_symbol='eval_input',
|
start_symbol='eval_input',
|
||||||
error_recovery=False
|
error_recovery=False
|
||||||
@@ -69,9 +69,9 @@ def _get_forward_reference_node(context, string):
|
|||||||
debug.warning('Annotation not parsed: %s' % string)
|
debug.warning('Annotation not parsed: %s' % string)
|
||||||
return None
|
return None
|
||||||
else:
|
else:
|
||||||
module = context.tree_node.get_root_node()
|
module = value.tree_node.get_root_node()
|
||||||
parser_utils.move(new_node, module.end_pos[0])
|
parser_utils.move(new_node, module.end_pos[0])
|
||||||
new_node.parent = context.tree_node
|
new_node.parent = value.tree_node
|
||||||
return new_node
|
return new_node
|
||||||
|
|
||||||
|
|
||||||
@@ -107,26 +107,26 @@ def _split_comment_param_declaration(decl_text):
|
|||||||
|
|
||||||
|
|
||||||
@infer_state_method_cache()
|
@infer_state_method_cache()
|
||||||
def infer_param(execution_context, param):
|
def infer_param(execution_value, param):
|
||||||
contexts = _infer_param(execution_context, param)
|
values = _infer_param(execution_value, param)
|
||||||
infer_state = execution_context.infer_state
|
infer_state = execution_value.infer_state
|
||||||
if param.star_count == 1:
|
if param.star_count == 1:
|
||||||
tuple_ = builtin_from_name(infer_state, 'tuple')
|
tuple_ = builtin_from_name(infer_state, 'tuple')
|
||||||
return ContextSet([GenericClass(
|
return ContextSet([GenericClass(
|
||||||
tuple_,
|
tuple_,
|
||||||
generics=(contexts,),
|
generics=(values,),
|
||||||
) for c in contexts])
|
) for c in values])
|
||||||
elif param.star_count == 2:
|
elif param.star_count == 2:
|
||||||
dct = builtin_from_name(infer_state, 'dict')
|
dct = builtin_from_name(infer_state, 'dict')
|
||||||
return ContextSet([GenericClass(
|
return ContextSet([GenericClass(
|
||||||
dct,
|
dct,
|
||||||
generics=(ContextSet([builtin_from_name(infer_state, 'str')]), contexts),
|
generics=(ContextSet([builtin_from_name(infer_state, 'str')]), values),
|
||||||
) for c in contexts])
|
) for c in values])
|
||||||
pass
|
pass
|
||||||
return contexts
|
return values
|
||||||
|
|
||||||
|
|
||||||
def _infer_param(execution_context, param):
|
def _infer_param(execution_value, param):
|
||||||
"""
|
"""
|
||||||
Infers the type of a function parameter, using type annotations.
|
Infers the type of a function parameter, using type annotations.
|
||||||
"""
|
"""
|
||||||
@@ -158,8 +158,8 @@ def _infer_param(execution_context, param):
|
|||||||
"Comments length != Params length %s %s",
|
"Comments length != Params length %s %s",
|
||||||
params_comments, all_params
|
params_comments, all_params
|
||||||
)
|
)
|
||||||
from jedi.inference.context.instance import InstanceArguments
|
from jedi.inference.value.instance import InstanceArguments
|
||||||
if isinstance(execution_context.var_args, InstanceArguments):
|
if isinstance(execution_value.var_args, InstanceArguments):
|
||||||
if index == 0:
|
if index == 0:
|
||||||
# Assume it's self, which is already handled
|
# Assume it's self, which is already handled
|
||||||
return NO_CONTEXTS
|
return NO_CONTEXTS
|
||||||
@@ -169,12 +169,12 @@ def _infer_param(execution_context, param):
|
|||||||
|
|
||||||
param_comment = params_comments[index]
|
param_comment = params_comments[index]
|
||||||
return _infer_annotation_string(
|
return _infer_annotation_string(
|
||||||
execution_context.function_context.get_default_param_context(),
|
execution_value.function_value.get_default_param_value(),
|
||||||
param_comment
|
param_comment
|
||||||
)
|
)
|
||||||
# Annotations are like default params and resolve in the same way.
|
# Annotations are like default params and resolve in the same way.
|
||||||
context = execution_context.function_context.get_default_param_context()
|
value = execution_value.function_value.get_default_param_value()
|
||||||
return infer_annotation(context, annotation)
|
return infer_annotation(value, annotation)
|
||||||
|
|
||||||
|
|
||||||
def py__annotations__(funcdef):
|
def py__annotations__(funcdef):
|
||||||
@@ -191,16 +191,16 @@ def py__annotations__(funcdef):
|
|||||||
|
|
||||||
|
|
||||||
@infer_state_method_cache()
|
@infer_state_method_cache()
|
||||||
def infer_return_types(function_execution_context):
|
def infer_return_types(function_execution_value):
|
||||||
"""
|
"""
|
||||||
Infers the type of a function's return value,
|
Infers the type of a function's return value,
|
||||||
according to type annotations.
|
according to type annotations.
|
||||||
"""
|
"""
|
||||||
all_annotations = py__annotations__(function_execution_context.tree_node)
|
all_annotations = py__annotations__(function_execution_value.tree_node)
|
||||||
annotation = all_annotations.get("return", None)
|
annotation = all_annotations.get("return", None)
|
||||||
if annotation is None:
|
if annotation is None:
|
||||||
# If there is no Python 3-type annotation, look for a Python 2-type annotation
|
# If there is no Python 3-type annotation, look for a Python 2-type annotation
|
||||||
node = function_execution_context.tree_node
|
node = function_execution_value.tree_node
|
||||||
comment = parser_utils.get_following_comment_same_line(node)
|
comment = parser_utils.get_following_comment_same_line(node)
|
||||||
if comment is None:
|
if comment is None:
|
||||||
return NO_CONTEXTS
|
return NO_CONTEXTS
|
||||||
@@ -210,28 +210,28 @@ def infer_return_types(function_execution_context):
|
|||||||
return NO_CONTEXTS
|
return NO_CONTEXTS
|
||||||
|
|
||||||
return _infer_annotation_string(
|
return _infer_annotation_string(
|
||||||
function_execution_context.function_context.get_default_param_context(),
|
function_execution_value.function_value.get_default_param_value(),
|
||||||
match.group(1).strip()
|
match.group(1).strip()
|
||||||
).execute_annotation()
|
).execute_annotation()
|
||||||
if annotation is None:
|
if annotation is None:
|
||||||
return NO_CONTEXTS
|
return NO_CONTEXTS
|
||||||
|
|
||||||
context = function_execution_context.function_context.get_default_param_context()
|
value = function_execution_value.function_value.get_default_param_value()
|
||||||
unknown_type_vars = list(find_unknown_type_vars(context, annotation))
|
unknown_type_vars = list(find_unknown_type_vars(value, annotation))
|
||||||
annotation_contexts = infer_annotation(context, annotation)
|
annotation_values = infer_annotation(value, annotation)
|
||||||
if not unknown_type_vars:
|
if not unknown_type_vars:
|
||||||
return annotation_contexts.execute_annotation()
|
return annotation_values.execute_annotation()
|
||||||
|
|
||||||
type_var_dict = infer_type_vars_for_execution(function_execution_context, all_annotations)
|
type_var_dict = infer_type_vars_for_execution(function_execution_value, all_annotations)
|
||||||
|
|
||||||
return ContextSet.from_sets(
|
return ContextSet.from_sets(
|
||||||
ann.define_generics(type_var_dict)
|
ann.define_generics(type_var_dict)
|
||||||
if isinstance(ann, (AbstractAnnotatedClass, TypeVar)) else ContextSet({ann})
|
if isinstance(ann, (AbstractAnnotatedClass, TypeVar)) else ContextSet({ann})
|
||||||
for ann in annotation_contexts
|
for ann in annotation_values
|
||||||
).execute_annotation()
|
).execute_annotation()
|
||||||
|
|
||||||
|
|
||||||
def infer_type_vars_for_execution(execution_context, annotation_dict):
|
def infer_type_vars_for_execution(execution_value, annotation_dict):
|
||||||
"""
|
"""
|
||||||
Some functions use type vars that are not defined by the class, but rather
|
Some functions use type vars that are not defined by the class, but rather
|
||||||
only defined in the function. See for example `iter`. In those cases we
|
only defined in the function. See for example `iter`. In those cases we
|
||||||
@@ -241,48 +241,48 @@ def infer_type_vars_for_execution(execution_context, annotation_dict):
|
|||||||
2. Infer type vars with the execution state we have.
|
2. Infer type vars with the execution state we have.
|
||||||
3. Return the union of all type vars that have been found.
|
3. Return the union of all type vars that have been found.
|
||||||
"""
|
"""
|
||||||
context = execution_context.function_context.get_default_param_context()
|
value = execution_value.function_value.get_default_param_value()
|
||||||
|
|
||||||
annotation_variable_results = {}
|
annotation_variable_results = {}
|
||||||
executed_params, _ = execution_context.get_executed_params_and_issues()
|
executed_params, _ = execution_value.get_executed_params_and_issues()
|
||||||
for executed_param in executed_params:
|
for executed_param in executed_params:
|
||||||
try:
|
try:
|
||||||
annotation_node = annotation_dict[executed_param.string_name]
|
annotation_node = annotation_dict[executed_param.string_name]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
annotation_variables = find_unknown_type_vars(context, annotation_node)
|
annotation_variables = find_unknown_type_vars(value, annotation_node)
|
||||||
if annotation_variables:
|
if annotation_variables:
|
||||||
# Infer unknown type var
|
# Infer unknown type var
|
||||||
annotation_context_set = context.infer_node(annotation_node)
|
annotation_value_set = value.infer_node(annotation_node)
|
||||||
star_count = executed_param._param_node.star_count
|
star_count = executed_param._param_node.star_count
|
||||||
actual_context_set = executed_param.infer(use_hints=False)
|
actual_value_set = executed_param.infer(use_hints=False)
|
||||||
if star_count == 1:
|
if star_count == 1:
|
||||||
actual_context_set = actual_context_set.merge_types_of_iterate()
|
actual_value_set = actual_value_set.merge_types_of_iterate()
|
||||||
elif star_count == 2:
|
elif star_count == 2:
|
||||||
# TODO _dict_values is not public.
|
# TODO _dict_values is not public.
|
||||||
actual_context_set = actual_context_set.try_merge('_dict_values')
|
actual_value_set = actual_value_set.try_merge('_dict_values')
|
||||||
for ann in annotation_context_set:
|
for ann in annotation_value_set:
|
||||||
_merge_type_var_dicts(
|
_merge_type_var_dicts(
|
||||||
annotation_variable_results,
|
annotation_variable_results,
|
||||||
_infer_type_vars(ann, actual_context_set),
|
_infer_type_vars(ann, actual_value_set),
|
||||||
)
|
)
|
||||||
|
|
||||||
return annotation_variable_results
|
return annotation_variable_results
|
||||||
|
|
||||||
|
|
||||||
def _merge_type_var_dicts(base_dict, new_dict):
|
def _merge_type_var_dicts(base_dict, new_dict):
|
||||||
for type_var_name, contexts in new_dict.items():
|
for type_var_name, values in new_dict.items():
|
||||||
try:
|
try:
|
||||||
base_dict[type_var_name] |= contexts
|
base_dict[type_var_name] |= values
|
||||||
except KeyError:
|
except KeyError:
|
||||||
base_dict[type_var_name] = contexts
|
base_dict[type_var_name] = values
|
||||||
|
|
||||||
|
|
||||||
def _infer_type_vars(annotation_context, context_set):
|
def _infer_type_vars(annotation_value, value_set):
|
||||||
"""
|
"""
|
||||||
This function tries to find information about undefined type vars and
|
This function tries to find information about undefined type vars and
|
||||||
returns a dict from type var name to context set.
|
returns a dict from type var name to value set.
|
||||||
|
|
||||||
This is for example important to understand what `iter([1])` returns.
|
This is for example important to understand what `iter([1])` returns.
|
||||||
According to typeshed, `iter` returns an `Iterator[_T]`:
|
According to typeshed, `iter` returns an `Iterator[_T]`:
|
||||||
@@ -293,66 +293,66 @@ def _infer_type_vars(annotation_context, context_set):
|
|||||||
unpacks the `Iterable`.
|
unpacks the `Iterable`.
|
||||||
"""
|
"""
|
||||||
type_var_dict = {}
|
type_var_dict = {}
|
||||||
if isinstance(annotation_context, TypeVar):
|
if isinstance(annotation_value, TypeVar):
|
||||||
return {annotation_context.py__name__(): context_set.py__class__()}
|
return {annotation_value.py__name__(): value_set.py__class__()}
|
||||||
elif isinstance(annotation_context, LazyGenericClass):
|
elif isinstance(annotation_value, LazyGenericClass):
|
||||||
name = annotation_context.py__name__()
|
name = annotation_value.py__name__()
|
||||||
if name == 'Iterable':
|
if name == 'Iterable':
|
||||||
given = annotation_context.get_generics()
|
given = annotation_value.get_generics()
|
||||||
if given:
|
if given:
|
||||||
for nested_annotation_context in given[0]:
|
for nested_annotation_value in given[0]:
|
||||||
_merge_type_var_dicts(
|
_merge_type_var_dicts(
|
||||||
type_var_dict,
|
type_var_dict,
|
||||||
_infer_type_vars(
|
_infer_type_vars(
|
||||||
nested_annotation_context,
|
nested_annotation_value,
|
||||||
context_set.merge_types_of_iterate()
|
value_set.merge_types_of_iterate()
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
elif name == 'Mapping':
|
elif name == 'Mapping':
|
||||||
given = annotation_context.get_generics()
|
given = annotation_value.get_generics()
|
||||||
if len(given) == 2:
|
if len(given) == 2:
|
||||||
for context in context_set:
|
for value in value_set:
|
||||||
try:
|
try:
|
||||||
method = context.get_mapping_item_contexts
|
method = value.get_mapping_item_values
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
continue
|
continue
|
||||||
key_contexts, value_contexts = method()
|
key_values, value_values = method()
|
||||||
|
|
||||||
for nested_annotation_context in given[0]:
|
for nested_annotation_value in given[0]:
|
||||||
_merge_type_var_dicts(
|
_merge_type_var_dicts(
|
||||||
type_var_dict,
|
type_var_dict,
|
||||||
_infer_type_vars(
|
_infer_type_vars(
|
||||||
nested_annotation_context,
|
nested_annotation_value,
|
||||||
key_contexts,
|
key_values,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
for nested_annotation_context in given[1]:
|
for nested_annotation_value in given[1]:
|
||||||
_merge_type_var_dicts(
|
_merge_type_var_dicts(
|
||||||
type_var_dict,
|
type_var_dict,
|
||||||
_infer_type_vars(
|
_infer_type_vars(
|
||||||
nested_annotation_context,
|
nested_annotation_value,
|
||||||
value_contexts,
|
value_values,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
return type_var_dict
|
return type_var_dict
|
||||||
|
|
||||||
|
|
||||||
def find_type_from_comment_hint_for(context, node, name):
|
def find_type_from_comment_hint_for(value, node, name):
|
||||||
return _find_type_from_comment_hint(context, node, node.children[1], name)
|
return _find_type_from_comment_hint(value, node, node.children[1], name)
|
||||||
|
|
||||||
|
|
||||||
def find_type_from_comment_hint_with(context, node, name):
|
def find_type_from_comment_hint_with(value, node, name):
|
||||||
assert len(node.children[1].children) == 3, \
|
assert len(node.children[1].children) == 3, \
|
||||||
"Can only be here when children[1] is 'foo() as f'"
|
"Can only be here when children[1] is 'foo() as f'"
|
||||||
varlist = node.children[1].children[2]
|
varlist = node.children[1].children[2]
|
||||||
return _find_type_from_comment_hint(context, node, varlist, name)
|
return _find_type_from_comment_hint(value, node, varlist, name)
|
||||||
|
|
||||||
|
|
||||||
def find_type_from_comment_hint_assign(context, node, name):
|
def find_type_from_comment_hint_assign(value, node, name):
|
||||||
return _find_type_from_comment_hint(context, node, node.children[0], name)
|
return _find_type_from_comment_hint(value, node, node.children[0], name)
|
||||||
|
|
||||||
|
|
||||||
def _find_type_from_comment_hint(context, node, varlist, name):
|
def _find_type_from_comment_hint(value, node, varlist, name):
|
||||||
index = None
|
index = None
|
||||||
if varlist.type in ("testlist_star_expr", "exprlist", "testlist"):
|
if varlist.type in ("testlist_star_expr", "exprlist", "testlist"):
|
||||||
# something like "a, b = 1, 2"
|
# something like "a, b = 1, 2"
|
||||||
@@ -373,11 +373,11 @@ def _find_type_from_comment_hint(context, node, varlist, name):
|
|||||||
if match is None:
|
if match is None:
|
||||||
return []
|
return []
|
||||||
return _infer_annotation_string(
|
return _infer_annotation_string(
|
||||||
context, match.group(1).strip(), index
|
value, match.group(1).strip(), index
|
||||||
).execute_annotation()
|
).execute_annotation()
|
||||||
|
|
||||||
|
|
||||||
def find_unknown_type_vars(context, node):
|
def find_unknown_type_vars(value, node):
|
||||||
def check_node(node):
|
def check_node(node):
|
||||||
if node.type in ('atom_expr', 'power'):
|
if node.type in ('atom_expr', 'power'):
|
||||||
trailer = node.children[-1]
|
trailer = node.children[-1]
|
||||||
@@ -385,7 +385,7 @@ def find_unknown_type_vars(context, node):
|
|||||||
for subscript_node in _unpack_subscriptlist(trailer.children[1]):
|
for subscript_node in _unpack_subscriptlist(trailer.children[1]):
|
||||||
check_node(subscript_node)
|
check_node(subscript_node)
|
||||||
else:
|
else:
|
||||||
type_var_set = context.infer_node(node)
|
type_var_set = value.infer_node(node)
|
||||||
for type_var in type_var_set:
|
for type_var in type_var_set:
|
||||||
if isinstance(type_var, TypeVar) and type_var not in found:
|
if isinstance(type_var, TypeVar) and type_var not in found:
|
||||||
found.append(type_var)
|
found.append(type_var)
|
||||||
|
|||||||
@@ -2,47 +2,47 @@ from jedi import debug
|
|||||||
from jedi.inference.base_value import ContextSet, \
|
from jedi.inference.base_value import ContextSet, \
|
||||||
NO_CONTEXTS
|
NO_CONTEXTS
|
||||||
from jedi.inference.utils import to_list
|
from jedi.inference.utils import to_list
|
||||||
from jedi.inference.gradual.stub_context import StubModuleContext
|
from jedi.inference.gradual.stub_value import StubModuleContext
|
||||||
|
|
||||||
|
|
||||||
def _stub_to_python_context_set(stub_context, ignore_compiled=False):
|
def _stub_to_python_value_set(stub_value, ignore_compiled=False):
|
||||||
stub_module = stub_context.get_root_context()
|
stub_module = stub_value.get_root_value()
|
||||||
if not stub_module.is_stub():
|
if not stub_module.is_stub():
|
||||||
return ContextSet([stub_context])
|
return ContextSet([stub_value])
|
||||||
|
|
||||||
was_instance = stub_context.is_instance()
|
was_instance = stub_value.is_instance()
|
||||||
if was_instance:
|
if was_instance:
|
||||||
stub_context = stub_context.py__class__()
|
stub_value = stub_value.py__class__()
|
||||||
|
|
||||||
qualified_names = stub_context.get_qualified_names()
|
qualified_names = stub_value.get_qualified_names()
|
||||||
if qualified_names is None:
|
if qualified_names is None:
|
||||||
return NO_CONTEXTS
|
return NO_CONTEXTS
|
||||||
|
|
||||||
was_bound_method = stub_context.is_bound_method()
|
was_bound_method = stub_value.is_bound_method()
|
||||||
if was_bound_method:
|
if was_bound_method:
|
||||||
# Infer the object first. We can infer the method later.
|
# Infer the object first. We can infer the method later.
|
||||||
method_name = qualified_names[-1]
|
method_name = qualified_names[-1]
|
||||||
qualified_names = qualified_names[:-1]
|
qualified_names = qualified_names[:-1]
|
||||||
was_instance = True
|
was_instance = True
|
||||||
|
|
||||||
contexts = _infer_from_stub(stub_module, qualified_names, ignore_compiled)
|
values = _infer_from_stub(stub_module, qualified_names, ignore_compiled)
|
||||||
if was_instance:
|
if was_instance:
|
||||||
contexts = ContextSet.from_sets(
|
values = ContextSet.from_sets(
|
||||||
c.execute_with_values()
|
c.execute_with_values()
|
||||||
for c in contexts
|
for c in values
|
||||||
if c.is_class()
|
if c.is_class()
|
||||||
)
|
)
|
||||||
if was_bound_method:
|
if was_bound_method:
|
||||||
# Now that the instance has been properly created, we can simply get
|
# Now that the instance has been properly created, we can simply get
|
||||||
# the method.
|
# the method.
|
||||||
contexts = contexts.py__getattribute__(method_name)
|
values = values.py__getattribute__(method_name)
|
||||||
return contexts
|
return values
|
||||||
|
|
||||||
|
|
||||||
def _infer_from_stub(stub_module, qualified_names, ignore_compiled):
|
def _infer_from_stub(stub_module, qualified_names, ignore_compiled):
|
||||||
from jedi.inference.compiled.mixed import MixedObject
|
from jedi.inference.compiled.mixed import MixedObject
|
||||||
assert isinstance(stub_module, (StubModuleContext, MixedObject)), stub_module
|
assert isinstance(stub_module, (StubModuleContext, MixedObject)), stub_module
|
||||||
non_stubs = stub_module.non_stub_context_set
|
non_stubs = stub_module.non_stub_value_set
|
||||||
if ignore_compiled:
|
if ignore_compiled:
|
||||||
non_stubs = non_stubs.filter(lambda c: not c.is_compiled())
|
non_stubs = non_stubs.filter(lambda c: not c.is_compiled())
|
||||||
for name in qualified_names:
|
for name in qualified_names:
|
||||||
@@ -53,28 +53,28 @@ def _infer_from_stub(stub_module, qualified_names, ignore_compiled):
|
|||||||
@to_list
|
@to_list
|
||||||
def _try_stub_to_python_names(names, prefer_stub_to_compiled=False):
|
def _try_stub_to_python_names(names, prefer_stub_to_compiled=False):
|
||||||
for name in names:
|
for name in names:
|
||||||
module = name.get_root_context()
|
module = name.get_root_value()
|
||||||
if not module.is_stub():
|
if not module.is_stub():
|
||||||
yield name
|
yield name
|
||||||
continue
|
continue
|
||||||
|
|
||||||
name_list = name.get_qualified_names()
|
name_list = name.get_qualified_names()
|
||||||
if name_list is None:
|
if name_list is None:
|
||||||
contexts = NO_CONTEXTS
|
values = NO_CONTEXTS
|
||||||
else:
|
else:
|
||||||
contexts = _infer_from_stub(
|
values = _infer_from_stub(
|
||||||
module,
|
module,
|
||||||
name_list[:-1],
|
name_list[:-1],
|
||||||
ignore_compiled=prefer_stub_to_compiled,
|
ignore_compiled=prefer_stub_to_compiled,
|
||||||
)
|
)
|
||||||
if contexts and name_list:
|
if values and name_list:
|
||||||
new_names = contexts.py__getattribute__(name_list[-1], is_goto=True)
|
new_names = values.py__getattribute__(name_list[-1], is_goto=True)
|
||||||
for new_name in new_names:
|
for new_name in new_names:
|
||||||
yield new_name
|
yield new_name
|
||||||
if new_names:
|
if new_names:
|
||||||
continue
|
continue
|
||||||
elif contexts:
|
elif values:
|
||||||
for c in contexts:
|
for c in values:
|
||||||
yield c.name
|
yield c.name
|
||||||
continue
|
continue
|
||||||
# This is the part where if we haven't found anything, just return the
|
# This is the part where if we haven't found anything, just return the
|
||||||
@@ -89,8 +89,8 @@ def _load_stub_module(module):
|
|||||||
return _try_to_load_stub_cached(
|
return _try_to_load_stub_cached(
|
||||||
module.infer_state,
|
module.infer_state,
|
||||||
import_names=module.string_names,
|
import_names=module.string_names,
|
||||||
python_context_set=ContextSet([module]),
|
python_value_set=ContextSet([module]),
|
||||||
parent_module_context=None,
|
parent_module_value=None,
|
||||||
sys_path=module.infer_state.get_sys_path(),
|
sys_path=module.infer_state.get_sys_path(),
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -98,7 +98,7 @@ def _load_stub_module(module):
|
|||||||
@to_list
|
@to_list
|
||||||
def _python_to_stub_names(names, fallback_to_python=False):
|
def _python_to_stub_names(names, fallback_to_python=False):
|
||||||
for name in names:
|
for name in names:
|
||||||
module = name.get_root_context()
|
module = name.get_root_value()
|
||||||
if module.is_stub():
|
if module.is_stub():
|
||||||
yield name
|
yield name
|
||||||
continue
|
continue
|
||||||
@@ -144,56 +144,56 @@ def convert_names(names, only_stubs=False, prefer_stubs=False):
|
|||||||
return _try_stub_to_python_names(names, prefer_stub_to_compiled=True)
|
return _try_stub_to_python_names(names, prefer_stub_to_compiled=True)
|
||||||
|
|
||||||
|
|
||||||
def convert_contexts(contexts, only_stubs=False, prefer_stubs=False, ignore_compiled=True):
|
def convert_values(values, only_stubs=False, prefer_stubs=False, ignore_compiled=True):
|
||||||
assert not (only_stubs and prefer_stubs)
|
assert not (only_stubs and prefer_stubs)
|
||||||
with debug.increase_indent_cm('convert contexts'):
|
with debug.increase_indent_cm('convert values'):
|
||||||
if only_stubs or prefer_stubs:
|
if only_stubs or prefer_stubs:
|
||||||
return ContextSet.from_sets(
|
return ContextSet.from_sets(
|
||||||
to_stub(context)
|
to_stub(value)
|
||||||
or (ContextSet({context}) if prefer_stubs else NO_CONTEXTS)
|
or (ContextSet({value}) if prefer_stubs else NO_CONTEXTS)
|
||||||
for context in contexts
|
for value in values
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
return ContextSet.from_sets(
|
return ContextSet.from_sets(
|
||||||
_stub_to_python_context_set(stub_context, ignore_compiled=ignore_compiled)
|
_stub_to_python_value_set(stub_value, ignore_compiled=ignore_compiled)
|
||||||
or ContextSet({stub_context})
|
or ContextSet({stub_value})
|
||||||
for stub_context in contexts
|
for stub_value in values
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
# TODO merge with _python_to_stub_names?
|
# TODO merge with _python_to_stub_names?
|
||||||
def to_stub(context):
|
def to_stub(value):
|
||||||
if context.is_stub():
|
if value.is_stub():
|
||||||
return ContextSet([context])
|
return ContextSet([value])
|
||||||
|
|
||||||
was_instance = context.is_instance()
|
was_instance = value.is_instance()
|
||||||
if was_instance:
|
if was_instance:
|
||||||
context = context.py__class__()
|
value = value.py__class__()
|
||||||
|
|
||||||
qualified_names = context.get_qualified_names()
|
qualified_names = value.get_qualified_names()
|
||||||
stub_module = _load_stub_module(context.get_root_context())
|
stub_module = _load_stub_module(value.get_root_value())
|
||||||
if stub_module is None or qualified_names is None:
|
if stub_module is None or qualified_names is None:
|
||||||
return NO_CONTEXTS
|
return NO_CONTEXTS
|
||||||
|
|
||||||
was_bound_method = context.is_bound_method()
|
was_bound_method = value.is_bound_method()
|
||||||
if was_bound_method:
|
if was_bound_method:
|
||||||
# Infer the object first. We can infer the method later.
|
# Infer the object first. We can infer the method later.
|
||||||
method_name = qualified_names[-1]
|
method_name = qualified_names[-1]
|
||||||
qualified_names = qualified_names[:-1]
|
qualified_names = qualified_names[:-1]
|
||||||
was_instance = True
|
was_instance = True
|
||||||
|
|
||||||
stub_contexts = ContextSet([stub_module])
|
stub_values = ContextSet([stub_module])
|
||||||
for name in qualified_names:
|
for name in qualified_names:
|
||||||
stub_contexts = stub_contexts.py__getattribute__(name)
|
stub_values = stub_values.py__getattribute__(name)
|
||||||
|
|
||||||
if was_instance:
|
if was_instance:
|
||||||
stub_contexts = ContextSet.from_sets(
|
stub_values = ContextSet.from_sets(
|
||||||
c.execute_with_values()
|
c.execute_with_values()
|
||||||
for c in stub_contexts
|
for c in stub_values
|
||||||
if c.is_class()
|
if c.is_class()
|
||||||
)
|
)
|
||||||
if was_bound_method:
|
if was_bound_method:
|
||||||
# Now that the instance has been properly created, we can simply get
|
# Now that the instance has been properly created, we can simply get
|
||||||
# the method.
|
# the method.
|
||||||
stub_contexts = stub_contexts.py__getattribute__(method_name)
|
stub_values = stub_values.py__getattribute__(method_name)
|
||||||
return stub_contexts
|
return stub_values
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
from jedi.inference.base_value import ContextWrapper
|
from jedi.inference.base_value import ContextWrapper
|
||||||
from jedi.inference.context.module import ModuleContext
|
from jedi.inference.value.module import ModuleContext
|
||||||
from jedi.inference.filters import ParserTreeFilter, \
|
from jedi.inference.filters import ParserTreeFilter, \
|
||||||
TreeNameDefinition
|
TreeNameDefinition
|
||||||
from jedi.inference.gradual.typing import TypingModuleFilterWrapper
|
from jedi.inference.gradual.typing import TypingModuleFilterWrapper
|
||||||
|
|
||||||
|
|
||||||
class StubModuleContext(ModuleContext):
|
class StubModuleContext(ModuleContext):
|
||||||
def __init__(self, non_stub_context_set, *args, **kwargs):
|
def __init__(self, non_stub_value_set, *args, **kwargs):
|
||||||
super(StubModuleContext, self).__init__(*args, **kwargs)
|
super(StubModuleContext, self).__init__(*args, **kwargs)
|
||||||
self.non_stub_context_set = non_stub_context_set
|
self.non_stub_value_set = non_stub_value_set
|
||||||
|
|
||||||
def is_stub(self):
|
def is_stub(self):
|
||||||
return True
|
return True
|
||||||
@@ -20,9 +20,9 @@ class StubModuleContext(ModuleContext):
|
|||||||
there are for example no stubs for `json.tool`.
|
there are for example no stubs for `json.tool`.
|
||||||
"""
|
"""
|
||||||
names = {}
|
names = {}
|
||||||
for context in self.non_stub_context_set:
|
for value in self.non_stub_value_set:
|
||||||
try:
|
try:
|
||||||
method = context.sub_modules_dict
|
method = value.sub_modules_dict
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
@@ -31,13 +31,13 @@ class StubModuleContext(ModuleContext):
|
|||||||
return names
|
return names
|
||||||
|
|
||||||
def _get_first_non_stub_filters(self):
|
def _get_first_non_stub_filters(self):
|
||||||
for context in self.non_stub_context_set:
|
for value in self.non_stub_value_set:
|
||||||
yield next(context.get_filters(search_global=False))
|
yield next(value.get_filters(search_global=False))
|
||||||
|
|
||||||
def _get_stub_filters(self, search_global, **filter_kwargs):
|
def _get_stub_filters(self, search_global, **filter_kwargs):
|
||||||
return [StubFilter(
|
return [StubFilter(
|
||||||
self.infer_state,
|
self.infer_state,
|
||||||
context=self,
|
value=self,
|
||||||
search_global=search_global,
|
search_global=search_global,
|
||||||
**filter_kwargs
|
**filter_kwargs
|
||||||
)] + list(self.iter_star_filters(search_global=search_global))
|
)] + list(self.iter_star_filters(search_global=search_global))
|
||||||
@@ -72,7 +72,7 @@ class TypingModuleWrapper(StubModuleContext):
|
|||||||
class _StubName(TreeNameDefinition):
|
class _StubName(TreeNameDefinition):
|
||||||
def infer(self):
|
def infer(self):
|
||||||
inferred = super(_StubName, self).infer()
|
inferred = super(_StubName, self).infer()
|
||||||
if self.string_name == 'version_info' and self.get_root_context().py__name__() == 'sys':
|
if self.string_name == 'version_info' and self.get_root_value().py__name__() == 'sys':
|
||||||
return [VersionInfo(c) for c in inferred]
|
return [VersionInfo(c) for c in inferred]
|
||||||
return inferred
|
return inferred
|
||||||
|
|
||||||
@@ -6,7 +6,7 @@ from jedi.file_io import FileIO
|
|||||||
from jedi._compatibility import FileNotFoundError, cast_path
|
from jedi._compatibility import FileNotFoundError, cast_path
|
||||||
from jedi.parser_utils import get_cached_code_lines
|
from jedi.parser_utils import get_cached_code_lines
|
||||||
from jedi.inference.base_value import ContextSet, NO_CONTEXTS
|
from jedi.inference.base_value import ContextSet, NO_CONTEXTS
|
||||||
from jedi.inference.gradual.stub_context import TypingModuleWrapper, StubModuleContext
|
from jedi.inference.gradual.stub_value import TypingModuleWrapper, StubModuleContext
|
||||||
|
|
||||||
_jedi_path = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
_jedi_path = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||||
TYPESHED_PATH = os.path.join(_jedi_path, 'third_party', 'typeshed')
|
TYPESHED_PATH = os.path.join(_jedi_path, 'third_party', 'typeshed')
|
||||||
@@ -89,38 +89,38 @@ def _cache_stub_file_map(version_info):
|
|||||||
|
|
||||||
def import_module_decorator(func):
|
def import_module_decorator(func):
|
||||||
@wraps(func)
|
@wraps(func)
|
||||||
def wrapper(infer_state, import_names, parent_module_context, sys_path, prefer_stubs):
|
def wrapper(infer_state, import_names, parent_module_value, sys_path, prefer_stubs):
|
||||||
try:
|
try:
|
||||||
python_context_set = infer_state.module_cache.get(import_names)
|
python_value_set = infer_state.module_cache.get(import_names)
|
||||||
except KeyError:
|
except KeyError:
|
||||||
if parent_module_context is not None and parent_module_context.is_stub():
|
if parent_module_value is not None and parent_module_value.is_stub():
|
||||||
parent_module_contexts = parent_module_context.non_stub_context_set
|
parent_module_values = parent_module_value.non_stub_value_set
|
||||||
else:
|
else:
|
||||||
parent_module_contexts = [parent_module_context]
|
parent_module_values = [parent_module_value]
|
||||||
if import_names == ('os', 'path'):
|
if import_names == ('os', 'path'):
|
||||||
# This is a huge exception, we follow a nested import
|
# This is a huge exception, we follow a nested import
|
||||||
# ``os.path``, because it's a very important one in Python
|
# ``os.path``, because it's a very important one in Python
|
||||||
# that is being achieved by messing with ``sys.modules`` in
|
# that is being achieved by messing with ``sys.modules`` in
|
||||||
# ``os``.
|
# ``os``.
|
||||||
python_parent = next(iter(parent_module_contexts))
|
python_parent = next(iter(parent_module_values))
|
||||||
if python_parent is None:
|
if python_parent is None:
|
||||||
python_parent, = infer_state.import_module(('os',), prefer_stubs=False)
|
python_parent, = infer_state.import_module(('os',), prefer_stubs=False)
|
||||||
python_context_set = python_parent.py__getattribute__('path')
|
python_value_set = python_parent.py__getattribute__('path')
|
||||||
else:
|
else:
|
||||||
python_context_set = ContextSet.from_sets(
|
python_value_set = ContextSet.from_sets(
|
||||||
func(infer_state, import_names, p, sys_path,)
|
func(infer_state, import_names, p, sys_path,)
|
||||||
for p in parent_module_contexts
|
for p in parent_module_values
|
||||||
)
|
)
|
||||||
infer_state.module_cache.add(import_names, python_context_set)
|
infer_state.module_cache.add(import_names, python_value_set)
|
||||||
|
|
||||||
if not prefer_stubs:
|
if not prefer_stubs:
|
||||||
return python_context_set
|
return python_value_set
|
||||||
|
|
||||||
stub = _try_to_load_stub_cached(infer_state, import_names, python_context_set,
|
stub = _try_to_load_stub_cached(infer_state, import_names, python_value_set,
|
||||||
parent_module_context, sys_path)
|
parent_module_value, sys_path)
|
||||||
if stub is not None:
|
if stub is not None:
|
||||||
return ContextSet([stub])
|
return ContextSet([stub])
|
||||||
return python_context_set
|
return python_value_set
|
||||||
|
|
||||||
return wrapper
|
return wrapper
|
||||||
|
|
||||||
@@ -139,19 +139,19 @@ def _try_to_load_stub_cached(infer_state, import_names, *args, **kwargs):
|
|||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
def _try_to_load_stub(infer_state, import_names, python_context_set,
|
def _try_to_load_stub(infer_state, import_names, python_value_set,
|
||||||
parent_module_context, sys_path):
|
parent_module_value, sys_path):
|
||||||
"""
|
"""
|
||||||
Trying to load a stub for a set of import_names.
|
Trying to load a stub for a set of import_names.
|
||||||
|
|
||||||
This is modelled to work like "PEP 561 -- Distributing and Packaging Type
|
This is modelled to work like "PEP 561 -- Distributing and Packaging Type
|
||||||
Information", see https://www.python.org/dev/peps/pep-0561.
|
Information", see https://www.python.org/dev/peps/pep-0561.
|
||||||
"""
|
"""
|
||||||
if parent_module_context is None and len(import_names) > 1:
|
if parent_module_value is None and len(import_names) > 1:
|
||||||
try:
|
try:
|
||||||
parent_module_context = _try_to_load_stub_cached(
|
parent_module_value = _try_to_load_stub_cached(
|
||||||
infer_state, import_names[:-1], NO_CONTEXTS,
|
infer_state, import_names[:-1], NO_CONTEXTS,
|
||||||
parent_module_context=None, sys_path=sys_path)
|
parent_module_value=None, sys_path=sys_path)
|
||||||
except KeyError:
|
except KeyError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@@ -162,7 +162,7 @@ def _try_to_load_stub(infer_state, import_names, python_context_set,
|
|||||||
init = os.path.join(p, *import_names) + '-stubs' + os.path.sep + '__init__.pyi'
|
init = os.path.join(p, *import_names) + '-stubs' + os.path.sep + '__init__.pyi'
|
||||||
m = _try_to_load_stub_from_file(
|
m = _try_to_load_stub_from_file(
|
||||||
infer_state,
|
infer_state,
|
||||||
python_context_set,
|
python_value_set,
|
||||||
file_io=FileIO(init),
|
file_io=FileIO(init),
|
||||||
import_names=import_names,
|
import_names=import_names,
|
||||||
)
|
)
|
||||||
@@ -170,7 +170,7 @@ def _try_to_load_stub(infer_state, import_names, python_context_set,
|
|||||||
return m
|
return m
|
||||||
|
|
||||||
# 2. Try to load pyi files next to py files.
|
# 2. Try to load pyi files next to py files.
|
||||||
for c in python_context_set:
|
for c in python_value_set:
|
||||||
try:
|
try:
|
||||||
method = c.py__file__
|
method = c.py__file__
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
@@ -186,7 +186,7 @@ def _try_to_load_stub(infer_state, import_names, python_context_set,
|
|||||||
for file_path in file_paths:
|
for file_path in file_paths:
|
||||||
m = _try_to_load_stub_from_file(
|
m = _try_to_load_stub_from_file(
|
||||||
infer_state,
|
infer_state,
|
||||||
python_context_set,
|
python_value_set,
|
||||||
# The file path should end with .pyi
|
# The file path should end with .pyi
|
||||||
file_io=FileIO(file_path),
|
file_io=FileIO(file_path),
|
||||||
import_names=import_names,
|
import_names=import_names,
|
||||||
@@ -195,15 +195,15 @@ def _try_to_load_stub(infer_state, import_names, python_context_set,
|
|||||||
return m
|
return m
|
||||||
|
|
||||||
# 3. Try to load typeshed
|
# 3. Try to load typeshed
|
||||||
m = _load_from_typeshed(infer_state, python_context_set, parent_module_context, import_names)
|
m = _load_from_typeshed(infer_state, python_value_set, parent_module_value, import_names)
|
||||||
if m is not None:
|
if m is not None:
|
||||||
return m
|
return m
|
||||||
|
|
||||||
# 4. Try to load pyi file somewhere if python_context_set was not defined.
|
# 4. Try to load pyi file somewhere if python_value_set was not defined.
|
||||||
if not python_context_set:
|
if not python_value_set:
|
||||||
if parent_module_context is not None:
|
if parent_module_value is not None:
|
||||||
try:
|
try:
|
||||||
method = parent_module_context.py__path__
|
method = parent_module_value.py__path__
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
check_path = []
|
check_path = []
|
||||||
else:
|
else:
|
||||||
@@ -217,7 +217,7 @@ def _try_to_load_stub(infer_state, import_names, python_context_set,
|
|||||||
for p in check_path:
|
for p in check_path:
|
||||||
m = _try_to_load_stub_from_file(
|
m = _try_to_load_stub_from_file(
|
||||||
infer_state,
|
infer_state,
|
||||||
python_context_set,
|
python_value_set,
|
||||||
file_io=FileIO(os.path.join(p, *names_for_path) + '.pyi'),
|
file_io=FileIO(os.path.join(p, *names_for_path) + '.pyi'),
|
||||||
import_names=import_names,
|
import_names=import_names,
|
||||||
)
|
)
|
||||||
@@ -229,18 +229,18 @@ def _try_to_load_stub(infer_state, import_names, python_context_set,
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def _load_from_typeshed(infer_state, python_context_set, parent_module_context, import_names):
|
def _load_from_typeshed(infer_state, python_value_set, parent_module_value, import_names):
|
||||||
import_name = import_names[-1]
|
import_name = import_names[-1]
|
||||||
map_ = None
|
map_ = None
|
||||||
if len(import_names) == 1:
|
if len(import_names) == 1:
|
||||||
map_ = _cache_stub_file_map(infer_state.grammar.version_info)
|
map_ = _cache_stub_file_map(infer_state.grammar.version_info)
|
||||||
import_name = _IMPORT_MAP.get(import_name, import_name)
|
import_name = _IMPORT_MAP.get(import_name, import_name)
|
||||||
elif isinstance(parent_module_context, StubModuleContext):
|
elif isinstance(parent_module_value, StubModuleContext):
|
||||||
if not parent_module_context.is_package:
|
if not parent_module_value.is_package:
|
||||||
# Only if it's a package (= a folder) something can be
|
# Only if it's a package (= a folder) something can be
|
||||||
# imported.
|
# imported.
|
||||||
return None
|
return None
|
||||||
path = parent_module_context.py__path__()
|
path = parent_module_value.py__path__()
|
||||||
map_ = _merge_create_stub_map(path)
|
map_ = _merge_create_stub_map(path)
|
||||||
|
|
||||||
if map_ is not None:
|
if map_ is not None:
|
||||||
@@ -248,13 +248,13 @@ def _load_from_typeshed(infer_state, python_context_set, parent_module_context,
|
|||||||
if path is not None:
|
if path is not None:
|
||||||
return _try_to_load_stub_from_file(
|
return _try_to_load_stub_from_file(
|
||||||
infer_state,
|
infer_state,
|
||||||
python_context_set,
|
python_value_set,
|
||||||
file_io=FileIO(path),
|
file_io=FileIO(path),
|
||||||
import_names=import_names,
|
import_names=import_names,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def _try_to_load_stub_from_file(infer_state, python_context_set, file_io, import_names):
|
def _try_to_load_stub_from_file(infer_state, python_value_set, file_io, import_names):
|
||||||
try:
|
try:
|
||||||
stub_module_node = infer_state.parse(
|
stub_module_node = infer_state.parse(
|
||||||
file_io=file_io,
|
file_io=file_io,
|
||||||
@@ -266,19 +266,19 @@ def _try_to_load_stub_from_file(infer_state, python_context_set, file_io, import
|
|||||||
return None
|
return None
|
||||||
else:
|
else:
|
||||||
return create_stub_module(
|
return create_stub_module(
|
||||||
infer_state, python_context_set, stub_module_node, file_io,
|
infer_state, python_value_set, stub_module_node, file_io,
|
||||||
import_names
|
import_names
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def create_stub_module(infer_state, python_context_set, stub_module_node, file_io, import_names):
|
def create_stub_module(infer_state, python_value_set, stub_module_node, file_io, import_names):
|
||||||
if import_names == ('typing',):
|
if import_names == ('typing',):
|
||||||
module_cls = TypingModuleWrapper
|
module_cls = TypingModuleWrapper
|
||||||
else:
|
else:
|
||||||
module_cls = StubModuleContext
|
module_cls = StubModuleContext
|
||||||
file_name = os.path.basename(file_io.path)
|
file_name = os.path.basename(file_io.path)
|
||||||
stub_module_context = module_cls(
|
stub_module_value = module_cls(
|
||||||
python_context_set, infer_state, stub_module_node,
|
python_value_set, infer_state, stub_module_node,
|
||||||
file_io=file_io,
|
file_io=file_io,
|
||||||
string_names=import_names,
|
string_names=import_names,
|
||||||
# The code was loaded with latest_grammar, so use
|
# The code was loaded with latest_grammar, so use
|
||||||
@@ -286,4 +286,4 @@ def create_stub_module(infer_state, python_context_set, stub_module_node, file_i
|
|||||||
code_lines=get_cached_code_lines(infer_state.latest_grammar, file_io.path),
|
code_lines=get_cached_code_lines(infer_state.latest_grammar, file_io.path),
|
||||||
is_package=file_name == '__init__.pyi',
|
is_package=file_name == '__init__.pyi',
|
||||||
)
|
)
|
||||||
return stub_module_context
|
return stub_module_value
|
||||||
|
|||||||
+138
-138
@@ -1,7 +1,7 @@
|
|||||||
"""
|
"""
|
||||||
We need to somehow work with the typing objects. Since the typing objects are
|
We need to somehow work with the typing objects. Since the typing objects are
|
||||||
pretty bare we need to add all the Jedi customizations to make them work as
|
pretty bare we need to add all the Jedi customizations to make them work as
|
||||||
contexts.
|
values.
|
||||||
|
|
||||||
This file deals with all the typing.py cases.
|
This file deals with all the typing.py cases.
|
||||||
"""
|
"""
|
||||||
@@ -10,16 +10,16 @@ from jedi import debug
|
|||||||
from jedi.inference.cache import infer_state_method_cache
|
from jedi.inference.cache import infer_state_method_cache
|
||||||
from jedi.inference.compiled import builtin_from_name
|
from jedi.inference.compiled import builtin_from_name
|
||||||
from jedi.inference.base_value import ContextSet, NO_CONTEXTS, Context, \
|
from jedi.inference.base_value import ContextSet, NO_CONTEXTS, Context, \
|
||||||
iterator_to_context_set, ContextWrapper, LazyContextWrapper
|
iterator_to_value_set, ContextWrapper, LazyContextWrapper
|
||||||
from jedi.inference.lazy_context import LazyKnownContexts
|
from jedi.inference.lazy_value import LazyKnownContexts
|
||||||
from jedi.inference.context.iterable import SequenceLiteralContext
|
from jedi.inference.value.iterable import SequenceLiteralContext
|
||||||
from jedi.inference.arguments import repack_with_argument_clinic
|
from jedi.inference.arguments import repack_with_argument_clinic
|
||||||
from jedi.inference.utils import to_list
|
from jedi.inference.utils import to_list
|
||||||
from jedi.inference.filters import FilterWrapper
|
from jedi.inference.filters import FilterWrapper
|
||||||
from jedi.inference.names import NameWrapper, AbstractTreeName, \
|
from jedi.inference.names import NameWrapper, AbstractTreeName, \
|
||||||
AbstractNameDefinition, ContextName
|
AbstractNameDefinition, ContextName
|
||||||
from jedi.inference.helpers import is_string
|
from jedi.inference.helpers import is_string
|
||||||
from jedi.inference.context.klass import ClassMixin, ClassFilter
|
from jedi.inference.value.klass import ClassMixin, ClassFilter
|
||||||
|
|
||||||
_PROXY_CLASS_TYPES = 'Tuple Generic Protocol Callable Type'.split()
|
_PROXY_CLASS_TYPES = 'Tuple Generic Protocol Callable Type'.split()
|
||||||
_TYPE_ALIAS_TYPES = {
|
_TYPE_ALIAS_TYPES = {
|
||||||
@@ -36,17 +36,17 @@ _PROXY_TYPES = 'Optional Union ClassVar'.split()
|
|||||||
|
|
||||||
|
|
||||||
class TypingName(AbstractTreeName):
|
class TypingName(AbstractTreeName):
|
||||||
def __init__(self, context, other_name):
|
def __init__(self, value, other_name):
|
||||||
super(TypingName, self).__init__(context.parent_context, other_name.tree_name)
|
super(TypingName, self).__init__(value.parent_value, other_name.tree_name)
|
||||||
self._context = context
|
self._value = value
|
||||||
|
|
||||||
def infer(self):
|
def infer(self):
|
||||||
return ContextSet([self._context])
|
return ContextSet([self._value])
|
||||||
|
|
||||||
|
|
||||||
class _BaseTypingContext(Context):
|
class _BaseTypingContext(Context):
|
||||||
def __init__(self, infer_state, parent_context, tree_name):
|
def __init__(self, infer_state, parent_value, tree_name):
|
||||||
super(_BaseTypingContext, self).__init__(infer_state, parent_context)
|
super(_BaseTypingContext, self).__init__(infer_state, parent_value)
|
||||||
self._tree_name = tree_name
|
self._tree_name = tree_name
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@@ -87,39 +87,39 @@ class TypingModuleName(NameWrapper):
|
|||||||
|
|
||||||
def _remap(self):
|
def _remap(self):
|
||||||
name = self.string_name
|
name = self.string_name
|
||||||
infer_state = self.parent_context.infer_state
|
infer_state = self.parent_value.infer_state
|
||||||
try:
|
try:
|
||||||
actual = _TYPE_ALIAS_TYPES[name]
|
actual = _TYPE_ALIAS_TYPES[name]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
yield TypeAlias.create_cached(infer_state, self.parent_context, self.tree_name, actual)
|
yield TypeAlias.create_cached(infer_state, self.parent_value, self.tree_name, actual)
|
||||||
return
|
return
|
||||||
|
|
||||||
if name in _PROXY_CLASS_TYPES:
|
if name in _PROXY_CLASS_TYPES:
|
||||||
yield TypingClassContext.create_cached(infer_state, self.parent_context, self.tree_name)
|
yield TypingClassContext.create_cached(infer_state, self.parent_value, self.tree_name)
|
||||||
elif name in _PROXY_TYPES:
|
elif name in _PROXY_TYPES:
|
||||||
yield TypingContext.create_cached(infer_state, self.parent_context, self.tree_name)
|
yield TypingContext.create_cached(infer_state, self.parent_value, self.tree_name)
|
||||||
elif name == 'runtime':
|
elif name == 'runtime':
|
||||||
# We don't want anything here, not sure what this function is
|
# We don't want anything here, not sure what this function is
|
||||||
# supposed to do, since it just appears in the stubs and shouldn't
|
# supposed to do, since it just appears in the stubs and shouldn't
|
||||||
# have any effects there (because it's never executed).
|
# have any effects there (because it's never executed).
|
||||||
return
|
return
|
||||||
elif name == 'TypeVar':
|
elif name == 'TypeVar':
|
||||||
yield TypeVarClass.create_cached(infer_state, self.parent_context, self.tree_name)
|
yield TypeVarClass.create_cached(infer_state, self.parent_value, self.tree_name)
|
||||||
elif name == 'Any':
|
elif name == 'Any':
|
||||||
yield Any.create_cached(infer_state, self.parent_context, self.tree_name)
|
yield Any.create_cached(infer_state, self.parent_value, self.tree_name)
|
||||||
elif name == 'TYPE_CHECKING':
|
elif name == 'TYPE_CHECKING':
|
||||||
# This is needed for e.g. imports that are only available for type
|
# This is needed for e.g. imports that are only available for type
|
||||||
# checking or are in cycles. The user can then check this variable.
|
# checking or are in cycles. The user can then check this variable.
|
||||||
yield builtin_from_name(infer_state, u'True')
|
yield builtin_from_name(infer_state, u'True')
|
||||||
elif name == 'overload':
|
elif name == 'overload':
|
||||||
yield OverloadFunction.create_cached(infer_state, self.parent_context, self.tree_name)
|
yield OverloadFunction.create_cached(infer_state, self.parent_value, self.tree_name)
|
||||||
elif name == 'NewType':
|
elif name == 'NewType':
|
||||||
yield NewTypeFunction.create_cached(infer_state, self.parent_context, self.tree_name)
|
yield NewTypeFunction.create_cached(infer_state, self.parent_value, self.tree_name)
|
||||||
elif name == 'cast':
|
elif name == 'cast':
|
||||||
# TODO implement cast
|
# TODO implement cast
|
||||||
yield CastFunction.create_cached(infer_state, self.parent_context, self.tree_name)
|
yield CastFunction.create_cached(infer_state, self.parent_value, self.tree_name)
|
||||||
elif name == 'TypedDict':
|
elif name == 'TypedDict':
|
||||||
# TODO doesn't even exist in typeshed/typing.py, yet. But will be
|
# TODO doesn't even exist in typeshed/typing.py, yet. But will be
|
||||||
# added soon.
|
# added soon.
|
||||||
@@ -139,16 +139,16 @@ class TypingModuleFilterWrapper(FilterWrapper):
|
|||||||
|
|
||||||
|
|
||||||
class _WithIndexBase(_BaseTypingContext):
|
class _WithIndexBase(_BaseTypingContext):
|
||||||
def __init__(self, infer_state, parent_context, name, index_context, context_of_index):
|
def __init__(self, infer_state, parent_value, name, index_value, value_of_index):
|
||||||
super(_WithIndexBase, self).__init__(infer_state, parent_context, name)
|
super(_WithIndexBase, self).__init__(infer_state, parent_value, name)
|
||||||
self._index_context = index_context
|
self._index_value = index_value
|
||||||
self._context_of_index = context_of_index
|
self._value_of_index = value_of_index
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return '<%s: %s[%s]>' % (
|
return '<%s: %s[%s]>' % (
|
||||||
self.__class__.__name__,
|
self.__class__.__name__,
|
||||||
self._tree_name.value,
|
self._tree_name.value,
|
||||||
self._index_context,
|
self._index_value,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -166,24 +166,24 @@ class TypingContextWithIndex(_WithIndexBase):
|
|||||||
return self.gather_annotation_classes().execute_annotation() \
|
return self.gather_annotation_classes().execute_annotation() \
|
||||||
| ContextSet([builtin_from_name(self.infer_state, u'None')])
|
| ContextSet([builtin_from_name(self.infer_state, u'None')])
|
||||||
elif string_name == 'Type':
|
elif string_name == 'Type':
|
||||||
# The type is actually already given in the index_context
|
# The type is actually already given in the index_value
|
||||||
return ContextSet([self._index_context])
|
return ContextSet([self._index_value])
|
||||||
elif string_name == 'ClassVar':
|
elif string_name == 'ClassVar':
|
||||||
# For now don't do anything here, ClassVars are always used.
|
# For now don't do anything here, ClassVars are always used.
|
||||||
return self._index_context.execute_annotation()
|
return self._index_value.execute_annotation()
|
||||||
|
|
||||||
cls = globals()[string_name]
|
cls = globals()[string_name]
|
||||||
return ContextSet([cls(
|
return ContextSet([cls(
|
||||||
self.infer_state,
|
self.infer_state,
|
||||||
self.parent_context,
|
self.parent_value,
|
||||||
self._tree_name,
|
self._tree_name,
|
||||||
self._index_context,
|
self._index_value,
|
||||||
self._context_of_index
|
self._value_of_index
|
||||||
)])
|
)])
|
||||||
|
|
||||||
def gather_annotation_classes(self):
|
def gather_annotation_classes(self):
|
||||||
return ContextSet.from_sets(
|
return ContextSet.from_sets(
|
||||||
_iter_over_arguments(self._index_context, self._context_of_index)
|
_iter_over_arguments(self._index_value, self._value_of_index)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -191,15 +191,15 @@ class TypingContext(_BaseTypingContext):
|
|||||||
index_class = TypingContextWithIndex
|
index_class = TypingContextWithIndex
|
||||||
py__simple_getitem__ = None
|
py__simple_getitem__ = None
|
||||||
|
|
||||||
def py__getitem__(self, index_context_set, contextualized_node):
|
def py__getitem__(self, index_value_set, valueualized_node):
|
||||||
return ContextSet(
|
return ContextSet(
|
||||||
self.index_class.create_cached(
|
self.index_class.create_cached(
|
||||||
self.infer_state,
|
self.infer_state,
|
||||||
self.parent_context,
|
self.parent_value,
|
||||||
self._tree_name,
|
self._tree_name,
|
||||||
index_context,
|
index_value,
|
||||||
context_of_index=contextualized_node.context)
|
value_of_index=valueualized_node.value)
|
||||||
for index_context in index_context_set
|
for index_value in index_value_set
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -221,33 +221,33 @@ class TypingClassContext(_TypingClassMixin, TypingContext, ClassMixin):
|
|||||||
index_class = TypingClassContextWithIndex
|
index_class = TypingClassContextWithIndex
|
||||||
|
|
||||||
|
|
||||||
def _iter_over_arguments(maybe_tuple_context, defining_context):
|
def _iter_over_arguments(maybe_tuple_value, defining_value):
|
||||||
def iterate():
|
def iterate():
|
||||||
if isinstance(maybe_tuple_context, SequenceLiteralContext):
|
if isinstance(maybe_tuple_value, SequenceLiteralContext):
|
||||||
for lazy_context in maybe_tuple_context.py__iter__(contextualized_node=None):
|
for lazy_value in maybe_tuple_value.py__iter__(valueualized_node=None):
|
||||||
yield lazy_context.infer()
|
yield lazy_value.infer()
|
||||||
else:
|
else:
|
||||||
yield ContextSet([maybe_tuple_context])
|
yield ContextSet([maybe_tuple_value])
|
||||||
|
|
||||||
def resolve_forward_references(context_set):
|
def resolve_forward_references(value_set):
|
||||||
for context in context_set:
|
for value in value_set:
|
||||||
if is_string(context):
|
if is_string(value):
|
||||||
from jedi.inference.gradual.annotation import _get_forward_reference_node
|
from jedi.inference.gradual.annotation import _get_forward_reference_node
|
||||||
node = _get_forward_reference_node(defining_context, context.get_safe_value())
|
node = _get_forward_reference_node(defining_value, value.get_safe_value())
|
||||||
if node is not None:
|
if node is not None:
|
||||||
for c in defining_context.infer_node(node):
|
for c in defining_value.infer_node(node):
|
||||||
yield c
|
yield c
|
||||||
else:
|
else:
|
||||||
yield context
|
yield value
|
||||||
|
|
||||||
for context_set in iterate():
|
for value_set in iterate():
|
||||||
yield ContextSet(resolve_forward_references(context_set))
|
yield ContextSet(resolve_forward_references(value_set))
|
||||||
|
|
||||||
|
|
||||||
class TypeAlias(LazyContextWrapper):
|
class TypeAlias(LazyContextWrapper):
|
||||||
def __init__(self, parent_context, origin_tree_name, actual):
|
def __init__(self, parent_value, origin_tree_name, actual):
|
||||||
self.infer_state = parent_context.infer_state
|
self.infer_state = parent_value.infer_state
|
||||||
self.parent_context = parent_context
|
self.parent_value = parent_value
|
||||||
self._origin_tree_name = origin_tree_name
|
self._origin_tree_name = origin_tree_name
|
||||||
self._actual = actual # e.g. builtins.list
|
self._actual = actual # e.g. builtins.list
|
||||||
|
|
||||||
@@ -261,7 +261,7 @@ class TypeAlias(LazyContextWrapper):
|
|||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return '<%s: %s>' % (self.__class__.__name__, self._actual)
|
return '<%s: %s>' % (self.__class__.__name__, self._actual)
|
||||||
|
|
||||||
def _get_wrapped_context(self):
|
def _get_wrapped_value(self):
|
||||||
module_name, class_name = self._actual.split('.')
|
module_name, class_name = self._actual.split('.')
|
||||||
if self.infer_state.environment.version_info.major == 2 and module_name == 'builtins':
|
if self.infer_state.environment.version_info.major == 2 and module_name == 'builtins':
|
||||||
module_name = '__builtin__'
|
module_name = '__builtin__'
|
||||||
@@ -279,56 +279,56 @@ class TypeAlias(LazyContextWrapper):
|
|||||||
|
|
||||||
|
|
||||||
class _ContainerBase(_WithIndexBase):
|
class _ContainerBase(_WithIndexBase):
|
||||||
def _get_getitem_contexts(self, index):
|
def _get_getitem_values(self, index):
|
||||||
args = _iter_over_arguments(self._index_context, self._context_of_index)
|
args = _iter_over_arguments(self._index_value, self._value_of_index)
|
||||||
for i, contexts in enumerate(args):
|
for i, values in enumerate(args):
|
||||||
if i == index:
|
if i == index:
|
||||||
return contexts
|
return values
|
||||||
|
|
||||||
debug.warning('No param #%s found for annotation %s', index, self._index_context)
|
debug.warning('No param #%s found for annotation %s', index, self._index_value)
|
||||||
return NO_CONTEXTS
|
return NO_CONTEXTS
|
||||||
|
|
||||||
|
|
||||||
class Callable(_ContainerBase):
|
class Callable(_ContainerBase):
|
||||||
def py__call__(self, arguments):
|
def py__call__(self, arguments):
|
||||||
# The 0th index are the arguments.
|
# The 0th index are the arguments.
|
||||||
return self._get_getitem_contexts(1).execute_annotation()
|
return self._get_getitem_values(1).execute_annotation()
|
||||||
|
|
||||||
|
|
||||||
class Tuple(_ContainerBase):
|
class Tuple(_ContainerBase):
|
||||||
def _is_homogenous(self):
|
def _is_homogenous(self):
|
||||||
# To specify a variable-length tuple of homogeneous type, Tuple[T, ...]
|
# To specify a variable-length tuple of homogeneous type, Tuple[T, ...]
|
||||||
# is used.
|
# is used.
|
||||||
if isinstance(self._index_context, SequenceLiteralContext):
|
if isinstance(self._index_value, SequenceLiteralContext):
|
||||||
entries = self._index_context.get_tree_entries()
|
entries = self._index_value.get_tree_entries()
|
||||||
if len(entries) == 2 and entries[1] == '...':
|
if len(entries) == 2 and entries[1] == '...':
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def py__simple_getitem__(self, index):
|
def py__simple_getitem__(self, index):
|
||||||
if self._is_homogenous():
|
if self._is_homogenous():
|
||||||
return self._get_getitem_contexts(0).execute_annotation()
|
return self._get_getitem_values(0).execute_annotation()
|
||||||
else:
|
else:
|
||||||
if isinstance(index, int):
|
if isinstance(index, int):
|
||||||
return self._get_getitem_contexts(index).execute_annotation()
|
return self._get_getitem_values(index).execute_annotation()
|
||||||
|
|
||||||
debug.dbg('The getitem type on Tuple was %s' % index)
|
debug.dbg('The getitem type on Tuple was %s' % index)
|
||||||
return NO_CONTEXTS
|
return NO_CONTEXTS
|
||||||
|
|
||||||
def py__iter__(self, contextualized_node=None):
|
def py__iter__(self, valueualized_node=None):
|
||||||
if self._is_homogenous():
|
if self._is_homogenous():
|
||||||
yield LazyKnownContexts(self._get_getitem_contexts(0).execute_annotation())
|
yield LazyKnownContexts(self._get_getitem_values(0).execute_annotation())
|
||||||
else:
|
else:
|
||||||
if isinstance(self._index_context, SequenceLiteralContext):
|
if isinstance(self._index_value, SequenceLiteralContext):
|
||||||
for i in range(self._index_context.py__len__()):
|
for i in range(self._index_value.py__len__()):
|
||||||
yield LazyKnownContexts(self._get_getitem_contexts(i).execute_annotation())
|
yield LazyKnownContexts(self._get_getitem_values(i).execute_annotation())
|
||||||
|
|
||||||
def py__getitem__(self, index_context_set, contextualized_node):
|
def py__getitem__(self, index_value_set, valueualized_node):
|
||||||
if self._is_homogenous():
|
if self._is_homogenous():
|
||||||
return self._get_getitem_contexts(0).execute_annotation()
|
return self._get_getitem_values(0).execute_annotation()
|
||||||
|
|
||||||
return ContextSet.from_sets(
|
return ContextSet.from_sets(
|
||||||
_iter_over_arguments(self._index_context, self._context_of_index)
|
_iter_over_arguments(self._index_value, self._value_of_index)
|
||||||
).execute_annotation()
|
).execute_annotation()
|
||||||
|
|
||||||
|
|
||||||
@@ -350,8 +350,8 @@ class TypeVarClass(_BaseTypingContext):
|
|||||||
def py__call__(self, arguments):
|
def py__call__(self, arguments):
|
||||||
unpacked = arguments.unpack()
|
unpacked = arguments.unpack()
|
||||||
|
|
||||||
key, lazy_context = next(unpacked, (None, None))
|
key, lazy_value = next(unpacked, (None, None))
|
||||||
var_name = self._find_string_name(lazy_context)
|
var_name = self._find_string_name(lazy_value)
|
||||||
# The name must be given, otherwise it's useless.
|
# The name must be given, otherwise it's useless.
|
||||||
if var_name is None or key is not None:
|
if var_name is None or key is not None:
|
||||||
debug.warning('Found a variable without a name %s', arguments)
|
debug.warning('Found a variable without a name %s', arguments)
|
||||||
@@ -359,25 +359,25 @@ class TypeVarClass(_BaseTypingContext):
|
|||||||
|
|
||||||
return ContextSet([TypeVar.create_cached(
|
return ContextSet([TypeVar.create_cached(
|
||||||
self.infer_state,
|
self.infer_state,
|
||||||
self.parent_context,
|
self.parent_value,
|
||||||
self._tree_name,
|
self._tree_name,
|
||||||
var_name,
|
var_name,
|
||||||
unpacked
|
unpacked
|
||||||
)])
|
)])
|
||||||
|
|
||||||
def _find_string_name(self, lazy_context):
|
def _find_string_name(self, lazy_value):
|
||||||
if lazy_context is None:
|
if lazy_value is None:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
context_set = lazy_context.infer()
|
value_set = lazy_value.infer()
|
||||||
if not context_set:
|
if not value_set:
|
||||||
return None
|
return None
|
||||||
if len(context_set) > 1:
|
if len(value_set) > 1:
|
||||||
debug.warning('Found multiple contexts for a type variable: %s', context_set)
|
debug.warning('Found multiple values for a type variable: %s', value_set)
|
||||||
|
|
||||||
name_context = next(iter(context_set))
|
name_value = next(iter(value_set))
|
||||||
try:
|
try:
|
||||||
method = name_context.get_safe_value
|
method = name_value.get_safe_value
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
return None
|
return None
|
||||||
else:
|
else:
|
||||||
@@ -391,24 +391,24 @@ class TypeVarClass(_BaseTypingContext):
|
|||||||
|
|
||||||
|
|
||||||
class TypeVar(_BaseTypingContext):
|
class TypeVar(_BaseTypingContext):
|
||||||
def __init__(self, infer_state, parent_context, tree_name, var_name, unpacked_args):
|
def __init__(self, infer_state, parent_value, tree_name, var_name, unpacked_args):
|
||||||
super(TypeVar, self).__init__(infer_state, parent_context, tree_name)
|
super(TypeVar, self).__init__(infer_state, parent_value, tree_name)
|
||||||
self._var_name = var_name
|
self._var_name = var_name
|
||||||
|
|
||||||
self._constraints_lazy_contexts = []
|
self._constraints_lazy_values = []
|
||||||
self._bound_lazy_context = None
|
self._bound_lazy_value = None
|
||||||
self._covariant_lazy_context = None
|
self._covariant_lazy_value = None
|
||||||
self._contravariant_lazy_context = None
|
self._contravariant_lazy_value = None
|
||||||
for key, lazy_context in unpacked_args:
|
for key, lazy_value in unpacked_args:
|
||||||
if key is None:
|
if key is None:
|
||||||
self._constraints_lazy_contexts.append(lazy_context)
|
self._constraints_lazy_values.append(lazy_value)
|
||||||
else:
|
else:
|
||||||
if key == 'bound':
|
if key == 'bound':
|
||||||
self._bound_lazy_context = lazy_context
|
self._bound_lazy_value = lazy_value
|
||||||
elif key == 'covariant':
|
elif key == 'covariant':
|
||||||
self._covariant_lazy_context = lazy_context
|
self._covariant_lazy_value = lazy_value
|
||||||
elif key == 'contravariant':
|
elif key == 'contravariant':
|
||||||
self._contra_variant_lazy_context = lazy_context
|
self._contra_variant_lazy_value = lazy_value
|
||||||
else:
|
else:
|
||||||
debug.warning('Invalid TypeVar param name %s', key)
|
debug.warning('Invalid TypeVar param name %s', key)
|
||||||
|
|
||||||
@@ -419,9 +419,9 @@ class TypeVar(_BaseTypingContext):
|
|||||||
return iter([])
|
return iter([])
|
||||||
|
|
||||||
def _get_classes(self):
|
def _get_classes(self):
|
||||||
if self._bound_lazy_context is not None:
|
if self._bound_lazy_value is not None:
|
||||||
return self._bound_lazy_context.infer()
|
return self._bound_lazy_value.infer()
|
||||||
if self._constraints_lazy_contexts:
|
if self._constraints_lazy_values:
|
||||||
return self.constraints
|
return self.constraints
|
||||||
debug.warning('Tried to infer the TypeVar %s without a given type', self._var_name)
|
debug.warning('Tried to infer the TypeVar %s without a given type', self._var_name)
|
||||||
return NO_CONTEXTS
|
return NO_CONTEXTS
|
||||||
@@ -433,7 +433,7 @@ class TypeVar(_BaseTypingContext):
|
|||||||
@property
|
@property
|
||||||
def constraints(self):
|
def constraints(self):
|
||||||
return ContextSet.from_sets(
|
return ContextSet.from_sets(
|
||||||
lazy.infer() for lazy in self._constraints_lazy_contexts
|
lazy.infer() for lazy in self._constraints_lazy_values
|
||||||
)
|
)
|
||||||
|
|
||||||
def define_generics(self, type_var_dict):
|
def define_generics(self, type_var_dict):
|
||||||
@@ -455,9 +455,9 @@ class TypeVar(_BaseTypingContext):
|
|||||||
|
|
||||||
class OverloadFunction(_BaseTypingContext):
|
class OverloadFunction(_BaseTypingContext):
|
||||||
@repack_with_argument_clinic('func, /')
|
@repack_with_argument_clinic('func, /')
|
||||||
def py__call__(self, func_context_set):
|
def py__call__(self, func_value_set):
|
||||||
# Just pass arguments through.
|
# Just pass arguments through.
|
||||||
return func_context_set
|
return func_value_set
|
||||||
|
|
||||||
|
|
||||||
class NewTypeFunction(_BaseTypingContext):
|
class NewTypeFunction(_BaseTypingContext):
|
||||||
@@ -470,53 +470,53 @@ class NewTypeFunction(_BaseTypingContext):
|
|||||||
return ContextSet(
|
return ContextSet(
|
||||||
NewType(
|
NewType(
|
||||||
self.infer_state,
|
self.infer_state,
|
||||||
contextualized_node.context,
|
valueualized_node.value,
|
||||||
contextualized_node.node,
|
valueualized_node.node,
|
||||||
second_arg.infer(),
|
second_arg.infer(),
|
||||||
) for contextualized_node in arguments.get_calling_nodes())
|
) for valueualized_node in arguments.get_calling_nodes())
|
||||||
|
|
||||||
|
|
||||||
class NewType(Context):
|
class NewType(Context):
|
||||||
def __init__(self, infer_state, parent_context, tree_node, type_context_set):
|
def __init__(self, infer_state, parent_value, tree_node, type_value_set):
|
||||||
super(NewType, self).__init__(infer_state, parent_context)
|
super(NewType, self).__init__(infer_state, parent_value)
|
||||||
self._type_context_set = type_context_set
|
self._type_value_set = type_value_set
|
||||||
self.tree_node = tree_node
|
self.tree_node = tree_node
|
||||||
|
|
||||||
def py__call__(self, arguments):
|
def py__call__(self, arguments):
|
||||||
return self._type_context_set.execute_annotation()
|
return self._type_value_set.execute_annotation()
|
||||||
|
|
||||||
|
|
||||||
class CastFunction(_BaseTypingContext):
|
class CastFunction(_BaseTypingContext):
|
||||||
@repack_with_argument_clinic('type, object, /')
|
@repack_with_argument_clinic('type, object, /')
|
||||||
def py__call__(self, type_context_set, object_context_set):
|
def py__call__(self, type_value_set, object_value_set):
|
||||||
return type_context_set.execute_annotation()
|
return type_value_set.execute_annotation()
|
||||||
|
|
||||||
|
|
||||||
class BoundTypeVarName(AbstractNameDefinition):
|
class BoundTypeVarName(AbstractNameDefinition):
|
||||||
"""
|
"""
|
||||||
This type var was bound to a certain type, e.g. int.
|
This type var was bound to a certain type, e.g. int.
|
||||||
"""
|
"""
|
||||||
def __init__(self, type_var, context_set):
|
def __init__(self, type_var, value_set):
|
||||||
self._type_var = type_var
|
self._type_var = type_var
|
||||||
self.parent_context = type_var.parent_context
|
self.parent_value = type_var.parent_value
|
||||||
self._context_set = context_set
|
self._value_set = value_set
|
||||||
|
|
||||||
def infer(self):
|
def infer(self):
|
||||||
def iter_():
|
def iter_():
|
||||||
for context in self._context_set:
|
for value in self._value_set:
|
||||||
# Replace any with the constraints if they are there.
|
# Replace any with the constraints if they are there.
|
||||||
if isinstance(context, Any):
|
if isinstance(value, Any):
|
||||||
for constraint in self._type_var.constraints:
|
for constraint in self._type_var.constraints:
|
||||||
yield constraint
|
yield constraint
|
||||||
else:
|
else:
|
||||||
yield context
|
yield value
|
||||||
return ContextSet(iter_())
|
return ContextSet(iter_())
|
||||||
|
|
||||||
def py__name__(self):
|
def py__name__(self):
|
||||||
return self._type_var.py__name__()
|
return self._type_var.py__name__()
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return '<%s %s -> %s>' % (self.__class__.__name__, self.py__name__(), self._context_set)
|
return '<%s %s -> %s>' % (self.__class__.__name__, self.py__name__(), self._value_set)
|
||||||
|
|
||||||
|
|
||||||
class TypeVarFilter(object):
|
class TypeVarFilter(object):
|
||||||
@@ -602,16 +602,16 @@ class AbstractAnnotatedClass(ClassMixin, ContextWrapper):
|
|||||||
changed = False
|
changed = False
|
||||||
new_generics = []
|
new_generics = []
|
||||||
for generic_set in self.get_generics():
|
for generic_set in self.get_generics():
|
||||||
contexts = NO_CONTEXTS
|
values = NO_CONTEXTS
|
||||||
for generic in generic_set:
|
for generic in generic_set:
|
||||||
if isinstance(generic, (AbstractAnnotatedClass, TypeVar)):
|
if isinstance(generic, (AbstractAnnotatedClass, TypeVar)):
|
||||||
result = generic.define_generics(type_var_dict)
|
result = generic.define_generics(type_var_dict)
|
||||||
contexts |= result
|
values |= result
|
||||||
if result != ContextSet({generic}):
|
if result != ContextSet({generic}):
|
||||||
changed = True
|
changed = True
|
||||||
else:
|
else:
|
||||||
contexts |= ContextSet([generic])
|
values |= ContextSet([generic])
|
||||||
new_generics.append(contexts)
|
new_generics.append(values)
|
||||||
|
|
||||||
if not changed:
|
if not changed:
|
||||||
# There might not be any type vars that change. In that case just
|
# There might not be any type vars that change. In that case just
|
||||||
@@ -620,37 +620,37 @@ class AbstractAnnotatedClass(ClassMixin, ContextWrapper):
|
|||||||
return ContextSet([self])
|
return ContextSet([self])
|
||||||
|
|
||||||
return ContextSet([GenericClass(
|
return ContextSet([GenericClass(
|
||||||
self._wrapped_context,
|
self._wrapped_value,
|
||||||
generics=tuple(new_generics)
|
generics=tuple(new_generics)
|
||||||
)])
|
)])
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return '<%s: %s%s>' % (
|
return '<%s: %s%s>' % (
|
||||||
self.__class__.__name__,
|
self.__class__.__name__,
|
||||||
self._wrapped_context,
|
self._wrapped_value,
|
||||||
list(self.get_generics()),
|
list(self.get_generics()),
|
||||||
)
|
)
|
||||||
|
|
||||||
@to_list
|
@to_list
|
||||||
def py__bases__(self):
|
def py__bases__(self):
|
||||||
for base in self._wrapped_context.py__bases__():
|
for base in self._wrapped_value.py__bases__():
|
||||||
yield LazyAnnotatedBaseClass(self, base)
|
yield LazyAnnotatedBaseClass(self, base)
|
||||||
|
|
||||||
|
|
||||||
class LazyGenericClass(AbstractAnnotatedClass):
|
class LazyGenericClass(AbstractAnnotatedClass):
|
||||||
def __init__(self, class_context, index_context, context_of_index):
|
def __init__(self, class_value, index_value, value_of_index):
|
||||||
super(LazyGenericClass, self).__init__(class_context)
|
super(LazyGenericClass, self).__init__(class_value)
|
||||||
self._index_context = index_context
|
self._index_value = index_value
|
||||||
self._context_of_index = context_of_index
|
self._value_of_index = value_of_index
|
||||||
|
|
||||||
@infer_state_method_cache()
|
@infer_state_method_cache()
|
||||||
def get_generics(self):
|
def get_generics(self):
|
||||||
return list(_iter_over_arguments(self._index_context, self._context_of_index))
|
return list(_iter_over_arguments(self._index_value, self._value_of_index))
|
||||||
|
|
||||||
|
|
||||||
class GenericClass(AbstractAnnotatedClass):
|
class GenericClass(AbstractAnnotatedClass):
|
||||||
def __init__(self, class_context, generics):
|
def __init__(self, class_value, generics):
|
||||||
super(GenericClass, self).__init__(class_context)
|
super(GenericClass, self).__init__(class_value)
|
||||||
self._generics = generics
|
self._generics = generics
|
||||||
|
|
||||||
def get_generics(self):
|
def get_generics(self):
|
||||||
@@ -658,25 +658,25 @@ class GenericClass(AbstractAnnotatedClass):
|
|||||||
|
|
||||||
|
|
||||||
class LazyAnnotatedBaseClass(object):
|
class LazyAnnotatedBaseClass(object):
|
||||||
def __init__(self, class_context, lazy_base_class):
|
def __init__(self, class_value, lazy_base_class):
|
||||||
self._class_context = class_context
|
self._class_value = class_value
|
||||||
self._lazy_base_class = lazy_base_class
|
self._lazy_base_class = lazy_base_class
|
||||||
|
|
||||||
@iterator_to_context_set
|
@iterator_to_value_set
|
||||||
def infer(self):
|
def infer(self):
|
||||||
for base in self._lazy_base_class.infer():
|
for base in self._lazy_base_class.infer():
|
||||||
if isinstance(base, AbstractAnnotatedClass):
|
if isinstance(base, AbstractAnnotatedClass):
|
||||||
# Here we have to recalculate the given types.
|
# Here we have to recalculate the given types.
|
||||||
yield GenericClass.create_cached(
|
yield GenericClass.create_cached(
|
||||||
base.infer_state,
|
base.infer_state,
|
||||||
base._wrapped_context,
|
base._wrapped_value,
|
||||||
tuple(self._remap_type_vars(base)),
|
tuple(self._remap_type_vars(base)),
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
yield base
|
yield base
|
||||||
|
|
||||||
def _remap_type_vars(self, base):
|
def _remap_type_vars(self, base):
|
||||||
filter = self._class_context.get_type_var_filter()
|
filter = self._class_value.get_type_var_filter()
|
||||||
for type_var_set in base.get_generics():
|
for type_var_set in base.get_generics():
|
||||||
new = NO_CONTEXTS
|
new = NO_CONTEXTS
|
||||||
for type_var in type_var_set:
|
for type_var in type_var_set:
|
||||||
@@ -688,14 +688,14 @@ class LazyAnnotatedBaseClass(object):
|
|||||||
else:
|
else:
|
||||||
# Mostly will be type vars, except if in some cases
|
# Mostly will be type vars, except if in some cases
|
||||||
# a concrete type will already be there. In that
|
# a concrete type will already be there. In that
|
||||||
# case just add it to the context set.
|
# case just add it to the value set.
|
||||||
new |= ContextSet([type_var])
|
new |= ContextSet([type_var])
|
||||||
yield new
|
yield new
|
||||||
|
|
||||||
|
|
||||||
class InstanceWrapper(ContextWrapper):
|
class InstanceWrapper(ContextWrapper):
|
||||||
def py__stop_iteration_returns(self):
|
def py__stop_iteration_returns(self):
|
||||||
for cls in self._wrapped_context.class_context.py__mro__():
|
for cls in self._wrapped_value.class_value.py__mro__():
|
||||||
if cls.py__name__() == 'Generator':
|
if cls.py__name__() == 'Generator':
|
||||||
generics = cls.get_generics()
|
generics = cls.get_generics()
|
||||||
try:
|
try:
|
||||||
@@ -704,4 +704,4 @@ class InstanceWrapper(ContextWrapper):
|
|||||||
pass
|
pass
|
||||||
elif cls.py__name__() == 'Iterator':
|
elif cls.py__name__() == 'Iterator':
|
||||||
return ContextSet([builtin_from_name(self.infer_state, u'None')])
|
return ContextSet([builtin_from_name(self.infer_state, u'None')])
|
||||||
return self._wrapped_context.py__stop_iteration_returns()
|
return self._wrapped_value.py__stop_iteration_returns()
|
||||||
|
|||||||
@@ -20,12 +20,12 @@ def load_proper_stub_module(infer_state, file_io, import_names, module_node):
|
|||||||
import_names = import_names[:-1]
|
import_names = import_names[:-1]
|
||||||
|
|
||||||
if import_names is not None:
|
if import_names is not None:
|
||||||
actual_context_set = infer_state.import_module(import_names, prefer_stubs=False)
|
actual_value_set = infer_state.import_module(import_names, prefer_stubs=False)
|
||||||
if not actual_context_set:
|
if not actual_value_set:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
stub = create_stub_module(
|
stub = create_stub_module(
|
||||||
infer_state, actual_context_set, module_node, file_io, import_names
|
infer_state, actual_value_set, module_node, file_io, import_names
|
||||||
)
|
)
|
||||||
infer_state.stub_module_cache[import_names] = stub
|
infer_state.stub_module_cache[import_names] = stub
|
||||||
return stub
|
return stub
|
||||||
|
|||||||
+22
-22
@@ -44,7 +44,7 @@ def deep_ast_copy(obj):
|
|||||||
return new_obj
|
return new_obj
|
||||||
|
|
||||||
|
|
||||||
def infer_call_of_leaf(context, leaf, cut_own_trailer=False):
|
def infer_call_of_leaf(value, leaf, cut_own_trailer=False):
|
||||||
"""
|
"""
|
||||||
Creates a "call" node that consist of all ``trailer`` and ``power``
|
Creates a "call" node that consist of all ``trailer`` and ``power``
|
||||||
objects. E.g. if you call it with ``append``::
|
objects. E.g. if you call it with ``append``::
|
||||||
@@ -66,15 +66,15 @@ def infer_call_of_leaf(context, leaf, cut_own_trailer=False):
|
|||||||
trailer = leaf.parent
|
trailer = leaf.parent
|
||||||
if trailer.type == 'fstring':
|
if trailer.type == 'fstring':
|
||||||
from jedi.inference import compiled
|
from jedi.inference import compiled
|
||||||
return compiled.get_string_context_set(context.infer_state)
|
return compiled.get_string_value_set(value.infer_state)
|
||||||
|
|
||||||
# The leaf may not be the last or first child, because there exist three
|
# The leaf may not be the last or first child, because there exist three
|
||||||
# different trailers: `( x )`, `[ x ]` and `.x`. In the first two examples
|
# different trailers: `( x )`, `[ x ]` and `.x`. In the first two examples
|
||||||
# we should not match anything more than x.
|
# we should not match anything more than x.
|
||||||
if trailer.type != 'trailer' or leaf not in (trailer.children[0], trailer.children[-1]):
|
if trailer.type != 'trailer' or leaf not in (trailer.children[0], trailer.children[-1]):
|
||||||
if trailer.type == 'atom':
|
if trailer.type == 'atom':
|
||||||
return context.infer_node(trailer)
|
return value.infer_node(trailer)
|
||||||
return context.infer_node(leaf)
|
return value.infer_node(leaf)
|
||||||
|
|
||||||
power = trailer.parent
|
power = trailer.parent
|
||||||
index = power.children.index(trailer)
|
index = power.children.index(trailer)
|
||||||
@@ -99,10 +99,10 @@ def infer_call_of_leaf(context, leaf, cut_own_trailer=False):
|
|||||||
base = trailers[0]
|
base = trailers[0]
|
||||||
trailers = trailers[1:]
|
trailers = trailers[1:]
|
||||||
|
|
||||||
values = context.infer_node(base)
|
values = value.infer_node(base)
|
||||||
from jedi.inference.syntax_tree import infer_trailer
|
from jedi.inference.syntax_tree import infer_trailer
|
||||||
for trailer in trailers:
|
for trailer in trailers:
|
||||||
values = infer_trailer(context, values, trailer)
|
values = infer_trailer(value, values, trailer)
|
||||||
return values
|
return values
|
||||||
|
|
||||||
|
|
||||||
@@ -185,8 +185,8 @@ def get_module_names(module, all_scopes):
|
|||||||
|
|
||||||
|
|
||||||
@contextmanager
|
@contextmanager
|
||||||
def predefine_names(context, flow_scope, dct):
|
def predefine_names(value, flow_scope, dct):
|
||||||
predefined = context.predefined_names
|
predefined = value.predefined_names
|
||||||
predefined[flow_scope] = dct
|
predefined[flow_scope] = dct
|
||||||
try:
|
try:
|
||||||
yield
|
yield
|
||||||
@@ -194,34 +194,34 @@ def predefine_names(context, flow_scope, dct):
|
|||||||
del predefined[flow_scope]
|
del predefined[flow_scope]
|
||||||
|
|
||||||
|
|
||||||
def is_string(context):
|
def is_string(value):
|
||||||
if context.infer_state.environment.version_info.major == 2:
|
if value.infer_state.environment.version_info.major == 2:
|
||||||
str_classes = (unicode, bytes)
|
str_classes = (unicode, bytes)
|
||||||
else:
|
else:
|
||||||
str_classes = (unicode,)
|
str_classes = (unicode,)
|
||||||
return context.is_compiled() and isinstance(context.get_safe_value(default=None), str_classes)
|
return value.is_compiled() and isinstance(value.get_safe_value(default=None), str_classes)
|
||||||
|
|
||||||
|
|
||||||
def is_literal(context):
|
def is_literal(value):
|
||||||
return is_number(context) or is_string(context)
|
return is_number(value) or is_string(value)
|
||||||
|
|
||||||
|
|
||||||
def _get_safe_value_or_none(context, accept):
|
def _get_safe_value_or_none(value, accept):
|
||||||
value = context.get_safe_value(default=None)
|
value = value.get_safe_value(default=None)
|
||||||
if isinstance(value, accept):
|
if isinstance(value, accept):
|
||||||
return value
|
return value
|
||||||
|
|
||||||
|
|
||||||
def get_int_or_none(context):
|
def get_int_or_none(value):
|
||||||
return _get_safe_value_or_none(context, int)
|
return _get_safe_value_or_none(value, int)
|
||||||
|
|
||||||
|
|
||||||
def get_str_or_none(context):
|
def get_str_or_none(value):
|
||||||
return _get_safe_value_or_none(context, (bytes, unicode))
|
return _get_safe_value_or_none(value, (bytes, unicode))
|
||||||
|
|
||||||
|
|
||||||
def is_number(context):
|
def is_number(value):
|
||||||
return _get_safe_value_or_none(context, (int, float)) is not None
|
return _get_safe_value_or_none(value, (int, float)) is not None
|
||||||
|
|
||||||
|
|
||||||
class SimpleGetItemNotFound(Exception):
|
class SimpleGetItemNotFound(Exception):
|
||||||
@@ -265,5 +265,5 @@ def parse_dotted_names(nodes, is_import_from, until_node=None):
|
|||||||
return level, names
|
return level, names
|
||||||
|
|
||||||
|
|
||||||
def contexts_from_qualified_names(infer_state, *names):
|
def values_from_qualified_names(infer_state, *names):
|
||||||
return infer_state.import_module(names[:-1]).py__getattribute__(names[-1])
|
return infer_state.import_module(names[:-1]).py__getattribute__(names[-1])
|
||||||
|
|||||||
+44
-44
@@ -32,7 +32,7 @@ from jedi.inference.cache import infer_state_method_cache
|
|||||||
from jedi.inference.names import ImportName, SubModuleName
|
from jedi.inference.names import ImportName, SubModuleName
|
||||||
from jedi.inference.base_value import ContextSet, NO_CONTEXTS
|
from jedi.inference.base_value import ContextSet, NO_CONTEXTS
|
||||||
from jedi.inference.gradual.typeshed import import_module_decorator
|
from jedi.inference.gradual.typeshed import import_module_decorator
|
||||||
from jedi.inference.context.module import iter_module_names
|
from jedi.inference.value.module import iter_module_names
|
||||||
from jedi.plugins import plugin_manager
|
from jedi.plugins import plugin_manager
|
||||||
|
|
||||||
|
|
||||||
@@ -41,11 +41,11 @@ class ModuleCache(object):
|
|||||||
self._path_cache = {}
|
self._path_cache = {}
|
||||||
self._name_cache = {}
|
self._name_cache = {}
|
||||||
|
|
||||||
def add(self, string_names, context_set):
|
def add(self, string_names, value_set):
|
||||||
#path = module.py__file__()
|
#path = module.py__file__()
|
||||||
#self._path_cache[path] = context_set
|
#self._path_cache[path] = value_set
|
||||||
if string_names is not None:
|
if string_names is not None:
|
||||||
self._name_cache[string_names] = context_set
|
self._name_cache[string_names] = value_set
|
||||||
|
|
||||||
def get(self, string_names):
|
def get(self, string_names):
|
||||||
return self._name_cache[string_names]
|
return self._name_cache[string_names]
|
||||||
@@ -57,12 +57,12 @@ class ModuleCache(object):
|
|||||||
# This memoization is needed, because otherwise we will infinitely loop on
|
# This memoization is needed, because otherwise we will infinitely loop on
|
||||||
# certain imports.
|
# certain imports.
|
||||||
@infer_state_method_cache(default=NO_CONTEXTS)
|
@infer_state_method_cache(default=NO_CONTEXTS)
|
||||||
def infer_import(context, tree_name, is_goto=False):
|
def infer_import(value, tree_name, is_goto=False):
|
||||||
module_context = context.get_root_context()
|
module_value = value.get_root_value()
|
||||||
import_node = search_ancestor(tree_name, 'import_name', 'import_from')
|
import_node = search_ancestor(tree_name, 'import_name', 'import_from')
|
||||||
import_path = import_node.get_path_for_name(tree_name)
|
import_path = import_node.get_path_for_name(tree_name)
|
||||||
from_import_name = None
|
from_import_name = None
|
||||||
infer_state = context.infer_state
|
infer_state = value.infer_state
|
||||||
try:
|
try:
|
||||||
from_names = import_node.get_from_names()
|
from_names = import_node.get_from_names()
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
@@ -76,7 +76,7 @@ def infer_import(context, tree_name, is_goto=False):
|
|||||||
import_path = from_names
|
import_path = from_names
|
||||||
|
|
||||||
importer = Importer(infer_state, tuple(import_path),
|
importer = Importer(infer_state, tuple(import_path),
|
||||||
module_context, import_node.level)
|
module_value, import_node.level)
|
||||||
|
|
||||||
types = importer.follow()
|
types = importer.follow()
|
||||||
|
|
||||||
@@ -90,7 +90,7 @@ def infer_import(context, tree_name, is_goto=False):
|
|||||||
types = unite(
|
types = unite(
|
||||||
t.py__getattribute__(
|
t.py__getattribute__(
|
||||||
from_import_name,
|
from_import_name,
|
||||||
name_context=context,
|
name_value=value,
|
||||||
is_goto=is_goto,
|
is_goto=is_goto,
|
||||||
analysis_errors=False
|
analysis_errors=False
|
||||||
)
|
)
|
||||||
@@ -102,7 +102,7 @@ def infer_import(context, tree_name, is_goto=False):
|
|||||||
if not types:
|
if not types:
|
||||||
path = import_path + [from_import_name]
|
path = import_path + [from_import_name]
|
||||||
importer = Importer(infer_state, tuple(path),
|
importer = Importer(infer_state, tuple(path),
|
||||||
module_context, import_node.level)
|
module_value, import_node.level)
|
||||||
types = importer.follow()
|
types = importer.follow()
|
||||||
# goto only accepts `Name`
|
# goto only accepts `Name`
|
||||||
if is_goto:
|
if is_goto:
|
||||||
@@ -148,9 +148,9 @@ class NestedImportModule(tree.Module):
|
|||||||
self._nested_import)
|
self._nested_import)
|
||||||
|
|
||||||
|
|
||||||
def _add_error(context, name, message):
|
def _add_error(value, name, message):
|
||||||
if hasattr(name, 'parent') and context is not None:
|
if hasattr(name, 'parent') and value is not None:
|
||||||
analysis.add(context, 'import-error', name, message)
|
analysis.add(value, 'import-error', name, message)
|
||||||
else:
|
else:
|
||||||
debug.warning('ImportError without origin: ' + message)
|
debug.warning('ImportError without origin: ' + message)
|
||||||
|
|
||||||
@@ -183,7 +183,7 @@ def _level_to_base_import_path(project_path, directory, level):
|
|||||||
|
|
||||||
|
|
||||||
class Importer(object):
|
class Importer(object):
|
||||||
def __init__(self, infer_state, import_path, module_context, level=0):
|
def __init__(self, infer_state, import_path, module_value, level=0):
|
||||||
"""
|
"""
|
||||||
An implementation similar to ``__import__``. Use `follow`
|
An implementation similar to ``__import__``. Use `follow`
|
||||||
to actually follow the imports.
|
to actually follow the imports.
|
||||||
@@ -196,15 +196,15 @@ class Importer(object):
|
|||||||
|
|
||||||
:param import_path: List of namespaces (strings or Names).
|
:param import_path: List of namespaces (strings or Names).
|
||||||
"""
|
"""
|
||||||
debug.speed('import %s %s' % (import_path, module_context))
|
debug.speed('import %s %s' % (import_path, module_value))
|
||||||
self._infer_state = infer_state
|
self._infer_state = infer_state
|
||||||
self.level = level
|
self.level = level
|
||||||
self.module_context = module_context
|
self.module_value = module_value
|
||||||
|
|
||||||
self._fixed_sys_path = None
|
self._fixed_sys_path = None
|
||||||
self._infer_possible = True
|
self._infer_possible = True
|
||||||
if level:
|
if level:
|
||||||
base = module_context.py__package__()
|
base = module_value.py__package__()
|
||||||
# We need to care for two cases, the first one is if it's a valid
|
# We need to care for two cases, the first one is if it's a valid
|
||||||
# Python import. This import has a properly defined module name
|
# Python import. This import has a properly defined module name
|
||||||
# chain like `foo.bar.baz` and an import in baz is made for
|
# chain like `foo.bar.baz` and an import in baz is made for
|
||||||
@@ -221,7 +221,7 @@ class Importer(object):
|
|||||||
base = base[:-level + 1]
|
base = base[:-level + 1]
|
||||||
import_path = base + tuple(import_path)
|
import_path = base + tuple(import_path)
|
||||||
else:
|
else:
|
||||||
path = module_context.py__file__()
|
path = module_value.py__file__()
|
||||||
import_path = list(import_path)
|
import_path = list(import_path)
|
||||||
if path is None:
|
if path is None:
|
||||||
# If no path is defined, our best guess is that the current
|
# If no path is defined, our best guess is that the current
|
||||||
@@ -245,7 +245,7 @@ class Importer(object):
|
|||||||
if base_import_path is None:
|
if base_import_path is None:
|
||||||
if import_path:
|
if import_path:
|
||||||
_add_error(
|
_add_error(
|
||||||
module_context, import_path[0],
|
module_value, import_path[0],
|
||||||
message='Attempted relative import beyond top-level package.'
|
message='Attempted relative import beyond top-level package.'
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
@@ -266,11 +266,11 @@ class Importer(object):
|
|||||||
|
|
||||||
sys_path_mod = (
|
sys_path_mod = (
|
||||||
self._infer_state.get_sys_path()
|
self._infer_state.get_sys_path()
|
||||||
+ sys_path.check_sys_path_modifications(self.module_context)
|
+ sys_path.check_sys_path_modifications(self.module_value)
|
||||||
)
|
)
|
||||||
|
|
||||||
if self._infer_state.environment.version_info.major == 2:
|
if self._infer_state.environment.version_info.major == 2:
|
||||||
file_path = self.module_context.py__file__()
|
file_path = self.module_value.py__file__()
|
||||||
if file_path is not None:
|
if file_path is not None:
|
||||||
# Python2 uses an old strange way of importing relative imports.
|
# Python2 uses an old strange way of importing relative imports.
|
||||||
sys_path_mod.append(force_unicode(os.path.dirname(file_path)))
|
sys_path_mod.append(force_unicode(os.path.dirname(file_path)))
|
||||||
@@ -287,20 +287,20 @@ class Importer(object):
|
|||||||
)
|
)
|
||||||
sys_path = self._sys_path_with_modifications()
|
sys_path = self._sys_path_with_modifications()
|
||||||
|
|
||||||
context_set = [None]
|
value_set = [None]
|
||||||
for i, name in enumerate(self.import_path):
|
for i, name in enumerate(self.import_path):
|
||||||
context_set = ContextSet.from_sets([
|
value_set = ContextSet.from_sets([
|
||||||
self._infer_state.import_module(
|
self._infer_state.import_module(
|
||||||
import_names[:i+1],
|
import_names[:i+1],
|
||||||
parent_module_context,
|
parent_module_value,
|
||||||
sys_path
|
sys_path
|
||||||
) for parent_module_context in context_set
|
) for parent_module_value in value_set
|
||||||
])
|
])
|
||||||
if not context_set:
|
if not value_set:
|
||||||
message = 'No module named ' + '.'.join(import_names)
|
message = 'No module named ' + '.'.join(import_names)
|
||||||
_add_error(self.module_context, name, message)
|
_add_error(self.module_value, name, message)
|
||||||
return NO_CONTEXTS
|
return NO_CONTEXTS
|
||||||
return context_set
|
return value_set
|
||||||
|
|
||||||
def _get_module_names(self, search_path=None, in_module=None):
|
def _get_module_names(self, search_path=None, in_module=None):
|
||||||
"""
|
"""
|
||||||
@@ -310,7 +310,7 @@ class Importer(object):
|
|||||||
names = []
|
names = []
|
||||||
# add builtin module names
|
# add builtin module names
|
||||||
if search_path is None and in_module is None:
|
if search_path is None and in_module is None:
|
||||||
names += [ImportName(self.module_context, name)
|
names += [ImportName(self.module_value, name)
|
||||||
for name in self._infer_state.compiled_subprocess.get_builtin_module_names()]
|
for name in self._infer_state.compiled_subprocess.get_builtin_module_names()]
|
||||||
|
|
||||||
if search_path is None:
|
if search_path is None:
|
||||||
@@ -318,7 +318,7 @@ class Importer(object):
|
|||||||
|
|
||||||
for name in iter_module_names(self._infer_state, search_path):
|
for name in iter_module_names(self._infer_state, search_path):
|
||||||
if in_module is None:
|
if in_module is None:
|
||||||
n = ImportName(self.module_context, name)
|
n = ImportName(self.module_value, name)
|
||||||
else:
|
else:
|
||||||
n = SubModuleName(in_module, name)
|
n = SubModuleName(in_module, name)
|
||||||
names.append(n)
|
names.append(n)
|
||||||
@@ -341,25 +341,25 @@ class Importer(object):
|
|||||||
modname = mod.string_name
|
modname = mod.string_name
|
||||||
if modname.startswith('flask_'):
|
if modname.startswith('flask_'):
|
||||||
extname = modname[len('flask_'):]
|
extname = modname[len('flask_'):]
|
||||||
names.append(ImportName(self.module_context, extname))
|
names.append(ImportName(self.module_value, extname))
|
||||||
# Now the old style: ``flaskext.foo``
|
# Now the old style: ``flaskext.foo``
|
||||||
for dir in self._sys_path_with_modifications():
|
for dir in self._sys_path_with_modifications():
|
||||||
flaskext = os.path.join(dir, 'flaskext')
|
flaskext = os.path.join(dir, 'flaskext')
|
||||||
if os.path.isdir(flaskext):
|
if os.path.isdir(flaskext):
|
||||||
names += self._get_module_names([flaskext])
|
names += self._get_module_names([flaskext])
|
||||||
|
|
||||||
contexts = self.follow()
|
values = self.follow()
|
||||||
for context in contexts:
|
for value in values:
|
||||||
# Non-modules are not completable.
|
# Non-modules are not completable.
|
||||||
if context.api_type != 'module': # not a module
|
if value.api_type != 'module': # not a module
|
||||||
continue
|
continue
|
||||||
names += context.sub_modules_dict().values()
|
names += value.sub_modules_dict().values()
|
||||||
|
|
||||||
if not only_modules:
|
if not only_modules:
|
||||||
from jedi.inference.gradual.conversion import convert_contexts
|
from jedi.inference.gradual.conversion import convert_values
|
||||||
|
|
||||||
both_contexts = contexts | convert_contexts(contexts)
|
both_values = values | convert_values(values)
|
||||||
for c in both_contexts:
|
for c in both_values:
|
||||||
for filter in c.get_filters(search_global=False):
|
for filter in c.get_filters(search_global=False):
|
||||||
names += filter.values()
|
names += filter.values()
|
||||||
else:
|
else:
|
||||||
@@ -374,7 +374,7 @@ class Importer(object):
|
|||||||
|
|
||||||
@plugin_manager.decorate()
|
@plugin_manager.decorate()
|
||||||
@import_module_decorator
|
@import_module_decorator
|
||||||
def import_module(infer_state, import_names, parent_module_context, sys_path):
|
def import_module(infer_state, import_names, parent_module_value, sys_path):
|
||||||
"""
|
"""
|
||||||
This method is very similar to importlib's `_gcd_import`.
|
This method is very similar to importlib's `_gcd_import`.
|
||||||
"""
|
"""
|
||||||
@@ -385,7 +385,7 @@ def import_module(infer_state, import_names, parent_module_context, sys_path):
|
|||||||
return ContextSet([module])
|
return ContextSet([module])
|
||||||
|
|
||||||
module_name = '.'.join(import_names)
|
module_name = '.'.join(import_names)
|
||||||
if parent_module_context is None:
|
if parent_module_value is None:
|
||||||
# Override the sys.path. It works only good that way.
|
# Override the sys.path. It works only good that way.
|
||||||
# Injecting the path directly into `find_module` did not work.
|
# Injecting the path directly into `find_module` did not work.
|
||||||
file_io_or_ns, is_pkg = infer_state.compiled_subprocess.get_module_info(
|
file_io_or_ns, is_pkg = infer_state.compiled_subprocess.get_module_info(
|
||||||
@@ -398,7 +398,7 @@ def import_module(infer_state, import_names, parent_module_context, sys_path):
|
|||||||
return NO_CONTEXTS
|
return NO_CONTEXTS
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
method = parent_module_context.py__path__
|
method = parent_module_value.py__path__
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
# The module is not a package.
|
# The module is not a package.
|
||||||
return NO_CONTEXTS
|
return NO_CONTEXTS
|
||||||
@@ -421,7 +421,7 @@ def import_module(infer_state, import_names, parent_module_context, sys_path):
|
|||||||
return NO_CONTEXTS
|
return NO_CONTEXTS
|
||||||
|
|
||||||
if isinstance(file_io_or_ns, ImplicitNSInfo):
|
if isinstance(file_io_or_ns, ImplicitNSInfo):
|
||||||
from jedi.inference.context.namespace import ImplicitNamespaceContext
|
from jedi.inference.value.namespace import ImplicitNamespaceContext
|
||||||
module = ImplicitNamespaceContext(
|
module = ImplicitNamespaceContext(
|
||||||
infer_state,
|
infer_state,
|
||||||
fullname=file_io_or_ns.name,
|
fullname=file_io_or_ns.name,
|
||||||
@@ -438,7 +438,7 @@ def import_module(infer_state, import_names, parent_module_context, sys_path):
|
|||||||
is_package=is_pkg,
|
is_package=is_pkg,
|
||||||
)
|
)
|
||||||
|
|
||||||
if parent_module_context is None:
|
if parent_module_value is None:
|
||||||
debug.dbg('global search_module %s: %s', import_names[-1], module)
|
debug.dbg('global search_module %s: %s', import_names[-1], module)
|
||||||
else:
|
else:
|
||||||
debug.dbg('search_module %s in paths %s: %s', module_name, paths, module)
|
debug.dbg('search_module %s in paths %s: %s', module_name, paths, module)
|
||||||
@@ -459,7 +459,7 @@ def _load_python_module(infer_state, file_io, sys_path=None,
|
|||||||
cache_path=settings.cache_directory
|
cache_path=settings.cache_directory
|
||||||
)
|
)
|
||||||
|
|
||||||
from jedi.inference.context import ModuleContext
|
from jedi.inference.value import ModuleContext
|
||||||
return ModuleContext(
|
return ModuleContext(
|
||||||
infer_state, module_node,
|
infer_state, module_node,
|
||||||
file_io=file_io,
|
file_io=file_io,
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ class AbstractLazyContext(object):
|
|||||||
|
|
||||||
|
|
||||||
class LazyKnownContext(AbstractLazyContext):
|
class LazyKnownContext(AbstractLazyContext):
|
||||||
"""data is a context."""
|
"""data is a value."""
|
||||||
def infer(self):
|
def infer(self):
|
||||||
return ContextSet([self.data])
|
return ContextSet([self.data])
|
||||||
|
|
||||||
@@ -34,26 +34,26 @@ class LazyUnknownContext(AbstractLazyContext):
|
|||||||
|
|
||||||
|
|
||||||
class LazyTreeContext(AbstractLazyContext):
|
class LazyTreeContext(AbstractLazyContext):
|
||||||
def __init__(self, context, node):
|
def __init__(self, value, node):
|
||||||
super(LazyTreeContext, self).__init__(node)
|
super(LazyTreeContext, self).__init__(node)
|
||||||
self.context = context
|
self.value = value
|
||||||
# We need to save the predefined names. It's an unfortunate side effect
|
# We need to save the predefined names. It's an unfortunate side effect
|
||||||
# that needs to be tracked otherwise results will be wrong.
|
# that needs to be tracked otherwise results will be wrong.
|
||||||
self._predefined_names = dict(context.predefined_names)
|
self._predefined_names = dict(value.predefined_names)
|
||||||
|
|
||||||
def infer(self):
|
def infer(self):
|
||||||
with monkeypatch(self.context, 'predefined_names', self._predefined_names):
|
with monkeypatch(self.value, 'predefined_names', self._predefined_names):
|
||||||
return self.context.infer_node(self.data)
|
return self.value.infer_node(self.data)
|
||||||
|
|
||||||
|
|
||||||
def get_merged_lazy_context(lazy_contexts):
|
def get_merged_lazy_value(lazy_values):
|
||||||
if len(lazy_contexts) > 1:
|
if len(lazy_values) > 1:
|
||||||
return MergedLazyContexts(lazy_contexts)
|
return MergedLazyContexts(lazy_values)
|
||||||
else:
|
else:
|
||||||
return lazy_contexts[0]
|
return lazy_values[0]
|
||||||
|
|
||||||
|
|
||||||
class MergedLazyContexts(AbstractLazyContext):
|
class MergedLazyContexts(AbstractLazyContext):
|
||||||
"""data is a list of lazy contexts."""
|
"""data is a list of lazy values."""
|
||||||
def infer(self):
|
def infer(self):
|
||||||
return ContextSet.from_sets(l.infer() for l in self.data)
|
return ContextSet.from_sets(l.infer() for l in self.data)
|
||||||
+42
-42
@@ -10,9 +10,9 @@ from jedi.cache import memoize_method
|
|||||||
class AbstractNameDefinition(object):
|
class AbstractNameDefinition(object):
|
||||||
start_pos = None
|
start_pos = None
|
||||||
string_name = None
|
string_name = None
|
||||||
parent_context = None
|
parent_value = None
|
||||||
tree_name = None
|
tree_name = None
|
||||||
is_context_name = True
|
is_value_name = True
|
||||||
"""
|
"""
|
||||||
Used for the Jedi API to know if it's a keyword or an actual name.
|
Used for the Jedi API to know if it's a keyword or an actual name.
|
||||||
"""
|
"""
|
||||||
@@ -32,7 +32,7 @@ class AbstractNameDefinition(object):
|
|||||||
if qualified_names is None or not include_module_names:
|
if qualified_names is None or not include_module_names:
|
||||||
return qualified_names
|
return qualified_names
|
||||||
|
|
||||||
module_names = self.get_root_context().string_names
|
module_names = self.get_root_value().string_names
|
||||||
if module_names is None:
|
if module_names is None:
|
||||||
return None
|
return None
|
||||||
return module_names + qualified_names
|
return module_names + qualified_names
|
||||||
@@ -41,8 +41,8 @@ class AbstractNameDefinition(object):
|
|||||||
# By default, a name has no qualified names.
|
# By default, a name has no qualified names.
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def get_root_context(self):
|
def get_root_value(self):
|
||||||
return self.parent_context.get_root_context()
|
return self.parent_value.get_root_value()
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
if self.start_pos is None:
|
if self.start_pos is None:
|
||||||
@@ -55,7 +55,7 @@ class AbstractNameDefinition(object):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def api_type(self):
|
def api_type(self):
|
||||||
return self.parent_context.api_type
|
return self.parent_value.api_type
|
||||||
|
|
||||||
|
|
||||||
class AbstractArbitraryName(AbstractNameDefinition):
|
class AbstractArbitraryName(AbstractNameDefinition):
|
||||||
@@ -64,20 +64,20 @@ class AbstractArbitraryName(AbstractNameDefinition):
|
|||||||
string literals, which is not really a name, but for Jedi we use this
|
string literals, which is not really a name, but for Jedi we use this
|
||||||
concept of Name for completions as well.
|
concept of Name for completions as well.
|
||||||
"""
|
"""
|
||||||
is_context_name = False
|
is_value_name = False
|
||||||
|
|
||||||
def __init__(self, infer_state, string):
|
def __init__(self, infer_state, string):
|
||||||
self.infer_state = infer_state
|
self.infer_state = infer_state
|
||||||
self.string_name = string
|
self.string_name = string
|
||||||
self.parent_context = infer_state.builtins_module
|
self.parent_value = infer_state.builtins_module
|
||||||
|
|
||||||
def infer(self):
|
def infer(self):
|
||||||
return NO_CONTEXTS
|
return NO_CONTEXTS
|
||||||
|
|
||||||
|
|
||||||
class AbstractTreeName(AbstractNameDefinition):
|
class AbstractTreeName(AbstractNameDefinition):
|
||||||
def __init__(self, parent_context, tree_name):
|
def __init__(self, parent_value, tree_name):
|
||||||
self.parent_context = parent_context
|
self.parent_value = parent_value
|
||||||
self.tree_name = tree_name
|
self.tree_name = tree_name
|
||||||
|
|
||||||
def get_qualified_names(self, include_module_names=False):
|
def get_qualified_names(self, include_module_names=False):
|
||||||
@@ -87,7 +87,7 @@ class AbstractTreeName(AbstractNameDefinition):
|
|||||||
# In case of level == 1, it works always, because it's like a submodule
|
# In case of level == 1, it works always, because it's like a submodule
|
||||||
# lookup.
|
# lookup.
|
||||||
if import_node is not None and not (import_node.level == 1
|
if import_node is not None and not (import_node.level == 1
|
||||||
and self.get_root_context().is_package):
|
and self.get_root_value().is_package):
|
||||||
# TODO improve the situation for when level is present.
|
# TODO improve the situation for when level is present.
|
||||||
if include_module_names and not import_node.level:
|
if include_module_names and not import_node.level:
|
||||||
return tuple(n.value for n in import_node.get_path_for_name(self.tree_name))
|
return tuple(n.value for n in import_node.get_path_for_name(self.tree_name))
|
||||||
@@ -97,13 +97,13 @@ class AbstractTreeName(AbstractNameDefinition):
|
|||||||
return super(AbstractTreeName, self).get_qualified_names(include_module_names)
|
return super(AbstractTreeName, self).get_qualified_names(include_module_names)
|
||||||
|
|
||||||
def _get_qualified_names(self):
|
def _get_qualified_names(self):
|
||||||
parent_names = self.parent_context.get_qualified_names()
|
parent_names = self.parent_value.get_qualified_names()
|
||||||
if parent_names is None:
|
if parent_names is None:
|
||||||
return None
|
return None
|
||||||
return parent_names + (self.tree_name.value,)
|
return parent_names + (self.tree_name.value,)
|
||||||
|
|
||||||
def goto(self, **kwargs):
|
def goto(self, **kwargs):
|
||||||
return self.parent_context.infer_state.goto(self.parent_context, self.tree_name, **kwargs)
|
return self.parent_value.infer_state.goto(self.parent_value, self.tree_name, **kwargs)
|
||||||
|
|
||||||
def is_import(self):
|
def is_import(self):
|
||||||
imp = search_ancestor(self.tree_name, 'import_from', 'import_name')
|
imp = search_ancestor(self.tree_name, 'import_from', 'import_name')
|
||||||
@@ -120,28 +120,28 @@ class AbstractTreeName(AbstractNameDefinition):
|
|||||||
|
|
||||||
class ContextNameMixin(object):
|
class ContextNameMixin(object):
|
||||||
def infer(self):
|
def infer(self):
|
||||||
return ContextSet([self._context])
|
return ContextSet([self._value])
|
||||||
|
|
||||||
def _get_qualified_names(self):
|
def _get_qualified_names(self):
|
||||||
return self._context.get_qualified_names()
|
return self._value.get_qualified_names()
|
||||||
|
|
||||||
def get_root_context(self):
|
def get_root_value(self):
|
||||||
if self.parent_context is None: # A module
|
if self.parent_value is None: # A module
|
||||||
return self._context
|
return self._value
|
||||||
return super(ContextNameMixin, self).get_root_context()
|
return super(ContextNameMixin, self).get_root_value()
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def api_type(self):
|
def api_type(self):
|
||||||
return self._context.api_type
|
return self._value.api_type
|
||||||
|
|
||||||
|
|
||||||
class ContextName(ContextNameMixin, AbstractTreeName):
|
class ContextName(ContextNameMixin, AbstractTreeName):
|
||||||
def __init__(self, context, tree_name):
|
def __init__(self, value, tree_name):
|
||||||
super(ContextName, self).__init__(context.parent_context, tree_name)
|
super(ContextName, self).__init__(value.parent_value, tree_name)
|
||||||
self._context = context
|
self._value = value
|
||||||
|
|
||||||
def goto(self):
|
def goto(self):
|
||||||
return ContextSet([self._context.name])
|
return ContextSet([self._value.name])
|
||||||
|
|
||||||
|
|
||||||
class TreeNameDefinition(AbstractTreeName):
|
class TreeNameDefinition(AbstractTreeName):
|
||||||
@@ -155,9 +155,9 @@ class TreeNameDefinition(AbstractTreeName):
|
|||||||
|
|
||||||
def infer(self):
|
def infer(self):
|
||||||
# Refactor this, should probably be here.
|
# Refactor this, should probably be here.
|
||||||
from jedi.inference.syntax_tree import tree_name_to_contexts
|
from jedi.inference.syntax_tree import tree_name_to_values
|
||||||
parent = self.parent_context
|
parent = self.parent_value
|
||||||
return tree_name_to_contexts(parent.infer_state, parent, self.tree_name)
|
return tree_name_to_values(parent.infer_state, parent, self.tree_name)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def api_type(self):
|
def api_type(self):
|
||||||
@@ -241,16 +241,16 @@ class ParamName(BaseTreeParamName):
|
|||||||
node = self.annotation_node
|
node = self.annotation_node
|
||||||
if node is None:
|
if node is None:
|
||||||
return NO_CONTEXTS
|
return NO_CONTEXTS
|
||||||
contexts = self.parent_context.parent_context.infer_node(node)
|
values = self.parent_value.parent_value.infer_node(node)
|
||||||
if execute_annotation:
|
if execute_annotation:
|
||||||
contexts = contexts.execute_annotation()
|
values = values.execute_annotation()
|
||||||
return contexts
|
return values
|
||||||
|
|
||||||
def infer_default(self):
|
def infer_default(self):
|
||||||
node = self.default_node
|
node = self.default_node
|
||||||
if node is None:
|
if node is None:
|
||||||
return NO_CONTEXTS
|
return NO_CONTEXTS
|
||||||
return self.parent_context.parent_context.infer_node(node)
|
return self.parent_value.parent_value.infer_node(node)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def default_node(self):
|
def default_node(self):
|
||||||
@@ -297,7 +297,7 @@ class ParamName(BaseTreeParamName):
|
|||||||
return self.get_param().infer()
|
return self.get_param().infer()
|
||||||
|
|
||||||
def get_param(self):
|
def get_param(self):
|
||||||
params, _ = self.parent_context.get_executed_params_and_issues()
|
params, _ = self.parent_value.get_executed_params_and_issues()
|
||||||
param_node = search_ancestor(self.tree_name, 'param')
|
param_node = search_ancestor(self.tree_name, 'param')
|
||||||
return params[param_node.position_index]
|
return params[param_node.position_index]
|
||||||
|
|
||||||
@@ -317,15 +317,15 @@ class ImportName(AbstractNameDefinition):
|
|||||||
start_pos = (1, 0)
|
start_pos = (1, 0)
|
||||||
_level = 0
|
_level = 0
|
||||||
|
|
||||||
def __init__(self, parent_context, string_name):
|
def __init__(self, parent_value, string_name):
|
||||||
self._from_module_context = parent_context
|
self._from_module_value = parent_value
|
||||||
self.string_name = string_name
|
self.string_name = string_name
|
||||||
|
|
||||||
def get_qualified_names(self, include_module_names=False):
|
def get_qualified_names(self, include_module_names=False):
|
||||||
if include_module_names:
|
if include_module_names:
|
||||||
if self._level:
|
if self._level:
|
||||||
assert self._level == 1, "Everything else is not supported for now"
|
assert self._level == 1, "Everything else is not supported for now"
|
||||||
module_names = self._from_module_context.string_names
|
module_names = self._from_module_value.string_names
|
||||||
if module_names is None:
|
if module_names is None:
|
||||||
return module_names
|
return module_names
|
||||||
return module_names + (self.string_name,)
|
return module_names + (self.string_name,)
|
||||||
@@ -333,19 +333,19 @@ class ImportName(AbstractNameDefinition):
|
|||||||
return ()
|
return ()
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def parent_context(self):
|
def parent_value(self):
|
||||||
m = self._from_module_context
|
m = self._from_module_value
|
||||||
import_contexts = self.infer()
|
import_values = self.infer()
|
||||||
if not import_contexts:
|
if not import_values:
|
||||||
return m
|
return m
|
||||||
# It's almost always possible to find the import or to not find it. The
|
# It's almost always possible to find the import or to not find it. The
|
||||||
# importing returns only one context, pretty much always.
|
# importing returns only one value, pretty much always.
|
||||||
return next(iter(import_contexts))
|
return next(iter(import_values))
|
||||||
|
|
||||||
@memoize_method
|
@memoize_method
|
||||||
def infer(self):
|
def infer(self):
|
||||||
from jedi.inference.imports import Importer
|
from jedi.inference.imports import Importer
|
||||||
m = self._from_module_context
|
m = self._from_module_value
|
||||||
return Importer(m.infer_state, [self.string_name], m, level=self._level).follow()
|
return Importer(m.infer_state, [self.string_name], m, level=self._level).follow()
|
||||||
|
|
||||||
def goto(self):
|
def goto(self):
|
||||||
|
|||||||
+48
-48
@@ -3,46 +3,46 @@ from collections import defaultdict
|
|||||||
from jedi import debug
|
from jedi import debug
|
||||||
from jedi.inference.utils import PushBackIterator
|
from jedi.inference.utils import PushBackIterator
|
||||||
from jedi.inference import analysis
|
from jedi.inference import analysis
|
||||||
from jedi.inference.lazy_context import LazyKnownContext, \
|
from jedi.inference.lazy_value import LazyKnownContext, \
|
||||||
LazyTreeContext, LazyUnknownContext
|
LazyTreeContext, LazyUnknownContext
|
||||||
from jedi.inference import docstrings
|
from jedi.inference import docstrings
|
||||||
from jedi.inference.context import iterable
|
from jedi.inference.value import iterable
|
||||||
|
|
||||||
|
|
||||||
def _add_argument_issue(error_name, lazy_context, message):
|
def _add_argument_issue(error_name, lazy_value, message):
|
||||||
if isinstance(lazy_context, LazyTreeContext):
|
if isinstance(lazy_value, LazyTreeContext):
|
||||||
node = lazy_context.data
|
node = lazy_value.data
|
||||||
if node.parent.type == 'argument':
|
if node.parent.type == 'argument':
|
||||||
node = node.parent
|
node = node.parent
|
||||||
return analysis.add(lazy_context.context, error_name, node, message)
|
return analysis.add(lazy_value.value, error_name, node, message)
|
||||||
|
|
||||||
|
|
||||||
class ExecutedParam(object):
|
class ExecutedParam(object):
|
||||||
"""Fake a param and give it values."""
|
"""Fake a param and give it values."""
|
||||||
def __init__(self, execution_context, param_node, lazy_context, is_default=False):
|
def __init__(self, execution_value, param_node, lazy_value, is_default=False):
|
||||||
self._execution_context = execution_context
|
self._execution_value = execution_value
|
||||||
self._param_node = param_node
|
self._param_node = param_node
|
||||||
self._lazy_context = lazy_context
|
self._lazy_value = lazy_value
|
||||||
self.string_name = param_node.name.value
|
self.string_name = param_node.name.value
|
||||||
self._is_default = is_default
|
self._is_default = is_default
|
||||||
|
|
||||||
def infer_annotations(self):
|
def infer_annotations(self):
|
||||||
from jedi.inference.gradual.annotation import infer_param
|
from jedi.inference.gradual.annotation import infer_param
|
||||||
return infer_param(self._execution_context, self._param_node)
|
return infer_param(self._execution_value, self._param_node)
|
||||||
|
|
||||||
def infer(self, use_hints=True):
|
def infer(self, use_hints=True):
|
||||||
if use_hints:
|
if use_hints:
|
||||||
doc_params = docstrings.infer_param(self._execution_context, self._param_node)
|
doc_params = docstrings.infer_param(self._execution_value, self._param_node)
|
||||||
ann = self.infer_annotations().execute_annotation()
|
ann = self.infer_annotations().execute_annotation()
|
||||||
if ann or doc_params:
|
if ann or doc_params:
|
||||||
return ann | doc_params
|
return ann | doc_params
|
||||||
|
|
||||||
return self._lazy_context.infer()
|
return self._lazy_value.infer()
|
||||||
|
|
||||||
def matches_signature(self):
|
def matches_signature(self):
|
||||||
if self._is_default:
|
if self._is_default:
|
||||||
return True
|
return True
|
||||||
argument_contexts = self.infer(use_hints=False).py__class__()
|
argument_values = self.infer(use_hints=False).py__class__()
|
||||||
if self._param_node.star_count:
|
if self._param_node.star_count:
|
||||||
return True
|
return True
|
||||||
annotations = self.infer_annotations()
|
annotations = self.infer_annotations()
|
||||||
@@ -51,21 +51,21 @@ class ExecutedParam(object):
|
|||||||
# that the signature matches.
|
# that the signature matches.
|
||||||
return True
|
return True
|
||||||
matches = any(c1.is_sub_class_of(c2)
|
matches = any(c1.is_sub_class_of(c2)
|
||||||
for c1 in argument_contexts
|
for c1 in argument_values
|
||||||
for c2 in annotations.gather_annotation_classes())
|
for c2 in annotations.gather_annotation_classes())
|
||||||
debug.dbg("signature compare %s: %s <=> %s",
|
debug.dbg("signature compare %s: %s <=> %s",
|
||||||
matches, argument_contexts, annotations, color='BLUE')
|
matches, argument_values, annotations, color='BLUE')
|
||||||
return matches
|
return matches
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def var_args(self):
|
def var_args(self):
|
||||||
return self._execution_context.var_args
|
return self._execution_value.var_args
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return '<%s: %s>' % (self.__class__.__name__, self.string_name)
|
return '<%s: %s>' % (self.__class__.__name__, self.string_name)
|
||||||
|
|
||||||
|
|
||||||
def get_executed_params_and_issues(execution_context, arguments):
|
def get_executed_params_and_issues(execution_value, arguments):
|
||||||
def too_many_args(argument):
|
def too_many_args(argument):
|
||||||
m = _error_argument_count(funcdef, len(unpacked_va))
|
m = _error_argument_count(funcdef, len(unpacked_va))
|
||||||
# Just report an error for the first param that is not needed (like
|
# Just report an error for the first param that is not needed (like
|
||||||
@@ -85,11 +85,11 @@ def get_executed_params_and_issues(execution_context, arguments):
|
|||||||
issues = [] # List[Optional[analysis issue]]
|
issues = [] # List[Optional[analysis issue]]
|
||||||
result_params = []
|
result_params = []
|
||||||
param_dict = {}
|
param_dict = {}
|
||||||
funcdef = execution_context.tree_node
|
funcdef = execution_value.tree_node
|
||||||
# Default params are part of the context where the function was defined.
|
# Default params are part of the value where the function was defined.
|
||||||
# This means that they might have access on class variables that the
|
# This means that they might have access on class variables that the
|
||||||
# function itself doesn't have.
|
# function itself doesn't have.
|
||||||
default_param_context = execution_context.function_context.get_default_param_context()
|
default_param_value = execution_value.function_value.get_default_param_value()
|
||||||
|
|
||||||
for param in funcdef.get_params():
|
for param in funcdef.get_params():
|
||||||
param_dict[param.name.value] = param
|
param_dict[param.name.value] = param
|
||||||
@@ -118,14 +118,14 @@ def get_executed_params_and_issues(execution_context, arguments):
|
|||||||
had_multiple_value_error = True
|
had_multiple_value_error = True
|
||||||
m = ("TypeError: %s() got multiple values for keyword argument '%s'."
|
m = ("TypeError: %s() got multiple values for keyword argument '%s'."
|
||||||
% (funcdef.name, key))
|
% (funcdef.name, key))
|
||||||
for contextualized_node in arguments.get_calling_nodes():
|
for valueualized_node in arguments.get_calling_nodes():
|
||||||
issues.append(
|
issues.append(
|
||||||
analysis.add(contextualized_node.context,
|
analysis.add(valueualized_node.value,
|
||||||
'type-error-multiple-values',
|
'type-error-multiple-values',
|
||||||
contextualized_node.node, message=m)
|
valueualized_node.node, message=m)
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
keys_used[key] = ExecutedParam(execution_context, key_param, argument)
|
keys_used[key] = ExecutedParam(execution_value, key_param, argument)
|
||||||
key, argument = next(var_arg_iterator, (None, None))
|
key, argument = next(var_arg_iterator, (None, None))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@@ -136,22 +136,22 @@ def get_executed_params_and_issues(execution_context, arguments):
|
|||||||
|
|
||||||
if param.star_count == 1:
|
if param.star_count == 1:
|
||||||
# *args param
|
# *args param
|
||||||
lazy_context_list = []
|
lazy_value_list = []
|
||||||
if argument is not None:
|
if argument is not None:
|
||||||
lazy_context_list.append(argument)
|
lazy_value_list.append(argument)
|
||||||
for key, argument in var_arg_iterator:
|
for key, argument in var_arg_iterator:
|
||||||
# Iterate until a key argument is found.
|
# Iterate until a key argument is found.
|
||||||
if key:
|
if key:
|
||||||
var_arg_iterator.push_back((key, argument))
|
var_arg_iterator.push_back((key, argument))
|
||||||
break
|
break
|
||||||
lazy_context_list.append(argument)
|
lazy_value_list.append(argument)
|
||||||
seq = iterable.FakeSequence(execution_context.infer_state, u'tuple', lazy_context_list)
|
seq = iterable.FakeSequence(execution_value.infer_state, u'tuple', lazy_value_list)
|
||||||
result_arg = LazyKnownContext(seq)
|
result_arg = LazyKnownContext(seq)
|
||||||
elif param.star_count == 2:
|
elif param.star_count == 2:
|
||||||
if argument is not None:
|
if argument is not None:
|
||||||
too_many_args(argument)
|
too_many_args(argument)
|
||||||
# **kwargs param
|
# **kwargs param
|
||||||
dct = iterable.FakeDict(execution_context.infer_state, dict(non_matching_keys))
|
dct = iterable.FakeDict(execution_value.infer_state, dict(non_matching_keys))
|
||||||
result_arg = LazyKnownContext(dct)
|
result_arg = LazyKnownContext(dct)
|
||||||
non_matching_keys = {}
|
non_matching_keys = {}
|
||||||
else:
|
else:
|
||||||
@@ -161,24 +161,24 @@ def get_executed_params_and_issues(execution_context, arguments):
|
|||||||
if param.default is None:
|
if param.default is None:
|
||||||
result_arg = LazyUnknownContext()
|
result_arg = LazyUnknownContext()
|
||||||
if not keys_only:
|
if not keys_only:
|
||||||
for contextualized_node in arguments.get_calling_nodes():
|
for valueualized_node in arguments.get_calling_nodes():
|
||||||
m = _error_argument_count(funcdef, len(unpacked_va))
|
m = _error_argument_count(funcdef, len(unpacked_va))
|
||||||
issues.append(
|
issues.append(
|
||||||
analysis.add(
|
analysis.add(
|
||||||
contextualized_node.context,
|
valueualized_node.value,
|
||||||
'type-error-too-few-arguments',
|
'type-error-too-few-arguments',
|
||||||
contextualized_node.node,
|
valueualized_node.node,
|
||||||
message=m,
|
message=m,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
result_arg = LazyTreeContext(default_param_context, param.default)
|
result_arg = LazyTreeContext(default_param_value, param.default)
|
||||||
is_default = True
|
is_default = True
|
||||||
else:
|
else:
|
||||||
result_arg = argument
|
result_arg = argument
|
||||||
|
|
||||||
result_params.append(ExecutedParam(
|
result_params.append(ExecutedParam(
|
||||||
execution_context, param, result_arg,
|
execution_value, param, result_arg,
|
||||||
is_default=is_default
|
is_default=is_default
|
||||||
))
|
))
|
||||||
if not isinstance(result_arg, LazyUnknownContext):
|
if not isinstance(result_arg, LazyUnknownContext):
|
||||||
@@ -194,29 +194,29 @@ def get_executed_params_and_issues(execution_context, arguments):
|
|||||||
if not (non_matching_keys or had_multiple_value_error or
|
if not (non_matching_keys or had_multiple_value_error or
|
||||||
param.star_count or param.default):
|
param.star_count or param.default):
|
||||||
# add a warning only if there's not another one.
|
# add a warning only if there's not another one.
|
||||||
for contextualized_node in arguments.get_calling_nodes():
|
for valueualized_node in arguments.get_calling_nodes():
|
||||||
m = _error_argument_count(funcdef, len(unpacked_va))
|
m = _error_argument_count(funcdef, len(unpacked_va))
|
||||||
issues.append(
|
issues.append(
|
||||||
analysis.add(contextualized_node.context,
|
analysis.add(valueualized_node.value,
|
||||||
'type-error-too-few-arguments',
|
'type-error-too-few-arguments',
|
||||||
contextualized_node.node, message=m)
|
valueualized_node.node, message=m)
|
||||||
)
|
)
|
||||||
|
|
||||||
for key, lazy_context in non_matching_keys.items():
|
for key, lazy_value in non_matching_keys.items():
|
||||||
m = "TypeError: %s() got an unexpected keyword argument '%s'." \
|
m = "TypeError: %s() got an unexpected keyword argument '%s'." \
|
||||||
% (funcdef.name, key)
|
% (funcdef.name, key)
|
||||||
issues.append(
|
issues.append(
|
||||||
_add_argument_issue(
|
_add_argument_issue(
|
||||||
'type-error-keyword-argument',
|
'type-error-keyword-argument',
|
||||||
lazy_context,
|
lazy_value,
|
||||||
message=m
|
message=m
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
remaining_arguments = list(var_arg_iterator)
|
remaining_arguments = list(var_arg_iterator)
|
||||||
if remaining_arguments:
|
if remaining_arguments:
|
||||||
first_key, lazy_context = remaining_arguments[0]
|
first_key, lazy_value = remaining_arguments[0]
|
||||||
too_many_args(lazy_context)
|
too_many_args(lazy_value)
|
||||||
return result_params, issues
|
return result_params, issues
|
||||||
|
|
||||||
|
|
||||||
@@ -232,22 +232,22 @@ def _error_argument_count(funcdef, actual_count):
|
|||||||
% (funcdef.name, before, len(params), actual_count))
|
% (funcdef.name, before, len(params), actual_count))
|
||||||
|
|
||||||
|
|
||||||
def _create_default_param(execution_context, param):
|
def _create_default_param(execution_value, param):
|
||||||
if param.star_count == 1:
|
if param.star_count == 1:
|
||||||
result_arg = LazyKnownContext(
|
result_arg = LazyKnownContext(
|
||||||
iterable.FakeSequence(execution_context.infer_state, u'tuple', [])
|
iterable.FakeSequence(execution_value.infer_state, u'tuple', [])
|
||||||
)
|
)
|
||||||
elif param.star_count == 2:
|
elif param.star_count == 2:
|
||||||
result_arg = LazyKnownContext(
|
result_arg = LazyKnownContext(
|
||||||
iterable.FakeDict(execution_context.infer_state, {})
|
iterable.FakeDict(execution_value.infer_state, {})
|
||||||
)
|
)
|
||||||
elif param.default is None:
|
elif param.default is None:
|
||||||
result_arg = LazyUnknownContext()
|
result_arg = LazyUnknownContext()
|
||||||
else:
|
else:
|
||||||
result_arg = LazyTreeContext(execution_context.parent_context, param.default)
|
result_arg = LazyTreeContext(execution_value.parent_value, param.default)
|
||||||
return ExecutedParam(execution_context, param, result_arg)
|
return ExecutedParam(execution_value, param, result_arg)
|
||||||
|
|
||||||
|
|
||||||
def create_default_params(execution_context, funcdef):
|
def create_default_params(execution_value, funcdef):
|
||||||
return [_create_default_param(execution_context, p)
|
return [_create_default_param(execution_value, p)
|
||||||
for p in funcdef.get_params()]
|
for p in funcdef.get_params()]
|
||||||
|
|||||||
@@ -115,7 +115,7 @@ class ExecutionRecursionDetector(object):
|
|||||||
self._recursion_level += 1
|
self._recursion_level += 1
|
||||||
self._parent_execution_funcs.append(funcdef)
|
self._parent_execution_funcs.append(funcdef)
|
||||||
|
|
||||||
module = execution.get_root_context()
|
module = execution.get_root_value()
|
||||||
|
|
||||||
if module == self._infer_state.builtins_module:
|
if module == self._infer_state.builtins_module:
|
||||||
# We have control over builtins so we know they are not recursing
|
# We have control over builtins so we know they are not recursing
|
||||||
|
|||||||
+19
-19
@@ -33,46 +33,46 @@ class _SignatureMixin(object):
|
|||||||
|
|
||||||
|
|
||||||
class AbstractSignature(_SignatureMixin):
|
class AbstractSignature(_SignatureMixin):
|
||||||
def __init__(self, context, is_bound=False):
|
def __init__(self, value, is_bound=False):
|
||||||
self.context = context
|
self.value = value
|
||||||
self.is_bound = is_bound
|
self.is_bound = is_bound
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def name(self):
|
def name(self):
|
||||||
return self.context.name
|
return self.value.name
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def annotation_string(self):
|
def annotation_string(self):
|
||||||
return ''
|
return ''
|
||||||
|
|
||||||
def get_param_names(self, resolve_stars=False):
|
def get_param_names(self, resolve_stars=False):
|
||||||
param_names = self._function_context.get_param_names()
|
param_names = self._function_value.get_param_names()
|
||||||
if self.is_bound:
|
if self.is_bound:
|
||||||
return param_names[1:]
|
return param_names[1:]
|
||||||
return param_names
|
return param_names
|
||||||
|
|
||||||
def bind(self, context):
|
def bind(self, value):
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return '<%s: %s, %s>' % (self.__class__.__name__, self.context, self._function_context)
|
return '<%s: %s, %s>' % (self.__class__.__name__, self.value, self._function_value)
|
||||||
|
|
||||||
|
|
||||||
class TreeSignature(AbstractSignature):
|
class TreeSignature(AbstractSignature):
|
||||||
def __init__(self, context, function_context=None, is_bound=False):
|
def __init__(self, value, function_value=None, is_bound=False):
|
||||||
super(TreeSignature, self).__init__(context, is_bound)
|
super(TreeSignature, self).__init__(value, is_bound)
|
||||||
self._function_context = function_context or context
|
self._function_value = function_value or value
|
||||||
|
|
||||||
def bind(self, context):
|
def bind(self, value):
|
||||||
return TreeSignature(context, self._function_context, is_bound=True)
|
return TreeSignature(value, self._function_value, is_bound=True)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def _annotation(self):
|
def _annotation(self):
|
||||||
# Classes don't need annotations, even if __init__ has one. They always
|
# Classes don't need annotations, even if __init__ has one. They always
|
||||||
# return themselves.
|
# return themselves.
|
||||||
if self.context.is_class():
|
if self.value.is_class():
|
||||||
return None
|
return None
|
||||||
return self._function_context.tree_node.annotation
|
return self._function_value.tree_node.annotation
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def annotation_string(self):
|
def annotation_string(self):
|
||||||
@@ -91,8 +91,8 @@ class TreeSignature(AbstractSignature):
|
|||||||
|
|
||||||
|
|
||||||
class BuiltinSignature(AbstractSignature):
|
class BuiltinSignature(AbstractSignature):
|
||||||
def __init__(self, context, return_string, is_bound=False):
|
def __init__(self, value, return_string, is_bound=False):
|
||||||
super(BuiltinSignature, self).__init__(context, is_bound)
|
super(BuiltinSignature, self).__init__(value, is_bound)
|
||||||
self._return_string = return_string
|
self._return_string = return_string
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@@ -100,12 +100,12 @@ class BuiltinSignature(AbstractSignature):
|
|||||||
return self._return_string
|
return self._return_string
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def _function_context(self):
|
def _function_value(self):
|
||||||
return self.context
|
return self.value
|
||||||
|
|
||||||
def bind(self, context):
|
def bind(self, value):
|
||||||
assert not self.is_bound
|
assert not self.is_bound
|
||||||
return BuiltinSignature(context, self._return_string, is_bound=True)
|
return BuiltinSignature(value, self._return_string, is_bound=True)
|
||||||
|
|
||||||
|
|
||||||
class SignatureWrapper(_SignatureMixin):
|
class SignatureWrapper(_SignatureMixin):
|
||||||
|
|||||||
+15
-15
@@ -20,8 +20,8 @@ def _iter_nodes_for_param(param_name):
|
|||||||
from parso.python.tree import search_ancestor
|
from parso.python.tree import search_ancestor
|
||||||
from jedi.inference.arguments import TreeArguments
|
from jedi.inference.arguments import TreeArguments
|
||||||
|
|
||||||
execution_context = param_name.parent_context
|
execution_value = param_name.parent_value
|
||||||
function_node = execution_context.tree_node
|
function_node = execution_value.tree_node
|
||||||
module_node = function_node.get_root_node()
|
module_node = function_node.get_root_node()
|
||||||
start = function_node.children[-1].start_pos
|
start = function_node.children[-1].start_pos
|
||||||
end = function_node.children[-1].end_pos
|
end = function_node.children[-1].end_pos
|
||||||
@@ -35,44 +35,44 @@ def _iter_nodes_for_param(param_name):
|
|||||||
# anyway
|
# anyway
|
||||||
trailer = search_ancestor(argument, 'trailer')
|
trailer = search_ancestor(argument, 'trailer')
|
||||||
if trailer is not None: # Make sure we're in a function
|
if trailer is not None: # Make sure we're in a function
|
||||||
context = execution_context.create_context(trailer)
|
value = execution_value.create_value(trailer)
|
||||||
if _goes_to_param_name(param_name, context, name):
|
if _goes_to_param_name(param_name, value, name):
|
||||||
contexts = _to_callables(context, trailer)
|
values = _to_callables(value, trailer)
|
||||||
|
|
||||||
args = TreeArguments.create_cached(
|
args = TreeArguments.create_cached(
|
||||||
execution_context.infer_state,
|
execution_value.infer_state,
|
||||||
context=context,
|
value=value,
|
||||||
argument_node=trailer.children[1],
|
argument_node=trailer.children[1],
|
||||||
trailer=trailer,
|
trailer=trailer,
|
||||||
)
|
)
|
||||||
for c in contexts:
|
for c in values:
|
||||||
yield c, args
|
yield c, args
|
||||||
else:
|
else:
|
||||||
assert False
|
assert False
|
||||||
|
|
||||||
|
|
||||||
def _goes_to_param_name(param_name, context, potential_name):
|
def _goes_to_param_name(param_name, value, potential_name):
|
||||||
if potential_name.type != 'name':
|
if potential_name.type != 'name':
|
||||||
return False
|
return False
|
||||||
from jedi.inference.names import TreeNameDefinition
|
from jedi.inference.names import TreeNameDefinition
|
||||||
found = TreeNameDefinition(context, potential_name).goto()
|
found = TreeNameDefinition(value, potential_name).goto()
|
||||||
return any(param_name.parent_context == p.parent_context
|
return any(param_name.parent_value == p.parent_value
|
||||||
and param_name.start_pos == p.start_pos
|
and param_name.start_pos == p.start_pos
|
||||||
for p in found)
|
for p in found)
|
||||||
|
|
||||||
|
|
||||||
def _to_callables(context, trailer):
|
def _to_callables(value, trailer):
|
||||||
from jedi.inference.syntax_tree import infer_trailer
|
from jedi.inference.syntax_tree import infer_trailer
|
||||||
|
|
||||||
atom_expr = trailer.parent
|
atom_expr = trailer.parent
|
||||||
index = atom_expr.children[0] == 'await'
|
index = atom_expr.children[0] == 'await'
|
||||||
# Infer atom first
|
# Infer atom first
|
||||||
contexts = context.infer_node(atom_expr.children[index])
|
values = value.infer_node(atom_expr.children[index])
|
||||||
for trailer2 in atom_expr.children[index + 1:]:
|
for trailer2 in atom_expr.children[index + 1:]:
|
||||||
if trailer == trailer2:
|
if trailer == trailer2:
|
||||||
break
|
break
|
||||||
contexts = infer_trailer(context, contexts, trailer2)
|
values = infer_trailer(value, values, trailer2)
|
||||||
return contexts
|
return values
|
||||||
|
|
||||||
|
|
||||||
def _remove_given_params(arguments, param_names):
|
def _remove_given_params(arguments, param_names):
|
||||||
|
|||||||
+181
-181
@@ -9,28 +9,28 @@ from jedi._compatibility import force_unicode, unicode
|
|||||||
from jedi import debug
|
from jedi import debug
|
||||||
from jedi import parser_utils
|
from jedi import parser_utils
|
||||||
from jedi.inference.base_value import ContextSet, NO_CONTEXTS, ContextualizedNode, \
|
from jedi.inference.base_value import ContextSet, NO_CONTEXTS, ContextualizedNode, \
|
||||||
ContextualizedName, iterator_to_context_set, iterate_contexts
|
ContextualizedName, iterator_to_value_set, iterate_values
|
||||||
from jedi.inference.lazy_context import LazyTreeContext
|
from jedi.inference.lazy_value import LazyTreeContext
|
||||||
from jedi.inference import compiled
|
from jedi.inference import compiled
|
||||||
from jedi.inference import recursion
|
from jedi.inference import recursion
|
||||||
from jedi.inference import helpers
|
from jedi.inference import helpers
|
||||||
from jedi.inference import analysis
|
from jedi.inference import analysis
|
||||||
from jedi.inference import imports
|
from jedi.inference import imports
|
||||||
from jedi.inference import arguments
|
from jedi.inference import arguments
|
||||||
from jedi.inference.context import ClassContext, FunctionContext
|
from jedi.inference.value import ClassContext, FunctionContext
|
||||||
from jedi.inference.context import iterable
|
from jedi.inference.value import iterable
|
||||||
from jedi.inference.context import TreeInstance
|
from jedi.inference.value import TreeInstance
|
||||||
from jedi.inference.finder import NameFinder
|
from jedi.inference.finder import NameFinder
|
||||||
from jedi.inference.helpers import is_string, is_literal, is_number
|
from jedi.inference.helpers import is_string, is_literal, is_number
|
||||||
from jedi.inference.compiled.access import COMPARISON_OPERATORS
|
from jedi.inference.compiled.access import COMPARISON_OPERATORS
|
||||||
from jedi.inference.cache import infer_state_method_cache
|
from jedi.inference.cache import infer_state_method_cache
|
||||||
from jedi.inference.gradual.stub_context import VersionInfo
|
from jedi.inference.gradual.stub_value import VersionInfo
|
||||||
from jedi.inference.gradual import annotation
|
from jedi.inference.gradual import annotation
|
||||||
from jedi.inference.context.decorator import Decoratee
|
from jedi.inference.value.decorator import Decoratee
|
||||||
from jedi.plugins import plugin_manager
|
from jedi.plugins import plugin_manager
|
||||||
|
|
||||||
|
|
||||||
def _limit_context_infers(func):
|
def _limit_value_infers(func):
|
||||||
"""
|
"""
|
||||||
This is for now the way how we limit type inference going wild. There are
|
This is for now the way how we limit type inference going wild. There are
|
||||||
other ways to ensure recursion limits as well. This is mostly necessary
|
other ways to ensure recursion limits as well. This is mostly necessary
|
||||||
@@ -39,17 +39,17 @@ def _limit_context_infers(func):
|
|||||||
I'm still not sure this is the way to go, but it looks okay for now and we
|
I'm still not sure this is the way to go, but it looks okay for now and we
|
||||||
can still go anther way in the future. Tests are there. ~ dave
|
can still go anther way in the future. Tests are there. ~ dave
|
||||||
"""
|
"""
|
||||||
def wrapper(context, *args, **kwargs):
|
def wrapper(value, *args, **kwargs):
|
||||||
n = context.tree_node
|
n = value.tree_node
|
||||||
infer_state = context.infer_state
|
infer_state = value.infer_state
|
||||||
try:
|
try:
|
||||||
infer_state.inferred_element_counts[n] += 1
|
infer_state.inferred_element_counts[n] += 1
|
||||||
if infer_state.inferred_element_counts[n] > 300:
|
if infer_state.inferred_element_counts[n] > 300:
|
||||||
debug.warning('In context %s there were too many inferences.', n)
|
debug.warning('In value %s there were too many inferences.', n)
|
||||||
return NO_CONTEXTS
|
return NO_CONTEXTS
|
||||||
except KeyError:
|
except KeyError:
|
||||||
infer_state.inferred_element_counts[n] = 1
|
infer_state.inferred_element_counts[n] = 1
|
||||||
return func(context, *args, **kwargs)
|
return func(value, *args, **kwargs)
|
||||||
|
|
||||||
return wrapper
|
return wrapper
|
||||||
|
|
||||||
@@ -67,17 +67,17 @@ def _py__stop_iteration_returns(generators):
|
|||||||
|
|
||||||
|
|
||||||
@debug.increase_indent
|
@debug.increase_indent
|
||||||
@_limit_context_infers
|
@_limit_value_infers
|
||||||
def infer_node(context, element):
|
def infer_node(value, element):
|
||||||
debug.dbg('infer_node %s@%s in %s', element, element.start_pos, context)
|
debug.dbg('infer_node %s@%s in %s', element, element.start_pos, value)
|
||||||
infer_state = context.infer_state
|
infer_state = value.infer_state
|
||||||
typ = element.type
|
typ = element.type
|
||||||
if typ in ('name', 'number', 'string', 'atom', 'strings', 'keyword', 'fstring'):
|
if typ in ('name', 'number', 'string', 'atom', 'strings', 'keyword', 'fstring'):
|
||||||
return infer_atom(context, element)
|
return infer_atom(value, element)
|
||||||
elif typ == 'lambdef':
|
elif typ == 'lambdef':
|
||||||
return ContextSet([FunctionContext.from_context(context, element)])
|
return ContextSet([FunctionContext.from_value(value, element)])
|
||||||
elif typ == 'expr_stmt':
|
elif typ == 'expr_stmt':
|
||||||
return infer_expr_stmt(context, element)
|
return infer_expr_stmt(value, element)
|
||||||
elif typ in ('power', 'atom_expr'):
|
elif typ in ('power', 'atom_expr'):
|
||||||
first_child = element.children[0]
|
first_child = element.children[0]
|
||||||
children = element.children[1:]
|
children = element.children[1:]
|
||||||
@@ -86,35 +86,35 @@ def infer_node(context, element):
|
|||||||
had_await = True
|
had_await = True
|
||||||
first_child = children.pop(0)
|
first_child = children.pop(0)
|
||||||
|
|
||||||
context_set = context.infer_node(first_child)
|
value_set = value.infer_node(first_child)
|
||||||
for (i, trailer) in enumerate(children):
|
for (i, trailer) in enumerate(children):
|
||||||
if trailer == '**': # has a power operation.
|
if trailer == '**': # has a power operation.
|
||||||
right = context.infer_node(children[i + 1])
|
right = value.infer_node(children[i + 1])
|
||||||
context_set = _infer_comparison(
|
value_set = _infer_comparison(
|
||||||
infer_state,
|
infer_state,
|
||||||
context,
|
value,
|
||||||
context_set,
|
value_set,
|
||||||
trailer,
|
trailer,
|
||||||
right
|
right
|
||||||
)
|
)
|
||||||
break
|
break
|
||||||
context_set = infer_trailer(context, context_set, trailer)
|
value_set = infer_trailer(value, value_set, trailer)
|
||||||
|
|
||||||
if had_await:
|
if had_await:
|
||||||
return context_set.py__await__().py__stop_iteration_returns()
|
return value_set.py__await__().py__stop_iteration_returns()
|
||||||
return context_set
|
return value_set
|
||||||
elif typ in ('testlist_star_expr', 'testlist',):
|
elif typ in ('testlist_star_expr', 'testlist',):
|
||||||
# The implicit tuple in statements.
|
# The implicit tuple in statements.
|
||||||
return ContextSet([iterable.SequenceLiteralContext(infer_state, context, element)])
|
return ContextSet([iterable.SequenceLiteralContext(infer_state, value, element)])
|
||||||
elif typ in ('not_test', 'factor'):
|
elif typ in ('not_test', 'factor'):
|
||||||
context_set = context.infer_node(element.children[-1])
|
value_set = value.infer_node(element.children[-1])
|
||||||
for operator in element.children[:-1]:
|
for operator in element.children[:-1]:
|
||||||
context_set = infer_factor(context_set, operator)
|
value_set = infer_factor(value_set, operator)
|
||||||
return context_set
|
return value_set
|
||||||
elif typ == 'test':
|
elif typ == 'test':
|
||||||
# `x if foo else y` case.
|
# `x if foo else y` case.
|
||||||
return (context.infer_node(element.children[0]) |
|
return (value.infer_node(element.children[0]) |
|
||||||
context.infer_node(element.children[-1]))
|
value.infer_node(element.children[-1]))
|
||||||
elif typ == 'operator':
|
elif typ == 'operator':
|
||||||
# Must be an ellipsis, other operators are not inferred.
|
# Must be an ellipsis, other operators are not inferred.
|
||||||
# In Python 2 ellipsis is coded as three single dot tokens, not
|
# In Python 2 ellipsis is coded as three single dot tokens, not
|
||||||
@@ -124,57 +124,57 @@ def infer_node(context, element):
|
|||||||
raise AssertionError("unhandled operator %s in %s " % (repr(element.value), origin))
|
raise AssertionError("unhandled operator %s in %s " % (repr(element.value), origin))
|
||||||
return ContextSet([compiled.builtin_from_name(infer_state, u'Ellipsis')])
|
return ContextSet([compiled.builtin_from_name(infer_state, u'Ellipsis')])
|
||||||
elif typ == 'dotted_name':
|
elif typ == 'dotted_name':
|
||||||
context_set = infer_atom(context, element.children[0])
|
value_set = infer_atom(value, element.children[0])
|
||||||
for next_name in element.children[2::2]:
|
for next_name in element.children[2::2]:
|
||||||
# TODO add search_global=True?
|
# TODO add search_global=True?
|
||||||
context_set = context_set.py__getattribute__(next_name, name_context=context)
|
value_set = value_set.py__getattribute__(next_name, name_value=value)
|
||||||
return context_set
|
return value_set
|
||||||
elif typ == 'eval_input':
|
elif typ == 'eval_input':
|
||||||
return infer_node(context, element.children[0])
|
return infer_node(value, element.children[0])
|
||||||
elif typ == 'annassign':
|
elif typ == 'annassign':
|
||||||
return annotation.infer_annotation(context, element.children[1]) \
|
return annotation.infer_annotation(value, element.children[1]) \
|
||||||
.execute_annotation()
|
.execute_annotation()
|
||||||
elif typ == 'yield_expr':
|
elif typ == 'yield_expr':
|
||||||
if len(element.children) and element.children[1].type == 'yield_arg':
|
if len(element.children) and element.children[1].type == 'yield_arg':
|
||||||
# Implies that it's a yield from.
|
# Implies that it's a yield from.
|
||||||
element = element.children[1].children[1]
|
element = element.children[1].children[1]
|
||||||
generators = context.infer_node(element) \
|
generators = value.infer_node(element) \
|
||||||
.py__getattribute__('__iter__').execute_with_values()
|
.py__getattribute__('__iter__').execute_with_values()
|
||||||
return generators.py__stop_iteration_returns()
|
return generators.py__stop_iteration_returns()
|
||||||
|
|
||||||
# Generator.send() is not implemented.
|
# Generator.send() is not implemented.
|
||||||
return NO_CONTEXTS
|
return NO_CONTEXTS
|
||||||
elif typ == 'namedexpr_test':
|
elif typ == 'namedexpr_test':
|
||||||
return infer_node(context, element.children[2])
|
return infer_node(value, element.children[2])
|
||||||
else:
|
else:
|
||||||
return infer_or_test(context, element)
|
return infer_or_test(value, element)
|
||||||
|
|
||||||
|
|
||||||
def infer_trailer(context, atom_contexts, trailer):
|
def infer_trailer(value, atom_values, trailer):
|
||||||
trailer_op, node = trailer.children[:2]
|
trailer_op, node = trailer.children[:2]
|
||||||
if node == ')': # `arglist` is optional.
|
if node == ')': # `arglist` is optional.
|
||||||
node = None
|
node = None
|
||||||
|
|
||||||
if trailer_op == '[':
|
if trailer_op == '[':
|
||||||
trailer_op, node, _ = trailer.children
|
trailer_op, node, _ = trailer.children
|
||||||
return atom_contexts.get_item(
|
return atom_values.get_item(
|
||||||
infer_subscript_list(context.infer_state, context, node),
|
infer_subscript_list(value.infer_state, value, node),
|
||||||
ContextualizedNode(context, trailer)
|
ContextualizedNode(value, trailer)
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
debug.dbg('infer_trailer: %s in %s', trailer, atom_contexts)
|
debug.dbg('infer_trailer: %s in %s', trailer, atom_values)
|
||||||
if trailer_op == '.':
|
if trailer_op == '.':
|
||||||
return atom_contexts.py__getattribute__(
|
return atom_values.py__getattribute__(
|
||||||
name_context=context,
|
name_value=value,
|
||||||
name_or_str=node
|
name_or_str=node
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
assert trailer_op == '(', 'trailer_op is actually %s' % trailer_op
|
assert trailer_op == '(', 'trailer_op is actually %s' % trailer_op
|
||||||
args = arguments.TreeArguments(context.infer_state, context, node, trailer)
|
args = arguments.TreeArguments(value.infer_state, value, node, trailer)
|
||||||
return atom_contexts.execute(args)
|
return atom_values.execute(args)
|
||||||
|
|
||||||
|
|
||||||
def infer_atom(context, atom):
|
def infer_atom(value, atom):
|
||||||
"""
|
"""
|
||||||
Basically to process ``atom`` nodes. The parser sometimes doesn't
|
Basically to process ``atom`` nodes. The parser sometimes doesn't
|
||||||
generate the node (because it has just one child). In that case an atom
|
generate the node (because it has just one child). In that case an atom
|
||||||
@@ -183,7 +183,7 @@ def infer_atom(context, atom):
|
|||||||
if atom.type == 'name':
|
if atom.type == 'name':
|
||||||
if atom.value in ('True', 'False', 'None'):
|
if atom.value in ('True', 'False', 'None'):
|
||||||
# Python 2...
|
# Python 2...
|
||||||
return ContextSet([compiled.builtin_from_name(context.infer_state, atom.value)])
|
return ContextSet([compiled.builtin_from_name(value.infer_state, atom.value)])
|
||||||
|
|
||||||
# This is the first global lookup.
|
# This is the first global lookup.
|
||||||
stmt = tree.search_ancestor(
|
stmt = tree.search_ancestor(
|
||||||
@@ -199,7 +199,7 @@ def infer_atom(context, atom):
|
|||||||
# position to None, so the finder will not try to stop at a certain
|
# position to None, so the finder will not try to stop at a certain
|
||||||
# position in the module.
|
# position in the module.
|
||||||
position = None
|
position = None
|
||||||
return context.py__getattribute__(
|
return value.py__getattribute__(
|
||||||
name_or_str=atom,
|
name_or_str=atom,
|
||||||
position=position,
|
position=position,
|
||||||
search_global=True
|
search_global=True
|
||||||
@@ -207,7 +207,7 @@ def infer_atom(context, atom):
|
|||||||
elif atom.type == 'keyword':
|
elif atom.type == 'keyword':
|
||||||
# For False/True/None
|
# For False/True/None
|
||||||
if atom.value in ('False', 'True', 'None'):
|
if atom.value in ('False', 'True', 'None'):
|
||||||
return ContextSet([compiled.builtin_from_name(context.infer_state, atom.value)])
|
return ContextSet([compiled.builtin_from_name(value.infer_state, atom.value)])
|
||||||
elif atom.value == 'print':
|
elif atom.value == 'print':
|
||||||
# print e.g. could be inferred like this in Python 2.7
|
# print e.g. could be inferred like this in Python 2.7
|
||||||
return NO_CONTEXTS
|
return NO_CONTEXTS
|
||||||
@@ -218,24 +218,24 @@ def infer_atom(context, atom):
|
|||||||
assert False, 'Cannot infer the keyword %s' % atom
|
assert False, 'Cannot infer the keyword %s' % atom
|
||||||
|
|
||||||
elif isinstance(atom, tree.Literal):
|
elif isinstance(atom, tree.Literal):
|
||||||
string = context.infer_state.compiled_subprocess.safe_literal_eval(atom.value)
|
string = value.infer_state.compiled_subprocess.safe_literal_eval(atom.value)
|
||||||
return ContextSet([compiled.create_simple_object(context.infer_state, string)])
|
return ContextSet([compiled.create_simple_object(value.infer_state, string)])
|
||||||
elif atom.type == 'strings':
|
elif atom.type == 'strings':
|
||||||
# Will be multiple string.
|
# Will be multiple string.
|
||||||
context_set = infer_atom(context, atom.children[0])
|
value_set = infer_atom(value, atom.children[0])
|
||||||
for string in atom.children[1:]:
|
for string in atom.children[1:]:
|
||||||
right = infer_atom(context, string)
|
right = infer_atom(value, string)
|
||||||
context_set = _infer_comparison(context.infer_state, context, context_set, u'+', right)
|
value_set = _infer_comparison(value.infer_state, value, value_set, u'+', right)
|
||||||
return context_set
|
return value_set
|
||||||
elif atom.type == 'fstring':
|
elif atom.type == 'fstring':
|
||||||
return compiled.get_string_context_set(context.infer_state)
|
return compiled.get_string_value_set(value.infer_state)
|
||||||
else:
|
else:
|
||||||
c = atom.children
|
c = atom.children
|
||||||
# Parentheses without commas are not tuples.
|
# Parentheses without commas are not tuples.
|
||||||
if c[0] == '(' and not len(c) == 2 \
|
if c[0] == '(' and not len(c) == 2 \
|
||||||
and not(c[1].type == 'testlist_comp' and
|
and not(c[1].type == 'testlist_comp' and
|
||||||
len(c[1].children) > 1):
|
len(c[1].children) > 1):
|
||||||
return context.infer_node(c[1])
|
return value.infer_node(c[1])
|
||||||
|
|
||||||
try:
|
try:
|
||||||
comp_for = c[1].children[1]
|
comp_for = c[1].children[1]
|
||||||
@@ -251,7 +251,7 @@ def infer_atom(context, atom):
|
|||||||
|
|
||||||
if comp_for.type in ('comp_for', 'sync_comp_for'):
|
if comp_for.type in ('comp_for', 'sync_comp_for'):
|
||||||
return ContextSet([iterable.comprehension_from_atom(
|
return ContextSet([iterable.comprehension_from_atom(
|
||||||
context.infer_state, context, atom
|
value.infer_state, value, atom
|
||||||
)])
|
)])
|
||||||
|
|
||||||
# It's a dict/list/tuple literal.
|
# It's a dict/list/tuple literal.
|
||||||
@@ -262,36 +262,36 @@ def infer_atom(context, atom):
|
|||||||
array_node_c = []
|
array_node_c = []
|
||||||
if c[0] == '{' and (array_node == '}' or ':' in array_node_c or
|
if c[0] == '{' and (array_node == '}' or ':' in array_node_c or
|
||||||
'**' in array_node_c):
|
'**' in array_node_c):
|
||||||
context = iterable.DictLiteralContext(context.infer_state, context, atom)
|
new_value = iterable.DictLiteralContext(value.infer_state, value, atom)
|
||||||
else:
|
else:
|
||||||
context = iterable.SequenceLiteralContext(context.infer_state, context, atom)
|
new_value = iterable.SequenceLiteralContext(value.infer_state, value, atom)
|
||||||
return ContextSet([context])
|
return ContextSet([new_value])
|
||||||
|
|
||||||
|
|
||||||
@_limit_context_infers
|
@_limit_value_infers
|
||||||
def infer_expr_stmt(context, stmt, seek_name=None):
|
def infer_expr_stmt(value, stmt, seek_name=None):
|
||||||
with recursion.execution_allowed(context.infer_state, stmt) as allowed:
|
with recursion.execution_allowed(value.infer_state, stmt) as allowed:
|
||||||
# Here we allow list/set to recurse under certain conditions. To make
|
# Here we allow list/set to recurse under certain conditions. To make
|
||||||
# it possible to resolve stuff like list(set(list(x))), this is
|
# it possible to resolve stuff like list(set(list(x))), this is
|
||||||
# necessary.
|
# necessary.
|
||||||
if not allowed and context.get_root_context() == context.infer_state.builtins_module:
|
if not allowed and value.get_root_value() == value.infer_state.builtins_module:
|
||||||
try:
|
try:
|
||||||
instance = context.var_args.instance
|
instance = value.var_args.instance
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
if instance.name.string_name in ('list', 'set'):
|
if instance.name.string_name in ('list', 'set'):
|
||||||
c = instance.get_first_non_keyword_argument_contexts()
|
c = instance.get_first_non_keyword_argument_values()
|
||||||
if instance not in c:
|
if instance not in c:
|
||||||
allowed = True
|
allowed = True
|
||||||
|
|
||||||
if allowed:
|
if allowed:
|
||||||
return _infer_expr_stmt(context, stmt, seek_name)
|
return _infer_expr_stmt(value, stmt, seek_name)
|
||||||
return NO_CONTEXTS
|
return NO_CONTEXTS
|
||||||
|
|
||||||
|
|
||||||
@debug.increase_indent
|
@debug.increase_indent
|
||||||
def _infer_expr_stmt(context, stmt, seek_name=None):
|
def _infer_expr_stmt(value, stmt, seek_name=None):
|
||||||
"""
|
"""
|
||||||
The starting point of the completion. A statement always owns a call
|
The starting point of the completion. A statement always owns a call
|
||||||
list, which are the calls, that a statement does. In case multiple
|
list, which are the calls, that a statement does. In case multiple
|
||||||
@@ -302,11 +302,11 @@ def _infer_expr_stmt(context, stmt, seek_name=None):
|
|||||||
"""
|
"""
|
||||||
debug.dbg('infer_expr_stmt %s (%s)', stmt, seek_name)
|
debug.dbg('infer_expr_stmt %s (%s)', stmt, seek_name)
|
||||||
rhs = stmt.get_rhs()
|
rhs = stmt.get_rhs()
|
||||||
context_set = context.infer_node(rhs)
|
value_set = value.infer_node(rhs)
|
||||||
|
|
||||||
if seek_name:
|
if seek_name:
|
||||||
c_node = ContextualizedName(context, seek_name)
|
c_node = ContextualizedName(value, seek_name)
|
||||||
context_set = check_tuple_assignments(context.infer_state, c_node, context_set)
|
value_set = check_tuple_assignments(value.infer_state, c_node, value_set)
|
||||||
|
|
||||||
first_operator = next(stmt.yield_operators(), None)
|
first_operator = next(stmt.yield_operators(), None)
|
||||||
if first_operator not in ('=', None) and first_operator.type == 'operator':
|
if first_operator not in ('=', None) and first_operator.type == 'operator':
|
||||||
@@ -314,34 +314,34 @@ def _infer_expr_stmt(context, stmt, seek_name=None):
|
|||||||
operator = copy.copy(first_operator)
|
operator = copy.copy(first_operator)
|
||||||
operator.value = operator.value[:-1]
|
operator.value = operator.value[:-1]
|
||||||
name = stmt.get_defined_names()[0].value
|
name = stmt.get_defined_names()[0].value
|
||||||
left = context.py__getattribute__(
|
left = value.py__getattribute__(
|
||||||
name, position=stmt.start_pos, search_global=True)
|
name, position=stmt.start_pos, search_global=True)
|
||||||
|
|
||||||
for_stmt = tree.search_ancestor(stmt, 'for_stmt')
|
for_stmt = tree.search_ancestor(stmt, 'for_stmt')
|
||||||
if for_stmt is not None and for_stmt.type == 'for_stmt' and context_set \
|
if for_stmt is not None and for_stmt.type == 'for_stmt' and value_set \
|
||||||
and parser_utils.for_stmt_defines_one_name(for_stmt):
|
and parser_utils.for_stmt_defines_one_name(for_stmt):
|
||||||
# Iterate through result and add the values, that's possible
|
# Iterate through result and add the values, that's possible
|
||||||
# only in for loops without clutter, because they are
|
# only in for loops without clutter, because they are
|
||||||
# predictable. Also only do it, if the variable is not a tuple.
|
# predictable. Also only do it, if the variable is not a tuple.
|
||||||
node = for_stmt.get_testlist()
|
node = for_stmt.get_testlist()
|
||||||
cn = ContextualizedNode(context, node)
|
cn = ContextualizedNode(value, node)
|
||||||
ordered = list(cn.infer().iterate(cn))
|
ordered = list(cn.infer().iterate(cn))
|
||||||
|
|
||||||
for lazy_context in ordered:
|
for lazy_value in ordered:
|
||||||
dct = {for_stmt.children[1].value: lazy_context.infer()}
|
dct = {for_stmt.children[1].value: lazy_value.infer()}
|
||||||
with helpers.predefine_names(context, for_stmt, dct):
|
with helpers.predefine_names(value, for_stmt, dct):
|
||||||
t = context.infer_node(rhs)
|
t = value.infer_node(rhs)
|
||||||
left = _infer_comparison(context.infer_state, context, left, operator, t)
|
left = _infer_comparison(value.infer_state, value, left, operator, t)
|
||||||
context_set = left
|
value_set = left
|
||||||
else:
|
else:
|
||||||
context_set = _infer_comparison(context.infer_state, context, left, operator, context_set)
|
value_set = _infer_comparison(value.infer_state, value, left, operator, value_set)
|
||||||
debug.dbg('infer_expr_stmt result %s', context_set)
|
debug.dbg('infer_expr_stmt result %s', value_set)
|
||||||
return context_set
|
return value_set
|
||||||
|
|
||||||
|
|
||||||
def infer_or_test(context, or_test):
|
def infer_or_test(value, or_test):
|
||||||
iterator = iter(or_test.children)
|
iterator = iter(or_test.children)
|
||||||
types = context.infer_node(next(iterator))
|
types = value.infer_node(next(iterator))
|
||||||
for operator in iterator:
|
for operator in iterator:
|
||||||
right = next(iterator)
|
right = next(iterator)
|
||||||
if operator.type == 'comp_op': # not in / is not
|
if operator.type == 'comp_op': # not in / is not
|
||||||
@@ -352,34 +352,34 @@ def infer_or_test(context, or_test):
|
|||||||
left_bools = set(left.py__bool__() for left in types)
|
left_bools = set(left.py__bool__() for left in types)
|
||||||
if left_bools == {True}:
|
if left_bools == {True}:
|
||||||
if operator == 'and':
|
if operator == 'and':
|
||||||
types = context.infer_node(right)
|
types = value.infer_node(right)
|
||||||
elif left_bools == {False}:
|
elif left_bools == {False}:
|
||||||
if operator != 'and':
|
if operator != 'and':
|
||||||
types = context.infer_node(right)
|
types = value.infer_node(right)
|
||||||
# Otherwise continue, because of uncertainty.
|
# Otherwise continue, because of uncertainty.
|
||||||
else:
|
else:
|
||||||
types = _infer_comparison(context.infer_state, context, types, operator,
|
types = _infer_comparison(value.infer_state, value, types, operator,
|
||||||
context.infer_node(right))
|
value.infer_node(right))
|
||||||
debug.dbg('infer_or_test types %s', types)
|
debug.dbg('infer_or_test types %s', types)
|
||||||
return types
|
return types
|
||||||
|
|
||||||
|
|
||||||
@iterator_to_context_set
|
@iterator_to_value_set
|
||||||
def infer_factor(context_set, operator):
|
def infer_factor(value_set, operator):
|
||||||
"""
|
"""
|
||||||
Calculates `+`, `-`, `~` and `not` prefixes.
|
Calculates `+`, `-`, `~` and `not` prefixes.
|
||||||
"""
|
"""
|
||||||
for context in context_set:
|
for value in value_set:
|
||||||
if operator == '-':
|
if operator == '-':
|
||||||
if is_number(context):
|
if is_number(value):
|
||||||
yield context.negate()
|
yield value.negate()
|
||||||
elif operator == 'not':
|
elif operator == 'not':
|
||||||
value = context.py__bool__()
|
b = value.py__bool__()
|
||||||
if value is None: # Uncertainty.
|
if b is None: # Uncertainty.
|
||||||
return
|
return
|
||||||
yield compiled.create_simple_object(context.infer_state, not value)
|
yield compiled.create_simple_object(value.infer_state, not b)
|
||||||
else:
|
else:
|
||||||
yield context
|
yield value
|
||||||
|
|
||||||
|
|
||||||
def _literals_to_types(infer_state, result):
|
def _literals_to_types(infer_state, result):
|
||||||
@@ -397,22 +397,22 @@ def _literals_to_types(infer_state, result):
|
|||||||
return new_result
|
return new_result
|
||||||
|
|
||||||
|
|
||||||
def _infer_comparison(infer_state, context, left_contexts, operator, right_contexts):
|
def _infer_comparison(infer_state, value, left_values, operator, right_values):
|
||||||
if not left_contexts or not right_contexts:
|
if not left_values or not right_values:
|
||||||
# illegal slices e.g. cause left/right_result to be None
|
# illegal slices e.g. cause left/right_result to be None
|
||||||
result = (left_contexts or NO_CONTEXTS) | (right_contexts or NO_CONTEXTS)
|
result = (left_values or NO_CONTEXTS) | (right_values or NO_CONTEXTS)
|
||||||
return _literals_to_types(infer_state, result)
|
return _literals_to_types(infer_state, result)
|
||||||
else:
|
else:
|
||||||
# I don't think there's a reasonable chance that a string
|
# I don't think there's a reasonable chance that a string
|
||||||
# operation is still correct, once we pass something like six
|
# operation is still correct, once we pass something like six
|
||||||
# objects.
|
# objects.
|
||||||
if len(left_contexts) * len(right_contexts) > 6:
|
if len(left_values) * len(right_values) > 6:
|
||||||
return _literals_to_types(infer_state, left_contexts | right_contexts)
|
return _literals_to_types(infer_state, left_values | right_values)
|
||||||
else:
|
else:
|
||||||
return ContextSet.from_sets(
|
return ContextSet.from_sets(
|
||||||
_infer_comparison_part(infer_state, context, left, operator, right)
|
_infer_comparison_part(infer_state, value, left, operator, right)
|
||||||
for left in left_contexts
|
for left in left_values
|
||||||
for right in right_contexts
|
for right in right_values
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -432,26 +432,26 @@ def _is_annotation_name(name):
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def _is_tuple(context):
|
def _is_tuple(value):
|
||||||
return isinstance(context, iterable.Sequence) and context.array_type == 'tuple'
|
return isinstance(value, iterable.Sequence) and value.array_type == 'tuple'
|
||||||
|
|
||||||
|
|
||||||
def _is_list(context):
|
def _is_list(value):
|
||||||
return isinstance(context, iterable.Sequence) and context.array_type == 'list'
|
return isinstance(value, iterable.Sequence) and value.array_type == 'list'
|
||||||
|
|
||||||
|
|
||||||
def _bool_to_context(infer_state, bool_):
|
def _bool_to_value(infer_state, bool_):
|
||||||
return compiled.builtin_from_name(infer_state, force_unicode(str(bool_)))
|
return compiled.builtin_from_name(infer_state, force_unicode(str(bool_)))
|
||||||
|
|
||||||
|
|
||||||
def _get_tuple_ints(context):
|
def _get_tuple_ints(value):
|
||||||
if not isinstance(context, iterable.SequenceLiteralContext):
|
if not isinstance(value, iterable.SequenceLiteralContext):
|
||||||
return None
|
return None
|
||||||
numbers = []
|
numbers = []
|
||||||
for lazy_context in context.py__iter__():
|
for lazy_value in value.py__iter__():
|
||||||
if not isinstance(lazy_context, LazyTreeContext):
|
if not isinstance(lazy_value, LazyTreeContext):
|
||||||
return None
|
return None
|
||||||
node = lazy_context.data
|
node = lazy_value.data
|
||||||
if node.type != 'number':
|
if node.type != 'number':
|
||||||
return None
|
return None
|
||||||
try:
|
try:
|
||||||
@@ -461,7 +461,7 @@ def _get_tuple_ints(context):
|
|||||||
return numbers
|
return numbers
|
||||||
|
|
||||||
|
|
||||||
def _infer_comparison_part(infer_state, context, left, operator, right):
|
def _infer_comparison_part(infer_state, value, left, operator, right):
|
||||||
l_is_num = is_number(left)
|
l_is_num = is_number(left)
|
||||||
r_is_num = is_number(right)
|
r_is_num = is_number(right)
|
||||||
if isinstance(operator, unicode):
|
if isinstance(operator, unicode):
|
||||||
@@ -499,7 +499,7 @@ def _infer_comparison_part(infer_state, context, left, operator, right):
|
|||||||
if str_operator in ('is', '!=', '==', 'is not'):
|
if str_operator in ('is', '!=', '==', 'is not'):
|
||||||
operation = COMPARISON_OPERATORS[str_operator]
|
operation = COMPARISON_OPERATORS[str_operator]
|
||||||
bool_ = operation(left, right)
|
bool_ = operation(left, right)
|
||||||
return ContextSet([_bool_to_context(infer_state, bool_)])
|
return ContextSet([_bool_to_value(infer_state, bool_)])
|
||||||
|
|
||||||
if isinstance(left, VersionInfo):
|
if isinstance(left, VersionInfo):
|
||||||
version_info = _get_tuple_ints(right)
|
version_info = _get_tuple_ints(right)
|
||||||
@@ -508,9 +508,9 @@ def _infer_comparison_part(infer_state, context, left, operator, right):
|
|||||||
infer_state.environment.version_info,
|
infer_state.environment.version_info,
|
||||||
tuple(version_info)
|
tuple(version_info)
|
||||||
)
|
)
|
||||||
return ContextSet([_bool_to_context(infer_state, bool_result)])
|
return ContextSet([_bool_to_value(infer_state, bool_result)])
|
||||||
|
|
||||||
return ContextSet([_bool_to_context(infer_state, True), _bool_to_context(infer_state, False)])
|
return ContextSet([_bool_to_value(infer_state, True), _bool_to_value(infer_state, False)])
|
||||||
elif str_operator == 'in':
|
elif str_operator == 'in':
|
||||||
return NO_CONTEXTS
|
return NO_CONTEXTS
|
||||||
|
|
||||||
@@ -523,7 +523,7 @@ def _infer_comparison_part(infer_state, context, left, operator, right):
|
|||||||
if str_operator in ('+', '-') and l_is_num != r_is_num \
|
if str_operator in ('+', '-') and l_is_num != r_is_num \
|
||||||
and not (check(left) or check(right)):
|
and not (check(left) or check(right)):
|
||||||
message = "TypeError: unsupported operand type(s) for +: %s and %s"
|
message = "TypeError: unsupported operand type(s) for +: %s and %s"
|
||||||
analysis.add(context, 'type-error-operation', operator,
|
analysis.add(value, 'type-error-operation', operator,
|
||||||
message % (left, right))
|
message % (left, right))
|
||||||
|
|
||||||
result = ContextSet([left, right])
|
result = ContextSet([left, right])
|
||||||
@@ -531,25 +531,25 @@ def _infer_comparison_part(infer_state, context, left, operator, right):
|
|||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
def _remove_statements(infer_state, context, stmt, name):
|
def _remove_statements(infer_state, value, stmt, name):
|
||||||
"""
|
"""
|
||||||
This is the part where statements are being stripped.
|
This is the part where statements are being stripped.
|
||||||
|
|
||||||
Due to lazy type inference, statements like a = func; b = a; b() have to be
|
Due to lazy type inference, statements like a = func; b = a; b() have to be
|
||||||
inferred.
|
inferred.
|
||||||
"""
|
"""
|
||||||
pep0484_contexts = \
|
pep0484_values = \
|
||||||
annotation.find_type_from_comment_hint_assign(context, stmt, name)
|
annotation.find_type_from_comment_hint_assign(value, stmt, name)
|
||||||
if pep0484_contexts:
|
if pep0484_values:
|
||||||
return pep0484_contexts
|
return pep0484_values
|
||||||
|
|
||||||
return infer_expr_stmt(context, stmt, seek_name=name)
|
return infer_expr_stmt(value, stmt, seek_name=name)
|
||||||
|
|
||||||
|
|
||||||
@plugin_manager.decorate()
|
@plugin_manager.decorate()
|
||||||
def tree_name_to_contexts(infer_state, context, tree_name):
|
def tree_name_to_values(infer_state, value, tree_name):
|
||||||
context_set = NO_CONTEXTS
|
value_set = NO_CONTEXTS
|
||||||
module_node = context.get_root_context().tree_node
|
module_node = value.get_root_value().tree_node
|
||||||
# First check for annotations, like: `foo: int = 3`
|
# First check for annotations, like: `foo: int = 3`
|
||||||
if module_node is not None:
|
if module_node is not None:
|
||||||
names = module_node.get_used_names().get(tree_name.value, [])
|
names = module_node.get_used_names().get(tree_name.value, [])
|
||||||
@@ -557,67 +557,67 @@ def tree_name_to_contexts(infer_state, context, tree_name):
|
|||||||
expr_stmt = name.parent
|
expr_stmt = name.parent
|
||||||
|
|
||||||
if expr_stmt.type == "expr_stmt" and expr_stmt.children[1].type == "annassign":
|
if expr_stmt.type == "expr_stmt" and expr_stmt.children[1].type == "annassign":
|
||||||
correct_scope = parser_utils.get_parent_scope(name) == context.tree_node
|
correct_scope = parser_utils.get_parent_scope(name) == value.tree_node
|
||||||
if correct_scope:
|
if correct_scope:
|
||||||
context_set |= annotation.infer_annotation(
|
value_set |= annotation.infer_annotation(
|
||||||
context, expr_stmt.children[1].children[1]
|
value, expr_stmt.children[1].children[1]
|
||||||
).execute_annotation()
|
).execute_annotation()
|
||||||
if context_set:
|
if value_set:
|
||||||
return context_set
|
return value_set
|
||||||
|
|
||||||
types = []
|
types = []
|
||||||
node = tree_name.get_definition(import_name_always=True)
|
node = tree_name.get_definition(import_name_always=True)
|
||||||
if node is None:
|
if node is None:
|
||||||
node = tree_name.parent
|
node = tree_name.parent
|
||||||
if node.type == 'global_stmt':
|
if node.type == 'global_stmt':
|
||||||
context = infer_state.create_context(context, tree_name)
|
value = infer_state.create_value(value, tree_name)
|
||||||
finder = NameFinder(infer_state, context, context, tree_name.value)
|
finder = NameFinder(infer_state, value, value, tree_name.value)
|
||||||
filters = finder.get_filters(search_global=True)
|
filters = finder.get_filters(search_global=True)
|
||||||
# For global_stmt lookups, we only need the first possible scope,
|
# For global_stmt lookups, we only need the first possible scope,
|
||||||
# which means the function itself.
|
# which means the function itself.
|
||||||
filters = [next(filters)]
|
filters = [next(filters)]
|
||||||
return finder.find(filters, attribute_lookup=False)
|
return finder.find(filters, attribute_lookup=False)
|
||||||
elif node.type not in ('import_from', 'import_name'):
|
elif node.type not in ('import_from', 'import_name'):
|
||||||
context = infer_state.create_context(context, tree_name)
|
value = infer_state.create_value(value, tree_name)
|
||||||
return infer_atom(context, tree_name)
|
return infer_atom(value, tree_name)
|
||||||
|
|
||||||
typ = node.type
|
typ = node.type
|
||||||
if typ == 'for_stmt':
|
if typ == 'for_stmt':
|
||||||
types = annotation.find_type_from_comment_hint_for(context, node, tree_name)
|
types = annotation.find_type_from_comment_hint_for(value, node, tree_name)
|
||||||
if types:
|
if types:
|
||||||
return types
|
return types
|
||||||
if typ == 'with_stmt':
|
if typ == 'with_stmt':
|
||||||
types = annotation.find_type_from_comment_hint_with(context, node, tree_name)
|
types = annotation.find_type_from_comment_hint_with(value, node, tree_name)
|
||||||
if types:
|
if types:
|
||||||
return types
|
return types
|
||||||
|
|
||||||
if typ in ('for_stmt', 'comp_for', 'sync_comp_for'):
|
if typ in ('for_stmt', 'comp_for', 'sync_comp_for'):
|
||||||
try:
|
try:
|
||||||
types = context.predefined_names[node][tree_name.value]
|
types = value.predefined_names[node][tree_name.value]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
cn = ContextualizedNode(context, node.children[3])
|
cn = ContextualizedNode(value, node.children[3])
|
||||||
for_types = iterate_contexts(
|
for_types = iterate_values(
|
||||||
cn.infer(),
|
cn.infer(),
|
||||||
contextualized_node=cn,
|
valueualized_node=cn,
|
||||||
is_async=node.parent.type == 'async_stmt',
|
is_async=node.parent.type == 'async_stmt',
|
||||||
)
|
)
|
||||||
c_node = ContextualizedName(context, tree_name)
|
c_node = ContextualizedName(value, tree_name)
|
||||||
types = check_tuple_assignments(infer_state, c_node, for_types)
|
types = check_tuple_assignments(infer_state, c_node, for_types)
|
||||||
elif typ == 'expr_stmt':
|
elif typ == 'expr_stmt':
|
||||||
types = _remove_statements(infer_state, context, node, tree_name)
|
types = _remove_statements(infer_state, value, node, tree_name)
|
||||||
elif typ == 'with_stmt':
|
elif typ == 'with_stmt':
|
||||||
context_managers = context.infer_node(node.get_test_node_from_name(tree_name))
|
value_managers = value.infer_node(node.get_test_node_from_name(tree_name))
|
||||||
enter_methods = context_managers.py__getattribute__(u'__enter__')
|
enter_methods = value_managers.py__getattribute__(u'__enter__')
|
||||||
return enter_methods.execute_with_values()
|
return enter_methods.execute_with_values()
|
||||||
elif typ in ('import_from', 'import_name'):
|
elif typ in ('import_from', 'import_name'):
|
||||||
types = imports.infer_import(context, tree_name)
|
types = imports.infer_import(value, tree_name)
|
||||||
elif typ in ('funcdef', 'classdef'):
|
elif typ in ('funcdef', 'classdef'):
|
||||||
types = _apply_decorators(context, node)
|
types = _apply_decorators(value, node)
|
||||||
elif typ == 'try_stmt':
|
elif typ == 'try_stmt':
|
||||||
# TODO an exception can also be a tuple. Check for those.
|
# TODO an exception can also be a tuple. Check for those.
|
||||||
# TODO check for types that are not classes and add it to
|
# TODO check for types that are not classes and add it to
|
||||||
# the static analysis report.
|
# the static analysis report.
|
||||||
exceptions = context.infer_node(tree_name.get_previous_sibling().get_previous_sibling())
|
exceptions = value.infer_node(tree_name.get_previous_sibling().get_previous_sibling())
|
||||||
types = exceptions.execute_with_values()
|
types = exceptions.execute_with_values()
|
||||||
elif node.type == 'param':
|
elif node.type == 'param':
|
||||||
types = NO_CONTEXTS
|
types = NO_CONTEXTS
|
||||||
@@ -629,30 +629,30 @@ def tree_name_to_contexts(infer_state, context, tree_name):
|
|||||||
# We don't want to have functions/classes that are created by the same
|
# We don't want to have functions/classes that are created by the same
|
||||||
# tree_node.
|
# tree_node.
|
||||||
@infer_state_method_cache()
|
@infer_state_method_cache()
|
||||||
def _apply_decorators(context, node):
|
def _apply_decorators(value, node):
|
||||||
"""
|
"""
|
||||||
Returns the function, that should to be executed in the end.
|
Returns the function, that should to be executed in the end.
|
||||||
This is also the places where the decorators are processed.
|
This is also the places where the decorators are processed.
|
||||||
"""
|
"""
|
||||||
if node.type == 'classdef':
|
if node.type == 'classdef':
|
||||||
decoratee_context = ClassContext(
|
decoratee_value = ClassContext(
|
||||||
context.infer_state,
|
value.infer_state,
|
||||||
parent_context=context,
|
parent_value=value,
|
||||||
tree_node=node
|
tree_node=node
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
decoratee_context = FunctionContext.from_context(context, node)
|
decoratee_value = FunctionContext.from_value(value, node)
|
||||||
initial = values = ContextSet([decoratee_context])
|
initial = values = ContextSet([decoratee_value])
|
||||||
for dec in reversed(node.get_decorators()):
|
for dec in reversed(node.get_decorators()):
|
||||||
debug.dbg('decorator: %s %s', dec, values, color="MAGENTA")
|
debug.dbg('decorator: %s %s', dec, values, color="MAGENTA")
|
||||||
with debug.increase_indent_cm():
|
with debug.increase_indent_cm():
|
||||||
dec_values = context.infer_node(dec.children[1])
|
dec_values = value.infer_node(dec.children[1])
|
||||||
trailer_nodes = dec.children[2:-1]
|
trailer_nodes = dec.children[2:-1]
|
||||||
if trailer_nodes:
|
if trailer_nodes:
|
||||||
# Create a trailer and infer it.
|
# Create a trailer and infer it.
|
||||||
trailer = tree.PythonNode('trailer', trailer_nodes)
|
trailer = tree.PythonNode('trailer', trailer_nodes)
|
||||||
trailer.parent = dec
|
trailer.parent = dec
|
||||||
dec_values = infer_trailer(context, dec_values, trailer)
|
dec_values = infer_trailer(value, dec_values, trailer)
|
||||||
|
|
||||||
if not len(dec_values):
|
if not len(dec_values):
|
||||||
code = dec.get_code(include_prefix=False)
|
code = dec.get_code(include_prefix=False)
|
||||||
@@ -670,41 +670,41 @@ def _apply_decorators(context, node):
|
|||||||
|
|
||||||
debug.dbg('decorator end %s', values, color="MAGENTA")
|
debug.dbg('decorator end %s', values, color="MAGENTA")
|
||||||
if values != initial:
|
if values != initial:
|
||||||
return ContextSet([Decoratee(c, decoratee_context) for c in values])
|
return ContextSet([Decoratee(c, decoratee_value) for c in values])
|
||||||
return values
|
return values
|
||||||
|
|
||||||
|
|
||||||
def check_tuple_assignments(infer_state, contextualized_name, context_set):
|
def check_tuple_assignments(infer_state, valueualized_name, value_set):
|
||||||
"""
|
"""
|
||||||
Checks if tuples are assigned.
|
Checks if tuples are assigned.
|
||||||
"""
|
"""
|
||||||
lazy_context = None
|
lazy_value = None
|
||||||
for index, node in contextualized_name.assignment_indexes():
|
for index, node in valueualized_name.assignment_indexes():
|
||||||
cn = ContextualizedNode(contextualized_name.context, node)
|
cn = ContextualizedNode(valueualized_name.value, node)
|
||||||
iterated = context_set.iterate(cn)
|
iterated = value_set.iterate(cn)
|
||||||
if isinstance(index, slice):
|
if isinstance(index, slice):
|
||||||
# For no star unpacking is not possible.
|
# For no star unpacking is not possible.
|
||||||
return NO_CONTEXTS
|
return NO_CONTEXTS
|
||||||
for _ in range(index + 1):
|
for _ in range(index + 1):
|
||||||
try:
|
try:
|
||||||
lazy_context = next(iterated)
|
lazy_value = next(iterated)
|
||||||
except StopIteration:
|
except StopIteration:
|
||||||
# We could do this with the default param in next. But this
|
# We could do this with the default param in next. But this
|
||||||
# would allow this loop to run for a very long time if the
|
# would allow this loop to run for a very long time if the
|
||||||
# index number is high. Therefore break if the loop is
|
# index number is high. Therefore break if the loop is
|
||||||
# finished.
|
# finished.
|
||||||
return NO_CONTEXTS
|
return NO_CONTEXTS
|
||||||
context_set = lazy_context.infer()
|
value_set = lazy_value.infer()
|
||||||
return context_set
|
return value_set
|
||||||
|
|
||||||
|
|
||||||
def infer_subscript_list(infer_state, context, index):
|
def infer_subscript_list(infer_state, value, index):
|
||||||
"""
|
"""
|
||||||
Handles slices in subscript nodes.
|
Handles slices in subscript nodes.
|
||||||
"""
|
"""
|
||||||
if index == ':':
|
if index == ':':
|
||||||
# Like array[:]
|
# Like array[:]
|
||||||
return ContextSet([iterable.Slice(context, None, None, None)])
|
return ContextSet([iterable.Slice(value, None, None, None)])
|
||||||
|
|
||||||
elif index.type == 'subscript' and not index.children[0] == '.':
|
elif index.type == 'subscript' and not index.children[0] == '.':
|
||||||
# subscript basically implies a slice operation, except for Python 2's
|
# subscript basically implies a slice operation, except for Python 2's
|
||||||
@@ -722,9 +722,9 @@ def infer_subscript_list(infer_state, context, index):
|
|||||||
result.append(el)
|
result.append(el)
|
||||||
result += [None] * (3 - len(result))
|
result += [None] * (3 - len(result))
|
||||||
|
|
||||||
return ContextSet([iterable.Slice(context, *result)])
|
return ContextSet([iterable.Slice(value, *result)])
|
||||||
elif index.type == 'subscriptlist':
|
elif index.type == 'subscriptlist':
|
||||||
return ContextSet([iterable.SequenceLiteralContext(infer_state, context, index)])
|
return ContextSet([iterable.SequenceLiteralContext(infer_state, value, index)])
|
||||||
|
|
||||||
# No slices
|
# No slices
|
||||||
return context.infer_node(index)
|
return value.infer_node(index)
|
||||||
|
|||||||
+18
-18
@@ -11,11 +11,11 @@ from jedi import settings
|
|||||||
from jedi import debug
|
from jedi import debug
|
||||||
|
|
||||||
|
|
||||||
def _abs_path(module_context, path):
|
def _abs_path(module_value, path):
|
||||||
if os.path.isabs(path):
|
if os.path.isabs(path):
|
||||||
return path
|
return path
|
||||||
|
|
||||||
module_path = module_context.py__file__()
|
module_path = module_value.py__file__()
|
||||||
if module_path is None:
|
if module_path is None:
|
||||||
# In this case we have no idea where we actually are in the file
|
# In this case we have no idea where we actually are in the file
|
||||||
# system.
|
# system.
|
||||||
@@ -26,7 +26,7 @@ def _abs_path(module_context, path):
|
|||||||
return os.path.abspath(os.path.join(base_dir, path))
|
return os.path.abspath(os.path.join(base_dir, path))
|
||||||
|
|
||||||
|
|
||||||
def _paths_from_assignment(module_context, expr_stmt):
|
def _paths_from_assignment(module_value, expr_stmt):
|
||||||
"""
|
"""
|
||||||
Extracts the assigned strings from an assignment that looks as follows::
|
Extracts the assigned strings from an assignment that looks as follows::
|
||||||
|
|
||||||
@@ -60,16 +60,16 @@ def _paths_from_assignment(module_context, expr_stmt):
|
|||||||
except AssertionError:
|
except AssertionError:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
cn = ContextualizedNode(module_context.create_context(expr_stmt), expr_stmt)
|
cn = ContextualizedNode(module_value.create_value(expr_stmt), expr_stmt)
|
||||||
for lazy_context in cn.infer().iterate(cn):
|
for lazy_value in cn.infer().iterate(cn):
|
||||||
for context in lazy_context.infer():
|
for value in lazy_value.infer():
|
||||||
if is_string(context):
|
if is_string(value):
|
||||||
abs_path = _abs_path(module_context, context.get_safe_value())
|
abs_path = _abs_path(module_value, value.get_safe_value())
|
||||||
if abs_path is not None:
|
if abs_path is not None:
|
||||||
yield abs_path
|
yield abs_path
|
||||||
|
|
||||||
|
|
||||||
def _paths_from_list_modifications(module_context, trailer1, trailer2):
|
def _paths_from_list_modifications(module_value, trailer1, trailer2):
|
||||||
""" extract the path from either "sys.path.append" or "sys.path.insert" """
|
""" extract the path from either "sys.path.append" or "sys.path.insert" """
|
||||||
# Guarantee that both are trailers, the first one a name and the second one
|
# Guarantee that both are trailers, the first one a name and the second one
|
||||||
# a function execution with at least one param.
|
# a function execution with at least one param.
|
||||||
@@ -85,15 +85,15 @@ def _paths_from_list_modifications(module_context, trailer1, trailer2):
|
|||||||
if name == 'insert' and len(arg.children) in (3, 4): # Possible trailing comma.
|
if name == 'insert' and len(arg.children) in (3, 4): # Possible trailing comma.
|
||||||
arg = arg.children[2]
|
arg = arg.children[2]
|
||||||
|
|
||||||
for context in module_context.create_context(arg).infer_node(arg):
|
for value in module_value.create_value(arg).infer_node(arg):
|
||||||
if is_string(context):
|
if is_string(value):
|
||||||
abs_path = _abs_path(module_context, context.get_safe_value())
|
abs_path = _abs_path(module_value, value.get_safe_value())
|
||||||
if abs_path is not None:
|
if abs_path is not None:
|
||||||
yield abs_path
|
yield abs_path
|
||||||
|
|
||||||
|
|
||||||
@infer_state_method_cache(default=[])
|
@infer_state_method_cache(default=[])
|
||||||
def check_sys_path_modifications(module_context):
|
def check_sys_path_modifications(module_value):
|
||||||
"""
|
"""
|
||||||
Detect sys.path modifications within module.
|
Detect sys.path modifications within module.
|
||||||
"""
|
"""
|
||||||
@@ -108,12 +108,12 @@ def check_sys_path_modifications(module_context):
|
|||||||
if n.type == 'name' and n.value == 'path':
|
if n.type == 'name' and n.value == 'path':
|
||||||
yield name, power
|
yield name, power
|
||||||
|
|
||||||
if module_context.tree_node is None:
|
if module_value.tree_node is None:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
added = []
|
added = []
|
||||||
try:
|
try:
|
||||||
possible_names = module_context.tree_node.get_used_names()['path']
|
possible_names = module_value.tree_node.get_used_names()['path']
|
||||||
except KeyError:
|
except KeyError:
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
@@ -122,11 +122,11 @@ def check_sys_path_modifications(module_context):
|
|||||||
if len(power.children) >= 4:
|
if len(power.children) >= 4:
|
||||||
added.extend(
|
added.extend(
|
||||||
_paths_from_list_modifications(
|
_paths_from_list_modifications(
|
||||||
module_context, *power.children[2:4]
|
module_value, *power.children[2:4]
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
elif expr_stmt is not None and expr_stmt.type == 'expr_stmt':
|
elif expr_stmt is not None and expr_stmt.type == 'expr_stmt':
|
||||||
added.extend(_paths_from_assignment(module_context, expr_stmt))
|
added.extend(_paths_from_assignment(module_value, expr_stmt))
|
||||||
return added
|
return added
|
||||||
|
|
||||||
|
|
||||||
@@ -152,7 +152,7 @@ def _get_paths_from_buildout_script(infer_state, buildout_script_path):
|
|||||||
debug.warning('Error trying to read buildout_script: %s', buildout_script_path)
|
debug.warning('Error trying to read buildout_script: %s', buildout_script_path)
|
||||||
return
|
return
|
||||||
|
|
||||||
from jedi.inference.context import ModuleContext
|
from jedi.inference.value import ModuleContext
|
||||||
module = ModuleContext(
|
module = ModuleContext(
|
||||||
infer_state, module_node, file_io,
|
infer_state, module_node, file_io,
|
||||||
string_names=None,
|
string_names=None,
|
||||||
|
|||||||
@@ -26,22 +26,22 @@ def _dictionarize(names):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def _find_names(module_context, tree_name):
|
def _find_names(module_value, tree_name):
|
||||||
context = module_context.create_context(tree_name)
|
value = module_value.create_value(tree_name)
|
||||||
name = TreeNameDefinition(context, tree_name)
|
name = TreeNameDefinition(value, tree_name)
|
||||||
found_names = set(name.goto())
|
found_names = set(name.goto())
|
||||||
found_names.add(name)
|
found_names.add(name)
|
||||||
return _dictionarize(_resolve_names(found_names))
|
return _dictionarize(_resolve_names(found_names))
|
||||||
|
|
||||||
|
|
||||||
def usages(module_context, tree_name):
|
def usages(module_value, tree_name):
|
||||||
search_name = tree_name.value
|
search_name = tree_name.value
|
||||||
found_names = _find_names(module_context, tree_name)
|
found_names = _find_names(module_value, tree_name)
|
||||||
modules = set(d.get_root_context() for d in found_names.values())
|
modules = set(d.get_root_value() for d in found_names.values())
|
||||||
modules = set(m for m in modules if m.is_module() and not m.is_compiled())
|
modules = set(m for m in modules if m.is_module() and not m.is_compiled())
|
||||||
|
|
||||||
non_matching_usage_maps = {}
|
non_matching_usage_maps = {}
|
||||||
for m in imports.get_modules_containing_name(module_context.infer_state, modules, search_name):
|
for m in imports.get_modules_containing_name(module_value.infer_state, modules, search_name):
|
||||||
for name_leaf in m.tree_node.get_used_names().get(search_name, []):
|
for name_leaf in m.tree_node.get_used_names().get(search_name, []):
|
||||||
new = _find_names(m, name_leaf)
|
new = _find_names(m, name_leaf)
|
||||||
if any(tree_name in found_names for tree_name in new):
|
if any(tree_name in found_names for tree_name in new):
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
from jedi.inference.value.module import ModuleContext
|
||||||
|
from jedi.inference.value.klass import ClassContext
|
||||||
|
from jedi.inference.value.function import FunctionContext, \
|
||||||
|
MethodContext, FunctionExecutionContext
|
||||||
|
from jedi.inference.value.instance import AnonymousInstance, BoundMethod, \
|
||||||
|
CompiledInstance, AbstractInstanceContext, TreeInstance
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
'''
|
||||||
|
Decorators are not really values, however we need some wrappers to improve
|
||||||
|
docstrings and other things around decorators.
|
||||||
|
'''
|
||||||
|
|
||||||
|
from jedi.inference.base_value import ContextWrapper
|
||||||
|
|
||||||
|
|
||||||
|
class Decoratee(ContextWrapper):
|
||||||
|
def __init__(self, wrapped_value, original_value):
|
||||||
|
self._wrapped_value = wrapped_value
|
||||||
|
self._original_value = original_value
|
||||||
|
|
||||||
|
def py__doc__(self):
|
||||||
|
return self._original_value.py__doc__()
|
||||||
@@ -14,39 +14,39 @@ from jedi.inference.filters import ParserTreeFilter, FunctionExecutionFilter
|
|||||||
from jedi.inference.names import ContextName, AbstractNameDefinition, ParamName
|
from jedi.inference.names import ContextName, AbstractNameDefinition, ParamName
|
||||||
from jedi.inference.base_value import ContextualizedNode, NO_CONTEXTS, \
|
from jedi.inference.base_value import ContextualizedNode, NO_CONTEXTS, \
|
||||||
ContextSet, TreeContext, ContextWrapper
|
ContextSet, TreeContext, ContextWrapper
|
||||||
from jedi.inference.lazy_context import LazyKnownContexts, LazyKnownContext, \
|
from jedi.inference.lazy_value import LazyKnownContexts, LazyKnownContext, \
|
||||||
LazyTreeContext
|
LazyTreeContext
|
||||||
from jedi.inference.context import iterable
|
from jedi.inference.value import iterable
|
||||||
from jedi import parser_utils
|
from jedi import parser_utils
|
||||||
from jedi.inference.parser_cache import get_yield_exprs
|
from jedi.inference.parser_cache import get_yield_exprs
|
||||||
from jedi.inference.helpers import contexts_from_qualified_names
|
from jedi.inference.helpers import values_from_qualified_names
|
||||||
|
|
||||||
|
|
||||||
class LambdaName(AbstractNameDefinition):
|
class LambdaName(AbstractNameDefinition):
|
||||||
string_name = '<lambda>'
|
string_name = '<lambda>'
|
||||||
api_type = u'function'
|
api_type = u'function'
|
||||||
|
|
||||||
def __init__(self, lambda_context):
|
def __init__(self, lambda_value):
|
||||||
self._lambda_context = lambda_context
|
self._lambda_value = lambda_value
|
||||||
self.parent_context = lambda_context.parent_context
|
self.parent_value = lambda_value.parent_value
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def start_pos(self):
|
def start_pos(self):
|
||||||
return self._lambda_context.tree_node.start_pos
|
return self._lambda_value.tree_node.start_pos
|
||||||
|
|
||||||
def infer(self):
|
def infer(self):
|
||||||
return ContextSet([self._lambda_context])
|
return ContextSet([self._lambda_value])
|
||||||
|
|
||||||
|
|
||||||
class FunctionAndClassBase(TreeContext):
|
class FunctionAndClassBase(TreeContext):
|
||||||
def get_qualified_names(self):
|
def get_qualified_names(self):
|
||||||
if self.parent_context.is_class():
|
if self.parent_value.is_class():
|
||||||
n = self.parent_context.get_qualified_names()
|
n = self.parent_value.get_qualified_names()
|
||||||
if n is None:
|
if n is None:
|
||||||
# This means that the parent class lives within a function.
|
# This means that the parent class lives within a function.
|
||||||
return None
|
return None
|
||||||
return n + (self.py__name__(),)
|
return n + (self.py__name__(),)
|
||||||
elif self.parent_context.is_module():
|
elif self.parent_value.is_module():
|
||||||
return (self.py__name__(),)
|
return (self.py__name__(),)
|
||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
@@ -59,7 +59,7 @@ class FunctionMixin(object):
|
|||||||
if search_global:
|
if search_global:
|
||||||
yield ParserTreeFilter(
|
yield ParserTreeFilter(
|
||||||
self.infer_state,
|
self.infer_state,
|
||||||
context=self,
|
value=self,
|
||||||
until_position=until_position,
|
until_position=until_position,
|
||||||
origin_scope=origin_scope
|
origin_scope=origin_scope
|
||||||
)
|
)
|
||||||
@@ -69,8 +69,8 @@ class FunctionMixin(object):
|
|||||||
for filter in instance.get_filters(search_global=False, origin_scope=origin_scope):
|
for filter in instance.get_filters(search_global=False, origin_scope=origin_scope):
|
||||||
yield filter
|
yield filter
|
||||||
|
|
||||||
def py__get__(self, instance, class_context):
|
def py__get__(self, instance, class_value):
|
||||||
from jedi.inference.context.instance import BoundMethod
|
from jedi.inference.value.instance import BoundMethod
|
||||||
if instance is None:
|
if instance is None:
|
||||||
# Calling the Foo.bar results in the original bar function.
|
# Calling the Foo.bar results in the original bar function.
|
||||||
return ContextSet([self])
|
return ContextSet([self])
|
||||||
@@ -98,7 +98,7 @@ class FunctionMixin(object):
|
|||||||
if arguments is None:
|
if arguments is None:
|
||||||
arguments = AnonymousArguments()
|
arguments = AnonymousArguments()
|
||||||
|
|
||||||
return FunctionExecutionContext(self.infer_state, self.parent_context, self, arguments)
|
return FunctionExecutionContext(self.infer_state, self.parent_value, self, arguments)
|
||||||
|
|
||||||
def get_signatures(self):
|
def get_signatures(self):
|
||||||
return [TreeSignature(f) for f in self.get_signature_functions()]
|
return [TreeSignature(f) for f in self.get_signature_functions()]
|
||||||
@@ -109,27 +109,27 @@ class FunctionContext(use_metaclass(CachedMetaClass, FunctionMixin, FunctionAndC
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_context(cls, context, tree_node):
|
def from_value(cls, value, tree_node):
|
||||||
def create(tree_node):
|
def create(tree_node):
|
||||||
if context.is_class():
|
if value.is_class():
|
||||||
return MethodContext(
|
return MethodContext(
|
||||||
context.infer_state,
|
value.infer_state,
|
||||||
context,
|
value,
|
||||||
parent_context=parent_context,
|
parent_value=parent_value,
|
||||||
tree_node=tree_node
|
tree_node=tree_node
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
return cls(
|
return cls(
|
||||||
context.infer_state,
|
value.infer_state,
|
||||||
parent_context=parent_context,
|
parent_value=parent_value,
|
||||||
tree_node=tree_node
|
tree_node=tree_node
|
||||||
)
|
)
|
||||||
|
|
||||||
overloaded_funcs = list(_find_overload_functions(context, tree_node))
|
overloaded_funcs = list(_find_overload_functions(value, tree_node))
|
||||||
|
|
||||||
parent_context = context
|
parent_value = value
|
||||||
while parent_context.is_class() or parent_context.is_instance():
|
while parent_value.is_class() or parent_value.is_instance():
|
||||||
parent_context = parent_context.parent_context
|
parent_value = parent_value.parent_value
|
||||||
|
|
||||||
function = create(tree_node)
|
function = create(tree_node)
|
||||||
|
|
||||||
@@ -141,28 +141,28 @@ class FunctionContext(use_metaclass(CachedMetaClass, FunctionMixin, FunctionAndC
|
|||||||
return function
|
return function
|
||||||
|
|
||||||
def py__class__(self):
|
def py__class__(self):
|
||||||
c, = contexts_from_qualified_names(self.infer_state, u'types', u'FunctionType')
|
c, = values_from_qualified_names(self.infer_state, u'types', u'FunctionType')
|
||||||
return c
|
return c
|
||||||
|
|
||||||
def get_default_param_context(self):
|
def get_default_param_value(self):
|
||||||
return self.parent_context
|
return self.parent_value
|
||||||
|
|
||||||
def get_signature_functions(self):
|
def get_signature_functions(self):
|
||||||
return [self]
|
return [self]
|
||||||
|
|
||||||
|
|
||||||
class MethodContext(FunctionContext):
|
class MethodContext(FunctionContext):
|
||||||
def __init__(self, infer_state, class_context, *args, **kwargs):
|
def __init__(self, infer_state, class_value, *args, **kwargs):
|
||||||
super(MethodContext, self).__init__(infer_state, *args, **kwargs)
|
super(MethodContext, self).__init__(infer_state, *args, **kwargs)
|
||||||
self.class_context = class_context
|
self.class_value = class_value
|
||||||
|
|
||||||
def get_default_param_context(self):
|
def get_default_param_value(self):
|
||||||
return self.class_context
|
return self.class_value
|
||||||
|
|
||||||
def get_qualified_names(self):
|
def get_qualified_names(self):
|
||||||
# Need to implement this, because the parent context of a method
|
# Need to implement this, because the parent value of a method
|
||||||
# context is not the class context but the module.
|
# value is not the class value but the module.
|
||||||
names = self.class_context.get_qualified_names()
|
names = self.class_value.get_qualified_names()
|
||||||
if names is None:
|
if names is None:
|
||||||
return None
|
return None
|
||||||
return names + (self.py__name__(),)
|
return names + (self.py__name__(),)
|
||||||
@@ -171,13 +171,13 @@ class MethodContext(FunctionContext):
|
|||||||
class FunctionExecutionContext(TreeContext):
|
class FunctionExecutionContext(TreeContext):
|
||||||
function_execution_filter = FunctionExecutionFilter
|
function_execution_filter = FunctionExecutionFilter
|
||||||
|
|
||||||
def __init__(self, infer_state, parent_context, function_context, var_args):
|
def __init__(self, infer_state, parent_value, function_value, var_args):
|
||||||
super(FunctionExecutionContext, self).__init__(
|
super(FunctionExecutionContext, self).__init__(
|
||||||
infer_state,
|
infer_state,
|
||||||
parent_context,
|
parent_value,
|
||||||
function_context.tree_node,
|
function_value.tree_node,
|
||||||
)
|
)
|
||||||
self.function_context = function_context
|
self.function_value = function_value
|
||||||
self.var_args = var_args
|
self.var_args = var_args
|
||||||
|
|
||||||
@infer_state_method_cache(default=NO_CONTEXTS)
|
@infer_state_method_cache(default=NO_CONTEXTS)
|
||||||
@@ -188,17 +188,17 @@ class FunctionExecutionContext(TreeContext):
|
|||||||
return self.infer_node(funcdef.children[-1])
|
return self.infer_node(funcdef.children[-1])
|
||||||
|
|
||||||
if check_yields:
|
if check_yields:
|
||||||
context_set = NO_CONTEXTS
|
value_set = NO_CONTEXTS
|
||||||
returns = get_yield_exprs(self.infer_state, funcdef)
|
returns = get_yield_exprs(self.infer_state, funcdef)
|
||||||
else:
|
else:
|
||||||
returns = funcdef.iter_return_stmts()
|
returns = funcdef.iter_return_stmts()
|
||||||
from jedi.inference.gradual.annotation import infer_return_types
|
from jedi.inference.gradual.annotation import infer_return_types
|
||||||
context_set = infer_return_types(self)
|
value_set = infer_return_types(self)
|
||||||
if context_set:
|
if value_set:
|
||||||
# If there are annotations, prefer them over anything else.
|
# If there are annotations, prefer them over anything else.
|
||||||
# This will make it faster.
|
# This will make it faster.
|
||||||
return context_set
|
return value_set
|
||||||
context_set |= docstrings.infer_return_types(self.function_context)
|
value_set |= docstrings.infer_return_types(self.function_value)
|
||||||
|
|
||||||
for r in returns:
|
for r in returns:
|
||||||
check = flow_analysis.reachability_check(self, funcdef, r)
|
check = flow_analysis.reachability_check(self, funcdef, r)
|
||||||
@@ -206,24 +206,24 @@ class FunctionExecutionContext(TreeContext):
|
|||||||
debug.dbg('Return unreachable: %s', r)
|
debug.dbg('Return unreachable: %s', r)
|
||||||
else:
|
else:
|
||||||
if check_yields:
|
if check_yields:
|
||||||
context_set |= ContextSet.from_sets(
|
value_set |= ContextSet.from_sets(
|
||||||
lazy_context.infer()
|
lazy_value.infer()
|
||||||
for lazy_context in self._get_yield_lazy_context(r)
|
for lazy_value in self._get_yield_lazy_value(r)
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
children = r.children
|
children = r.children
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
ctx = compiled.builtin_from_name(self.infer_state, u'None')
|
ctx = compiled.builtin_from_name(self.infer_state, u'None')
|
||||||
context_set |= ContextSet([ctx])
|
value_set |= ContextSet([ctx])
|
||||||
else:
|
else:
|
||||||
context_set |= self.infer_node(children[1])
|
value_set |= self.infer_node(children[1])
|
||||||
if check is flow_analysis.REACHABLE:
|
if check is flow_analysis.REACHABLE:
|
||||||
debug.dbg('Return reachable: %s', r)
|
debug.dbg('Return reachable: %s', r)
|
||||||
break
|
break
|
||||||
return context_set
|
return value_set
|
||||||
|
|
||||||
def _get_yield_lazy_context(self, yield_expr):
|
def _get_yield_lazy_value(self, yield_expr):
|
||||||
if yield_expr.type == 'keyword':
|
if yield_expr.type == 'keyword':
|
||||||
# `yield` just yields None.
|
# `yield` just yields None.
|
||||||
ctx = compiled.builtin_from_name(self.infer_state, u'None')
|
ctx = compiled.builtin_from_name(self.infer_state, u'None')
|
||||||
@@ -233,13 +233,13 @@ class FunctionExecutionContext(TreeContext):
|
|||||||
node = yield_expr.children[1]
|
node = yield_expr.children[1]
|
||||||
if node.type == 'yield_arg': # It must be a yield from.
|
if node.type == 'yield_arg': # It must be a yield from.
|
||||||
cn = ContextualizedNode(self, node.children[1])
|
cn = ContextualizedNode(self, node.children[1])
|
||||||
for lazy_context in cn.infer().iterate(cn):
|
for lazy_value in cn.infer().iterate(cn):
|
||||||
yield lazy_context
|
yield lazy_value
|
||||||
else:
|
else:
|
||||||
yield LazyTreeContext(self, node)
|
yield LazyTreeContext(self, node)
|
||||||
|
|
||||||
@recursion.execution_recursion_decorator(default=iter([]))
|
@recursion.execution_recursion_decorator(default=iter([]))
|
||||||
def get_yield_lazy_contexts(self, is_async=False):
|
def get_yield_lazy_values(self, is_async=False):
|
||||||
# TODO: if is_async, wrap yield statements in Awaitable/async_generator_asend
|
# TODO: if is_async, wrap yield statements in Awaitable/async_generator_asend
|
||||||
for_parents = [(y, tree.search_ancestor(y, 'for_stmt', 'funcdef',
|
for_parents = [(y, tree.search_ancestor(y, 'for_stmt', 'funcdef',
|
||||||
'while_stmt', 'if_stmt'))
|
'while_stmt', 'if_stmt'))
|
||||||
@@ -273,24 +273,24 @@ class FunctionExecutionContext(TreeContext):
|
|||||||
if for_stmt is None:
|
if for_stmt is None:
|
||||||
# No for_stmt, just normal yields.
|
# No for_stmt, just normal yields.
|
||||||
for yield_ in yields:
|
for yield_ in yields:
|
||||||
for result in self._get_yield_lazy_context(yield_):
|
for result in self._get_yield_lazy_value(yield_):
|
||||||
yield result
|
yield result
|
||||||
else:
|
else:
|
||||||
input_node = for_stmt.get_testlist()
|
input_node = for_stmt.get_testlist()
|
||||||
cn = ContextualizedNode(self, input_node)
|
cn = ContextualizedNode(self, input_node)
|
||||||
ordered = cn.infer().iterate(cn)
|
ordered = cn.infer().iterate(cn)
|
||||||
ordered = list(ordered)
|
ordered = list(ordered)
|
||||||
for lazy_context in ordered:
|
for lazy_value in ordered:
|
||||||
dct = {str(for_stmt.children[1].value): lazy_context.infer()}
|
dct = {str(for_stmt.children[1].value): lazy_value.infer()}
|
||||||
with helpers.predefine_names(self, for_stmt, dct):
|
with helpers.predefine_names(self, for_stmt, dct):
|
||||||
for yield_in_same_for_stmt in yields:
|
for yield_in_same_for_stmt in yields:
|
||||||
for result in self._get_yield_lazy_context(yield_in_same_for_stmt):
|
for result in self._get_yield_lazy_value(yield_in_same_for_stmt):
|
||||||
yield result
|
yield result
|
||||||
|
|
||||||
def merge_yield_contexts(self, is_async=False):
|
def merge_yield_values(self, is_async=False):
|
||||||
return ContextSet.from_sets(
|
return ContextSet.from_sets(
|
||||||
lazy_context.infer()
|
lazy_value.infer()
|
||||||
for lazy_context in self.get_yield_lazy_contexts()
|
for lazy_value in self.get_yield_lazy_values()
|
||||||
)
|
)
|
||||||
|
|
||||||
def get_filters(self, search_global=False, until_position=None, origin_scope=None):
|
def get_filters(self, search_global=False, until_position=None, origin_scope=None):
|
||||||
@@ -335,9 +335,9 @@ class FunctionExecutionContext(TreeContext):
|
|||||||
async_generator_classes = infer_state.typing_module \
|
async_generator_classes = infer_state.typing_module \
|
||||||
.py__getattribute__('AsyncGenerator')
|
.py__getattribute__('AsyncGenerator')
|
||||||
|
|
||||||
yield_contexts = self.merge_yield_contexts(is_async=True)
|
yield_values = self.merge_yield_values(is_async=True)
|
||||||
# The contravariant doesn't seem to be defined.
|
# The contravariant doesn't seem to be defined.
|
||||||
generics = (yield_contexts.py__class__(), NO_CONTEXTS)
|
generics = (yield_values.py__class__(), NO_CONTEXTS)
|
||||||
return ContextSet(
|
return ContextSet(
|
||||||
# In Python 3.6 AsyncGenerator is still a class.
|
# In Python 3.6 AsyncGenerator is still a class.
|
||||||
GenericClass(c, generics)
|
GenericClass(c, generics)
|
||||||
@@ -347,9 +347,9 @@ class FunctionExecutionContext(TreeContext):
|
|||||||
if infer_state.environment.version_info < (3, 5):
|
if infer_state.environment.version_info < (3, 5):
|
||||||
return NO_CONTEXTS
|
return NO_CONTEXTS
|
||||||
async_classes = infer_state.typing_module.py__getattribute__('Coroutine')
|
async_classes = infer_state.typing_module.py__getattribute__('Coroutine')
|
||||||
return_contexts = self.get_return_values()
|
return_values = self.get_return_values()
|
||||||
# Only the first generic is relevant.
|
# Only the first generic is relevant.
|
||||||
generics = (return_contexts.py__class__(), NO_CONTEXTS, NO_CONTEXTS)
|
generics = (return_values.py__class__(), NO_CONTEXTS, NO_CONTEXTS)
|
||||||
return ContextSet(
|
return ContextSet(
|
||||||
GenericClass(c, generics) for c in async_classes
|
GenericClass(c, generics) for c in async_classes
|
||||||
).execute_annotation()
|
).execute_annotation()
|
||||||
@@ -366,9 +366,9 @@ class OverloadedFunctionContext(FunctionMixin, ContextWrapper):
|
|||||||
self._overloaded_functions = overloaded_functions
|
self._overloaded_functions = overloaded_functions
|
||||||
|
|
||||||
def py__call__(self, arguments):
|
def py__call__(self, arguments):
|
||||||
debug.dbg("Execute overloaded function %s", self._wrapped_context, color='BLUE')
|
debug.dbg("Execute overloaded function %s", self._wrapped_value, color='BLUE')
|
||||||
function_executions = []
|
function_executions = []
|
||||||
context_set = NO_CONTEXTS
|
value_set = NO_CONTEXTS
|
||||||
matched = False
|
matched = False
|
||||||
for f in self._overloaded_functions:
|
for f in self._overloaded_functions:
|
||||||
function_execution = f.get_function_execution(arguments)
|
function_execution = f.get_function_execution(arguments)
|
||||||
@@ -378,7 +378,7 @@ class OverloadedFunctionContext(FunctionMixin, ContextWrapper):
|
|||||||
return function_execution.infer()
|
return function_execution.infer()
|
||||||
|
|
||||||
if matched:
|
if matched:
|
||||||
return context_set
|
return value_set
|
||||||
|
|
||||||
if self.infer_state.is_analysis:
|
if self.infer_state.is_analysis:
|
||||||
# In this case we want precision.
|
# In this case we want precision.
|
||||||
@@ -389,7 +389,7 @@ class OverloadedFunctionContext(FunctionMixin, ContextWrapper):
|
|||||||
return self._overloaded_functions
|
return self._overloaded_functions
|
||||||
|
|
||||||
|
|
||||||
def _find_overload_functions(context, tree_node):
|
def _find_overload_functions(value, tree_node):
|
||||||
def _is_overload_decorated(funcdef):
|
def _is_overload_decorated(funcdef):
|
||||||
if funcdef.parent.type == 'decorated':
|
if funcdef.parent.type == 'decorated':
|
||||||
decorators = funcdef.parent.children[0]
|
decorators = funcdef.parent.children[0]
|
||||||
@@ -400,7 +400,7 @@ def _find_overload_functions(context, tree_node):
|
|||||||
for decorator in decorators:
|
for decorator in decorators:
|
||||||
dotted_name = decorator.children[1]
|
dotted_name = decorator.children[1]
|
||||||
if dotted_name.type == 'name' and dotted_name.value == 'overload':
|
if dotted_name.type == 'name' and dotted_name.value == 'overload':
|
||||||
# TODO check with contexts if it's the right overload
|
# TODO check with values if it's the right overload
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@@ -412,8 +412,8 @@ def _find_overload_functions(context, tree_node):
|
|||||||
|
|
||||||
while True:
|
while True:
|
||||||
filter = ParserTreeFilter(
|
filter = ParserTreeFilter(
|
||||||
context.infer_state,
|
value.infer_state,
|
||||||
context,
|
value,
|
||||||
until_position=tree_node.start_pos
|
until_position=tree_node.start_pos
|
||||||
)
|
)
|
||||||
names = filter.get(tree_node.name.value)
|
names = filter.get(tree_node.name.value)
|
||||||
@@ -3,21 +3,21 @@ from abc import abstractproperty
|
|||||||
from jedi import debug
|
from jedi import debug
|
||||||
from jedi import settings
|
from jedi import settings
|
||||||
from jedi.inference import compiled
|
from jedi.inference import compiled
|
||||||
from jedi.inference.compiled.context import CompiledObjectFilter
|
from jedi.inference.compiled.value import CompiledObjectFilter
|
||||||
from jedi.inference.helpers import contexts_from_qualified_names
|
from jedi.inference.helpers import values_from_qualified_names
|
||||||
from jedi.inference.filters import AbstractFilter
|
from jedi.inference.filters import AbstractFilter
|
||||||
from jedi.inference.names import ContextName, TreeNameDefinition
|
from jedi.inference.names import ContextName, TreeNameDefinition
|
||||||
from jedi.inference.base_value import Context, NO_CONTEXTS, ContextSet, \
|
from jedi.inference.base_value import Context, NO_CONTEXTS, ContextSet, \
|
||||||
iterator_to_context_set, ContextWrapper
|
iterator_to_value_set, ContextWrapper
|
||||||
from jedi.inference.lazy_context import LazyKnownContext, LazyKnownContexts
|
from jedi.inference.lazy_value import LazyKnownContext, LazyKnownContexts
|
||||||
from jedi.inference.cache import infer_state_method_cache
|
from jedi.inference.cache import infer_state_method_cache
|
||||||
from jedi.inference.arguments import AnonymousArguments, \
|
from jedi.inference.arguments import AnonymousArguments, \
|
||||||
ValuesArguments, TreeArgumentsWrapper
|
ValuesArguments, TreeArgumentsWrapper
|
||||||
from jedi.inference.context.function import \
|
from jedi.inference.value.function import \
|
||||||
FunctionContext, FunctionMixin, OverloadedFunctionContext
|
FunctionContext, FunctionMixin, OverloadedFunctionContext
|
||||||
from jedi.inference.context.klass import ClassContext, apply_py__get__, \
|
from jedi.inference.value.klass import ClassContext, apply_py__get__, \
|
||||||
ClassFilter
|
ClassFilter
|
||||||
from jedi.inference.context import iterable
|
from jedi.inference.value import iterable
|
||||||
from jedi.parser_utils import get_parent_scope
|
from jedi.parser_utils import get_parent_scope
|
||||||
|
|
||||||
|
|
||||||
@@ -38,9 +38,9 @@ class AnonymousInstanceArguments(AnonymousArguments):
|
|||||||
def __init__(self, instance):
|
def __init__(self, instance):
|
||||||
self._instance = instance
|
self._instance = instance
|
||||||
|
|
||||||
def get_executed_params_and_issues(self, execution_context):
|
def get_executed_params_and_issues(self, execution_value):
|
||||||
from jedi.inference.dynamic import search_params
|
from jedi.inference.dynamic import search_params
|
||||||
tree_params = execution_context.tree_node.get_params()
|
tree_params = execution_value.tree_node.get_params()
|
||||||
if not tree_params:
|
if not tree_params:
|
||||||
return [], []
|
return [], []
|
||||||
|
|
||||||
@@ -50,9 +50,9 @@ class AnonymousInstanceArguments(AnonymousArguments):
|
|||||||
# executions of this function, we have all the params already.
|
# executions of this function, we have all the params already.
|
||||||
return [self_param], []
|
return [self_param], []
|
||||||
executed_params = list(search_params(
|
executed_params = list(search_params(
|
||||||
execution_context.infer_state,
|
execution_value.infer_state,
|
||||||
execution_context,
|
execution_value,
|
||||||
execution_context.tree_node
|
execution_value.tree_node
|
||||||
))
|
))
|
||||||
executed_params[0] = self_param
|
executed_params[0] = self_param
|
||||||
return executed_params, []
|
return executed_params, []
|
||||||
@@ -61,21 +61,21 @@ class AnonymousInstanceArguments(AnonymousArguments):
|
|||||||
class AbstractInstanceContext(Context):
|
class AbstractInstanceContext(Context):
|
||||||
api_type = u'instance'
|
api_type = u'instance'
|
||||||
|
|
||||||
def __init__(self, infer_state, parent_context, class_context, var_args):
|
def __init__(self, infer_state, parent_value, class_value, var_args):
|
||||||
super(AbstractInstanceContext, self).__init__(infer_state, parent_context)
|
super(AbstractInstanceContext, self).__init__(infer_state, parent_value)
|
||||||
# Generated instances are classes that are just generated by self
|
# Generated instances are classes that are just generated by self
|
||||||
# (No var_args) used.
|
# (No var_args) used.
|
||||||
self.class_context = class_context
|
self.class_value = class_value
|
||||||
self.var_args = var_args
|
self.var_args = var_args
|
||||||
|
|
||||||
def is_instance(self):
|
def is_instance(self):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def get_qualified_names(self):
|
def get_qualified_names(self):
|
||||||
return self.class_context.get_qualified_names()
|
return self.class_value.get_qualified_names()
|
||||||
|
|
||||||
def get_annotated_class_object(self):
|
def get_annotated_class_object(self):
|
||||||
return self.class_context # This is the default.
|
return self.class_value # This is the default.
|
||||||
|
|
||||||
def py__call__(self, arguments):
|
def py__call__(self, arguments):
|
||||||
names = self.get_function_slot_names(u'__call__')
|
names = self.get_function_slot_names(u'__call__')
|
||||||
@@ -86,7 +86,7 @@ class AbstractInstanceContext(Context):
|
|||||||
return ContextSet.from_sets(name.infer().execute(arguments) for name in names)
|
return ContextSet.from_sets(name.infer().execute(arguments) for name in names)
|
||||||
|
|
||||||
def py__class__(self):
|
def py__class__(self):
|
||||||
return self.class_context
|
return self.class_value
|
||||||
|
|
||||||
def py__bool__(self):
|
def py__bool__(self):
|
||||||
# Signalize that we don't know about the bool type.
|
# Signalize that we don't know about the bool type.
|
||||||
@@ -108,7 +108,7 @@ class AbstractInstanceContext(Context):
|
|||||||
for name in names
|
for name in names
|
||||||
)
|
)
|
||||||
|
|
||||||
def py__get__(self, obj, class_context):
|
def py__get__(self, obj, class_value):
|
||||||
"""
|
"""
|
||||||
obj may be None.
|
obj may be None.
|
||||||
"""
|
"""
|
||||||
@@ -118,15 +118,15 @@ class AbstractInstanceContext(Context):
|
|||||||
if names:
|
if names:
|
||||||
if obj is None:
|
if obj is None:
|
||||||
obj = compiled.builtin_from_name(self.infer_state, u'None')
|
obj = compiled.builtin_from_name(self.infer_state, u'None')
|
||||||
return self.execute_function_slots(names, obj, class_context)
|
return self.execute_function_slots(names, obj, class_value)
|
||||||
else:
|
else:
|
||||||
return ContextSet([self])
|
return ContextSet([self])
|
||||||
|
|
||||||
def get_filters(self, search_global=None, until_position=None,
|
def get_filters(self, search_global=None, until_position=None,
|
||||||
origin_scope=None, include_self_names=True):
|
origin_scope=None, include_self_names=True):
|
||||||
class_context = self.get_annotated_class_object()
|
class_value = self.get_annotated_class_object()
|
||||||
if include_self_names:
|
if include_self_names:
|
||||||
for cls in class_context.py__mro__():
|
for cls in class_value.py__mro__():
|
||||||
if not isinstance(cls, compiled.CompiledObject) \
|
if not isinstance(cls, compiled.CompiledObject) \
|
||||||
or cls.tree_node is not None:
|
or cls.tree_node is not None:
|
||||||
# In this case we're excluding compiled objects that are
|
# In this case we're excluding compiled objects that are
|
||||||
@@ -134,7 +134,7 @@ class AbstractInstanceContext(Context):
|
|||||||
# compiled objects to search for self variables.
|
# compiled objects to search for self variables.
|
||||||
yield SelfAttributeFilter(self.infer_state, self, cls, origin_scope)
|
yield SelfAttributeFilter(self.infer_state, self, cls, origin_scope)
|
||||||
|
|
||||||
class_filters = class_context.get_filters(
|
class_filters = class_value.get_filters(
|
||||||
search_global=False,
|
search_global=False,
|
||||||
origin_scope=origin_scope,
|
origin_scope=origin_scope,
|
||||||
is_instance=True,
|
is_instance=True,
|
||||||
@@ -148,21 +148,21 @@ class AbstractInstanceContext(Context):
|
|||||||
# Propably from the metaclass.
|
# Propably from the metaclass.
|
||||||
yield f
|
yield f
|
||||||
|
|
||||||
def py__getitem__(self, index_context_set, contextualized_node):
|
def py__getitem__(self, index_value_set, valueualized_node):
|
||||||
names = self.get_function_slot_names(u'__getitem__')
|
names = self.get_function_slot_names(u'__getitem__')
|
||||||
if not names:
|
if not names:
|
||||||
return super(AbstractInstanceContext, self).py__getitem__(
|
return super(AbstractInstanceContext, self).py__getitem__(
|
||||||
index_context_set,
|
index_value_set,
|
||||||
contextualized_node,
|
valueualized_node,
|
||||||
)
|
)
|
||||||
|
|
||||||
args = ValuesArguments([index_context_set])
|
args = ValuesArguments([index_value_set])
|
||||||
return ContextSet.from_sets(name.infer().execute(args) for name in names)
|
return ContextSet.from_sets(name.infer().execute(args) for name in names)
|
||||||
|
|
||||||
def py__iter__(self, contextualized_node=None):
|
def py__iter__(self, valueualized_node=None):
|
||||||
iter_slot_names = self.get_function_slot_names(u'__iter__')
|
iter_slot_names = self.get_function_slot_names(u'__iter__')
|
||||||
if not iter_slot_names:
|
if not iter_slot_names:
|
||||||
return super(AbstractInstanceContext, self).py__iter__(contextualized_node)
|
return super(AbstractInstanceContext, self).py__iter__(valueualized_node)
|
||||||
|
|
||||||
def iterate():
|
def iterate():
|
||||||
for generator in self.execute_function_slots(iter_slot_names):
|
for generator in self.execute_function_slots(iter_slot_names):
|
||||||
@@ -180,8 +180,8 @@ class AbstractInstanceContext(Context):
|
|||||||
else:
|
else:
|
||||||
debug.warning('Instance has no __next__ function in %s.', generator)
|
debug.warning('Instance has no __next__ function in %s.', generator)
|
||||||
else:
|
else:
|
||||||
for lazy_context in generator.py__iter__():
|
for lazy_value in generator.py__iter__():
|
||||||
yield lazy_context
|
yield lazy_value
|
||||||
return iterate()
|
return iterate()
|
||||||
|
|
||||||
@abstractproperty
|
@abstractproperty
|
||||||
@@ -192,88 +192,88 @@ class AbstractInstanceContext(Context):
|
|||||||
for name in self.get_function_slot_names(u'__init__'):
|
for name in self.get_function_slot_names(u'__init__'):
|
||||||
# TODO is this correct? I think we need to check for functions.
|
# TODO is this correct? I think we need to check for functions.
|
||||||
if isinstance(name, LazyInstanceClassName):
|
if isinstance(name, LazyInstanceClassName):
|
||||||
function = FunctionContext.from_context(
|
function = FunctionContext.from_value(
|
||||||
self.parent_context,
|
self.parent_value,
|
||||||
name.tree_name.parent
|
name.tree_name.parent
|
||||||
)
|
)
|
||||||
bound_method = BoundMethod(self, function)
|
bound_method = BoundMethod(self, function)
|
||||||
yield bound_method.get_function_execution(self.var_args)
|
yield bound_method.get_function_execution(self.var_args)
|
||||||
|
|
||||||
@infer_state_method_cache()
|
@infer_state_method_cache()
|
||||||
def create_instance_context(self, class_context, node):
|
def create_instance_value(self, class_value, node):
|
||||||
if node.parent.type in ('funcdef', 'classdef'):
|
if node.parent.type in ('funcdef', 'classdef'):
|
||||||
node = node.parent
|
node = node.parent
|
||||||
scope = get_parent_scope(node)
|
scope = get_parent_scope(node)
|
||||||
if scope == class_context.tree_node:
|
if scope == class_value.tree_node:
|
||||||
return class_context
|
return class_value
|
||||||
else:
|
else:
|
||||||
parent_context = self.create_instance_context(class_context, scope)
|
parent_value = self.create_instance_value(class_value, scope)
|
||||||
if scope.type == 'funcdef':
|
if scope.type == 'funcdef':
|
||||||
func = FunctionContext.from_context(
|
func = FunctionContext.from_value(
|
||||||
parent_context,
|
parent_value,
|
||||||
scope,
|
scope,
|
||||||
)
|
)
|
||||||
bound_method = BoundMethod(self, func)
|
bound_method = BoundMethod(self, func)
|
||||||
if scope.name.value == '__init__' and parent_context == class_context:
|
if scope.name.value == '__init__' and parent_value == class_value:
|
||||||
return bound_method.get_function_execution(self.var_args)
|
return bound_method.get_function_execution(self.var_args)
|
||||||
else:
|
else:
|
||||||
return bound_method.get_function_execution()
|
return bound_method.get_function_execution()
|
||||||
elif scope.type == 'classdef':
|
elif scope.type == 'classdef':
|
||||||
class_context = ClassContext(self.infer_state, parent_context, scope)
|
class_value = ClassContext(self.infer_state, parent_value, scope)
|
||||||
return class_context
|
return class_value
|
||||||
elif scope.type in ('comp_for', 'sync_comp_for'):
|
elif scope.type in ('comp_for', 'sync_comp_for'):
|
||||||
# Comprehensions currently don't have a special scope in Jedi.
|
# Comprehensions currently don't have a special scope in Jedi.
|
||||||
return self.create_instance_context(class_context, scope)
|
return self.create_instance_value(class_value, scope)
|
||||||
else:
|
else:
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
return class_context
|
return class_value
|
||||||
|
|
||||||
def get_signatures(self):
|
def get_signatures(self):
|
||||||
call_funcs = self.py__getattribute__('__call__').py__get__(self, self.class_context)
|
call_funcs = self.py__getattribute__('__call__').py__get__(self, self.class_value)
|
||||||
return [s.bind(self) for s in call_funcs.get_signatures()]
|
return [s.bind(self) for s in call_funcs.get_signatures()]
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "<%s of %s(%s)>" % (self.__class__.__name__, self.class_context,
|
return "<%s of %s(%s)>" % (self.__class__.__name__, self.class_value,
|
||||||
self.var_args)
|
self.var_args)
|
||||||
|
|
||||||
|
|
||||||
class CompiledInstance(AbstractInstanceContext):
|
class CompiledInstance(AbstractInstanceContext):
|
||||||
def __init__(self, infer_state, parent_context, class_context, var_args):
|
def __init__(self, infer_state, parent_value, class_value, var_args):
|
||||||
self._original_var_args = var_args
|
self._original_var_args = var_args
|
||||||
super(CompiledInstance, self).__init__(infer_state, parent_context, class_context, var_args)
|
super(CompiledInstance, self).__init__(infer_state, parent_value, class_value, var_args)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def name(self):
|
def name(self):
|
||||||
return compiled.CompiledContextName(self, self.class_context.name.string_name)
|
return compiled.CompiledContextName(self, self.class_value.name.string_name)
|
||||||
|
|
||||||
def get_first_non_keyword_argument_contexts(self):
|
def get_first_non_keyword_argument_values(self):
|
||||||
key, lazy_context = next(self._original_var_args.unpack(), ('', None))
|
key, lazy_value = next(self._original_var_args.unpack(), ('', None))
|
||||||
if key is not None:
|
if key is not None:
|
||||||
return NO_CONTEXTS
|
return NO_CONTEXTS
|
||||||
|
|
||||||
return lazy_context.infer()
|
return lazy_value.infer()
|
||||||
|
|
||||||
def is_stub(self):
|
def is_stub(self):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
class TreeInstance(AbstractInstanceContext):
|
class TreeInstance(AbstractInstanceContext):
|
||||||
def __init__(self, infer_state, parent_context, class_context, var_args):
|
def __init__(self, infer_state, parent_value, class_value, var_args):
|
||||||
# I don't think that dynamic append lookups should happen here. That
|
# I don't think that dynamic append lookups should happen here. That
|
||||||
# sounds more like something that should go to py__iter__.
|
# sounds more like something that should go to py__iter__.
|
||||||
if class_context.py__name__() in ['list', 'set'] \
|
if class_value.py__name__() in ['list', 'set'] \
|
||||||
and parent_context.get_root_context() == infer_state.builtins_module:
|
and parent_value.get_root_value() == infer_state.builtins_module:
|
||||||
# compare the module path with the builtin name.
|
# compare the module path with the builtin name.
|
||||||
if settings.dynamic_array_additions:
|
if settings.dynamic_array_additions:
|
||||||
var_args = iterable.get_dynamic_array_instance(self, var_args)
|
var_args = iterable.get_dynamic_array_instance(self, var_args)
|
||||||
|
|
||||||
super(TreeInstance, self).__init__(infer_state, parent_context,
|
super(TreeInstance, self).__init__(infer_state, parent_value,
|
||||||
class_context, var_args)
|
class_value, var_args)
|
||||||
self.tree_node = class_context.tree_node
|
self.tree_node = class_value.tree_node
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def name(self):
|
def name(self):
|
||||||
return ContextName(self, self.class_context.name.tree_name)
|
return ContextName(self, self.class_value.name.tree_name)
|
||||||
|
|
||||||
# This can recurse, if the initialization of the class includes a reference
|
# This can recurse, if the initialization of the class includes a reference
|
||||||
# to itself.
|
# to itself.
|
||||||
@@ -293,36 +293,36 @@ class TreeInstance(AbstractInstanceContext):
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
all_annotations = py__annotations__(execution.tree_node)
|
all_annotations = py__annotations__(execution.tree_node)
|
||||||
defined, = self.class_context.define_generics(
|
defined, = self.class_value.define_generics(
|
||||||
infer_type_vars_for_execution(execution, all_annotations),
|
infer_type_vars_for_execution(execution, all_annotations),
|
||||||
)
|
)
|
||||||
debug.dbg('Inferred instance context as %s', defined, color='BLUE')
|
debug.dbg('Inferred instance value as %s', defined, color='BLUE')
|
||||||
return defined
|
return defined
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def get_annotated_class_object(self):
|
def get_annotated_class_object(self):
|
||||||
return self._get_annotated_class_object() or self.class_context
|
return self._get_annotated_class_object() or self.class_value
|
||||||
|
|
||||||
def _get_annotation_init_functions(self):
|
def _get_annotation_init_functions(self):
|
||||||
filter = next(self.class_context.get_filters())
|
filter = next(self.class_value.get_filters())
|
||||||
for init_name in filter.get('__init__'):
|
for init_name in filter.get('__init__'):
|
||||||
for init in init_name.infer():
|
for init in init_name.infer():
|
||||||
if init.is_function():
|
if init.is_function():
|
||||||
for signature in init.get_signatures():
|
for signature in init.get_signatures():
|
||||||
yield signature.context
|
yield signature.value
|
||||||
|
|
||||||
|
|
||||||
class AnonymousInstance(TreeInstance):
|
class AnonymousInstance(TreeInstance):
|
||||||
def __init__(self, infer_state, parent_context, class_context):
|
def __init__(self, infer_state, parent_value, class_value):
|
||||||
super(AnonymousInstance, self).__init__(
|
super(AnonymousInstance, self).__init__(
|
||||||
infer_state,
|
infer_state,
|
||||||
parent_context,
|
parent_value,
|
||||||
class_context,
|
class_value,
|
||||||
var_args=AnonymousInstanceArguments(self),
|
var_args=AnonymousInstanceArguments(self),
|
||||||
)
|
)
|
||||||
|
|
||||||
def get_annotated_class_object(self):
|
def get_annotated_class_object(self):
|
||||||
return self.class_context # This is the default.
|
return self.class_value # This is the default.
|
||||||
|
|
||||||
|
|
||||||
class CompiledInstanceName(compiled.CompiledName):
|
class CompiledInstanceName(compiled.CompiledName):
|
||||||
@@ -330,19 +330,19 @@ class CompiledInstanceName(compiled.CompiledName):
|
|||||||
def __init__(self, infer_state, instance, klass, name):
|
def __init__(self, infer_state, instance, klass, name):
|
||||||
super(CompiledInstanceName, self).__init__(
|
super(CompiledInstanceName, self).__init__(
|
||||||
infer_state,
|
infer_state,
|
||||||
klass.parent_context,
|
klass.parent_value,
|
||||||
name.string_name
|
name.string_name
|
||||||
)
|
)
|
||||||
self._instance = instance
|
self._instance = instance
|
||||||
self._class_member_name = name
|
self._class_member_name = name
|
||||||
|
|
||||||
@iterator_to_context_set
|
@iterator_to_value_set
|
||||||
def infer(self):
|
def infer(self):
|
||||||
for result_context in self._class_member_name.infer():
|
for result_value in self._class_member_name.infer():
|
||||||
if result_context.api_type == 'function':
|
if result_value.api_type == 'function':
|
||||||
yield CompiledBoundMethod(result_context)
|
yield CompiledBoundMethod(result_value)
|
||||||
else:
|
else:
|
||||||
yield result_context
|
yield result_value
|
||||||
|
|
||||||
|
|
||||||
class CompiledInstanceClassFilter(AbstractFilter):
|
class CompiledInstanceClassFilter(AbstractFilter):
|
||||||
@@ -376,7 +376,7 @@ class BoundMethod(FunctionMixin, ContextWrapper):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
def py__class__(self):
|
def py__class__(self):
|
||||||
c, = contexts_from_qualified_names(self.infer_state, u'types', u'MethodType')
|
c, = values_from_qualified_names(self.infer_state, u'types', u'MethodType')
|
||||||
return c
|
return c
|
||||||
|
|
||||||
def _get_arguments(self, arguments):
|
def _get_arguments(self, arguments):
|
||||||
@@ -390,8 +390,8 @@ class BoundMethod(FunctionMixin, ContextWrapper):
|
|||||||
return super(BoundMethod, self).get_function_execution(arguments)
|
return super(BoundMethod, self).get_function_execution(arguments)
|
||||||
|
|
||||||
def py__call__(self, arguments):
|
def py__call__(self, arguments):
|
||||||
if isinstance(self._wrapped_context, OverloadedFunctionContext):
|
if isinstance(self._wrapped_value, OverloadedFunctionContext):
|
||||||
return self._wrapped_context.py__call__(self._get_arguments(arguments))
|
return self._wrapped_value.py__call__(self._get_arguments(arguments))
|
||||||
|
|
||||||
function_execution = self.get_function_execution(arguments)
|
function_execution = self.get_function_execution(arguments)
|
||||||
return function_execution.infer()
|
return function_execution.infer()
|
||||||
@@ -399,14 +399,14 @@ class BoundMethod(FunctionMixin, ContextWrapper):
|
|||||||
def get_signature_functions(self):
|
def get_signature_functions(self):
|
||||||
return [
|
return [
|
||||||
BoundMethod(self.instance, f)
|
BoundMethod(self.instance, f)
|
||||||
for f in self._wrapped_context.get_signature_functions()
|
for f in self._wrapped_value.get_signature_functions()
|
||||||
]
|
]
|
||||||
|
|
||||||
def get_signatures(self):
|
def get_signatures(self):
|
||||||
return [sig.bind(self) for sig in super(BoundMethod, self).get_signatures()]
|
return [sig.bind(self) for sig in super(BoundMethod, self).get_signatures()]
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return '<%s: %s>' % (self.__class__.__name__, self._wrapped_context)
|
return '<%s: %s>' % (self.__class__.__name__, self._wrapped_value)
|
||||||
|
|
||||||
|
|
||||||
class CompiledBoundMethod(ContextWrapper):
|
class CompiledBoundMethod(ContextWrapper):
|
||||||
@@ -414,33 +414,33 @@ class CompiledBoundMethod(ContextWrapper):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
def get_signatures(self):
|
def get_signatures(self):
|
||||||
return [sig.bind(self) for sig in self._wrapped_context.get_signatures()]
|
return [sig.bind(self) for sig in self._wrapped_value.get_signatures()]
|
||||||
|
|
||||||
|
|
||||||
class SelfName(TreeNameDefinition):
|
class SelfName(TreeNameDefinition):
|
||||||
"""
|
"""
|
||||||
This name calculates the parent_context lazily.
|
This name calculates the parent_value lazily.
|
||||||
"""
|
"""
|
||||||
def __init__(self, instance, class_context, tree_name):
|
def __init__(self, instance, class_value, tree_name):
|
||||||
self._instance = instance
|
self._instance = instance
|
||||||
self.class_context = class_context
|
self.class_value = class_value
|
||||||
self.tree_name = tree_name
|
self.tree_name = tree_name
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def parent_context(self):
|
def parent_value(self):
|
||||||
return self._instance.create_instance_context(self.class_context, self.tree_name)
|
return self._instance.create_instance_value(self.class_value, self.tree_name)
|
||||||
|
|
||||||
|
|
||||||
class LazyInstanceClassName(object):
|
class LazyInstanceClassName(object):
|
||||||
def __init__(self, instance, class_context, class_member_name):
|
def __init__(self, instance, class_value, class_member_name):
|
||||||
self._instance = instance
|
self._instance = instance
|
||||||
self.class_context = class_context
|
self.class_value = class_value
|
||||||
self._class_member_name = class_member_name
|
self._class_member_name = class_member_name
|
||||||
|
|
||||||
@iterator_to_context_set
|
@iterator_to_value_set
|
||||||
def infer(self):
|
def infer(self):
|
||||||
for result_context in self._class_member_name.infer():
|
for result_value in self._class_member_name.infer():
|
||||||
for c in apply_py__get__(result_context, self._instance, self.class_context):
|
for c in apply_py__get__(result_value, self._instance, self.class_value):
|
||||||
yield c
|
yield c
|
||||||
|
|
||||||
def __getattr__(self, name):
|
def __getattr__(self, name):
|
||||||
@@ -467,10 +467,10 @@ class InstanceClassFilter(AbstractFilter):
|
|||||||
return self._convert(self._class_filter.values(from_instance=True))
|
return self._convert(self._class_filter.values(from_instance=True))
|
||||||
|
|
||||||
def _convert(self, names):
|
def _convert(self, names):
|
||||||
return [LazyInstanceClassName(self._instance, self._class_filter.context, n) for n in names]
|
return [LazyInstanceClassName(self._instance, self._class_filter.value, n) for n in names]
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return '<%s for %s>' % (self.__class__.__name__, self._class_filter.context)
|
return '<%s for %s>' % (self.__class__.__name__, self._class_filter.value)
|
||||||
|
|
||||||
|
|
||||||
class SelfAttributeFilter(ClassFilter):
|
class SelfAttributeFilter(ClassFilter):
|
||||||
@@ -479,15 +479,15 @@ class SelfAttributeFilter(ClassFilter):
|
|||||||
"""
|
"""
|
||||||
name_class = SelfName
|
name_class = SelfName
|
||||||
|
|
||||||
def __init__(self, infer_state, context, class_context, origin_scope):
|
def __init__(self, infer_state, value, class_value, origin_scope):
|
||||||
super(SelfAttributeFilter, self).__init__(
|
super(SelfAttributeFilter, self).__init__(
|
||||||
infer_state=infer_state,
|
infer_state=infer_state,
|
||||||
context=context,
|
value=value,
|
||||||
node_context=class_context,
|
node_value=class_value,
|
||||||
origin_scope=origin_scope,
|
origin_scope=origin_scope,
|
||||||
is_instance=True,
|
is_instance=True,
|
||||||
)
|
)
|
||||||
self._class_context = class_context
|
self._class_value = class_value
|
||||||
|
|
||||||
def _filter(self, names):
|
def _filter(self, names):
|
||||||
names = self._filter_self_names(names)
|
names = self._filter_self_names(names)
|
||||||
@@ -505,7 +505,7 @@ class SelfAttributeFilter(ClassFilter):
|
|||||||
yield name
|
yield name
|
||||||
|
|
||||||
def _convert_names(self, names):
|
def _convert_names(self, names):
|
||||||
return [self.name_class(self.context, self._class_context, name) for name in names]
|
return [self.name_class(self.value, self._class_value, name) for name in names]
|
||||||
|
|
||||||
def _check_flows(self, names):
|
def _check_flows(self, names):
|
||||||
return names
|
return names
|
||||||
@@ -521,8 +521,8 @@ class InstanceArguments(TreeArgumentsWrapper):
|
|||||||
for values in self._wrapped_arguments.unpack(func):
|
for values in self._wrapped_arguments.unpack(func):
|
||||||
yield values
|
yield values
|
||||||
|
|
||||||
def get_executed_params_and_issues(self, execution_context):
|
def get_executed_params_and_issues(self, execution_value):
|
||||||
if isinstance(self._wrapped_arguments, AnonymousInstanceArguments):
|
if isinstance(self._wrapped_arguments, AnonymousInstanceArguments):
|
||||||
return self._wrapped_arguments.get_executed_params_and_issues(execution_context)
|
return self._wrapped_arguments.get_executed_params_and_issues(execution_value)
|
||||||
|
|
||||||
return super(InstanceArguments, self).get_executed_params_and_issues(execution_context)
|
return super(InstanceArguments, self).get_executed_params_and_issues(execution_value)
|
||||||
@@ -28,7 +28,7 @@ from jedi._compatibility import force_unicode, is_py3
|
|||||||
from jedi.inference import compiled
|
from jedi.inference import compiled
|
||||||
from jedi.inference import analysis
|
from jedi.inference import analysis
|
||||||
from jedi.inference import recursion
|
from jedi.inference import recursion
|
||||||
from jedi.inference.lazy_context import LazyKnownContext, LazyKnownContexts, \
|
from jedi.inference.lazy_value import LazyKnownContext, LazyKnownContexts, \
|
||||||
LazyTreeContext
|
LazyTreeContext
|
||||||
from jedi.inference.helpers import get_int_or_none, is_string, \
|
from jedi.inference.helpers import get_int_or_none, is_string, \
|
||||||
predefine_names, infer_call_of_leaf, reraise_getitem_errors, \
|
predefine_names, infer_call_of_leaf, reraise_getitem_errors, \
|
||||||
@@ -38,7 +38,7 @@ from jedi.inference.cache import infer_state_method_cache
|
|||||||
from jedi.inference.filters import ParserTreeFilter, LazyAttributeOverwrite, \
|
from jedi.inference.filters import ParserTreeFilter, LazyAttributeOverwrite, \
|
||||||
publish_method
|
publish_method
|
||||||
from jedi.inference.base_value import ContextSet, Context, NO_CONTEXTS, \
|
from jedi.inference.base_value import ContextSet, Context, NO_CONTEXTS, \
|
||||||
TreeContext, ContextualizedNode, iterate_contexts, HelperContextMixin, _sentinel
|
TreeContext, ContextualizedNode, iterate_values, HelperContextMixin, _sentinel
|
||||||
from jedi.parser_utils import get_sync_comp_fors
|
from jedi.parser_utils import get_sync_comp_fors
|
||||||
|
|
||||||
|
|
||||||
@@ -48,7 +48,7 @@ class IterableMixin(object):
|
|||||||
|
|
||||||
# At the moment, safe values are simple values like "foo", 1 and not
|
# At the moment, safe values are simple values like "foo", 1 and not
|
||||||
# lists/dicts. Therefore as a small speed optimization we can just do the
|
# lists/dicts. Therefore as a small speed optimization we can just do the
|
||||||
# default instead of resolving the lazy wrapped contexts, that are just
|
# default instead of resolving the lazy wrapped values, that are just
|
||||||
# doing this in the end as well.
|
# doing this in the end as well.
|
||||||
# This mostly speeds up patterns like `sys.version_info >= (3, 0)` in
|
# This mostly speeds up patterns like `sys.version_info >= (3, 0)` in
|
||||||
# typeshed.
|
# typeshed.
|
||||||
@@ -56,7 +56,7 @@ class IterableMixin(object):
|
|||||||
# Python 2...........
|
# Python 2...........
|
||||||
def get_safe_value(self, default=_sentinel):
|
def get_safe_value(self, default=_sentinel):
|
||||||
if default is _sentinel:
|
if default is _sentinel:
|
||||||
raise ValueError("There exists no safe value for context %s" % self)
|
raise ValueError("There exists no safe value for value %s" % self)
|
||||||
return default
|
return default
|
||||||
else:
|
else:
|
||||||
get_safe_value = Context.get_safe_value
|
get_safe_value = Context.get_safe_value
|
||||||
@@ -65,7 +65,7 @@ class IterableMixin(object):
|
|||||||
class GeneratorBase(LazyAttributeOverwrite, IterableMixin):
|
class GeneratorBase(LazyAttributeOverwrite, IterableMixin):
|
||||||
array_type = None
|
array_type = None
|
||||||
|
|
||||||
def _get_wrapped_context(self):
|
def _get_wrapped_value(self):
|
||||||
generator, = self.infer_state.typing_module \
|
generator, = self.infer_state.typing_module \
|
||||||
.py__getattribute__('Generator') \
|
.py__getattribute__('Generator') \
|
||||||
.execute_annotation()
|
.execute_annotation()
|
||||||
@@ -78,14 +78,14 @@ class GeneratorBase(LazyAttributeOverwrite, IterableMixin):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
@publish_method('__iter__')
|
@publish_method('__iter__')
|
||||||
def py__iter__(self, contextualized_node=None):
|
def py__iter__(self, valueualized_node=None):
|
||||||
return ContextSet([self])
|
return ContextSet([self])
|
||||||
|
|
||||||
@publish_method('send')
|
@publish_method('send')
|
||||||
@publish_method('next', python_version_match=2)
|
@publish_method('next', python_version_match=2)
|
||||||
@publish_method('__next__', python_version_match=3)
|
@publish_method('__next__', python_version_match=3)
|
||||||
def py__next__(self):
|
def py__next__(self):
|
||||||
return ContextSet.from_sets(lazy_context.infer() for lazy_context in self.py__iter__())
|
return ContextSet.from_sets(lazy_value.infer() for lazy_value in self.py__iter__())
|
||||||
|
|
||||||
def py__stop_iteration_returns(self):
|
def py__stop_iteration_returns(self):
|
||||||
return ContextSet([compiled.builtin_from_name(self.infer_state, u'None')])
|
return ContextSet([compiled.builtin_from_name(self.infer_state, u'None')])
|
||||||
@@ -97,30 +97,30 @@ class GeneratorBase(LazyAttributeOverwrite, IterableMixin):
|
|||||||
|
|
||||||
class Generator(GeneratorBase):
|
class Generator(GeneratorBase):
|
||||||
"""Handling of `yield` functions."""
|
"""Handling of `yield` functions."""
|
||||||
def __init__(self, infer_state, func_execution_context):
|
def __init__(self, infer_state, func_execution_value):
|
||||||
super(Generator, self).__init__(infer_state)
|
super(Generator, self).__init__(infer_state)
|
||||||
self._func_execution_context = func_execution_context
|
self._func_execution_value = func_execution_value
|
||||||
|
|
||||||
def py__iter__(self, contextualized_node=None):
|
def py__iter__(self, valueualized_node=None):
|
||||||
return self._func_execution_context.get_yield_lazy_contexts()
|
return self._func_execution_value.get_yield_lazy_values()
|
||||||
|
|
||||||
def py__stop_iteration_returns(self):
|
def py__stop_iteration_returns(self):
|
||||||
return self._func_execution_context.get_return_values()
|
return self._func_execution_value.get_return_values()
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "<%s of %s>" % (type(self).__name__, self._func_execution_context)
|
return "<%s of %s>" % (type(self).__name__, self._func_execution_value)
|
||||||
|
|
||||||
|
|
||||||
class CompForContext(TreeContext):
|
class CompForContext(TreeContext):
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_comp_for(cls, parent_context, comp_for):
|
def from_comp_for(cls, parent_value, comp_for):
|
||||||
return cls(parent_context.infer_state, parent_context, comp_for)
|
return cls(parent_value.infer_state, parent_value, comp_for)
|
||||||
|
|
||||||
def get_filters(self, search_global=False, until_position=None, origin_scope=None):
|
def get_filters(self, search_global=False, until_position=None, origin_scope=None):
|
||||||
yield ParserTreeFilter(self.infer_state, self)
|
yield ParserTreeFilter(self.infer_state, self)
|
||||||
|
|
||||||
|
|
||||||
def comprehension_from_atom(infer_state, context, atom):
|
def comprehension_from_atom(infer_state, value, atom):
|
||||||
bracket = atom.children[0]
|
bracket = atom.children[0]
|
||||||
test_list_comp = atom.children[1]
|
test_list_comp = atom.children[1]
|
||||||
|
|
||||||
@@ -132,7 +132,7 @@ def comprehension_from_atom(infer_state, context, atom):
|
|||||||
|
|
||||||
return DictComprehension(
|
return DictComprehension(
|
||||||
infer_state,
|
infer_state,
|
||||||
context,
|
value,
|
||||||
sync_comp_for_node=sync_comp_for,
|
sync_comp_for_node=sync_comp_for,
|
||||||
key_node=test_list_comp.children[0],
|
key_node=test_list_comp.children[0],
|
||||||
value_node=test_list_comp.children[2],
|
value_node=test_list_comp.children[2],
|
||||||
@@ -150,7 +150,7 @@ def comprehension_from_atom(infer_state, context, atom):
|
|||||||
|
|
||||||
return cls(
|
return cls(
|
||||||
infer_state,
|
infer_state,
|
||||||
defining_context=context,
|
defining_value=value,
|
||||||
sync_comp_for_node=sync_comp_for,
|
sync_comp_for_node=sync_comp_for,
|
||||||
entry_node=test_list_comp.children[0],
|
entry_node=test_list_comp.children[0],
|
||||||
)
|
)
|
||||||
@@ -158,37 +158,37 @@ def comprehension_from_atom(infer_state, context, atom):
|
|||||||
|
|
||||||
class ComprehensionMixin(object):
|
class ComprehensionMixin(object):
|
||||||
@infer_state_method_cache()
|
@infer_state_method_cache()
|
||||||
def _get_comp_for_context(self, parent_context, comp_for):
|
def _get_comp_for_value(self, parent_value, comp_for):
|
||||||
return CompForContext.from_comp_for(parent_context, comp_for)
|
return CompForContext.from_comp_for(parent_value, comp_for)
|
||||||
|
|
||||||
def _nested(self, comp_fors, parent_context=None):
|
def _nested(self, comp_fors, parent_value=None):
|
||||||
comp_for = comp_fors[0]
|
comp_for = comp_fors[0]
|
||||||
|
|
||||||
is_async = comp_for.parent.type == 'comp_for'
|
is_async = comp_for.parent.type == 'comp_for'
|
||||||
|
|
||||||
input_node = comp_for.children[3]
|
input_node = comp_for.children[3]
|
||||||
parent_context = parent_context or self._defining_context
|
parent_value = parent_value or self._defining_value
|
||||||
input_types = parent_context.infer_node(input_node)
|
input_types = parent_value.infer_node(input_node)
|
||||||
# TODO: simulate await if self.is_async
|
# TODO: simulate await if self.is_async
|
||||||
|
|
||||||
cn = ContextualizedNode(parent_context, input_node)
|
cn = ContextualizedNode(parent_value, input_node)
|
||||||
iterated = input_types.iterate(cn, is_async=is_async)
|
iterated = input_types.iterate(cn, is_async=is_async)
|
||||||
exprlist = comp_for.children[1]
|
exprlist = comp_for.children[1]
|
||||||
for i, lazy_context in enumerate(iterated):
|
for i, lazy_value in enumerate(iterated):
|
||||||
types = lazy_context.infer()
|
types = lazy_value.infer()
|
||||||
dct = unpack_tuple_to_dict(parent_context, types, exprlist)
|
dct = unpack_tuple_to_dict(parent_value, types, exprlist)
|
||||||
context_ = self._get_comp_for_context(
|
value_ = self._get_comp_for_value(
|
||||||
parent_context,
|
parent_value,
|
||||||
comp_for,
|
comp_for,
|
||||||
)
|
)
|
||||||
with predefine_names(context_, comp_for, dct):
|
with predefine_names(value_, comp_for, dct):
|
||||||
try:
|
try:
|
||||||
for result in self._nested(comp_fors[1:], context_):
|
for result in self._nested(comp_fors[1:], value_):
|
||||||
yield result
|
yield result
|
||||||
except IndexError:
|
except IndexError:
|
||||||
iterated = context_.infer_node(self._entry_node)
|
iterated = value_.infer_node(self._entry_node)
|
||||||
if self.array_type == 'dict':
|
if self.array_type == 'dict':
|
||||||
yield iterated, context_.infer_node(self._value_node)
|
yield iterated, value_.infer_node(self._value_node)
|
||||||
else:
|
else:
|
||||||
yield iterated
|
yield iterated
|
||||||
|
|
||||||
@@ -199,7 +199,7 @@ class ComprehensionMixin(object):
|
|||||||
for result in self._nested(comp_fors):
|
for result in self._nested(comp_fors):
|
||||||
yield result
|
yield result
|
||||||
|
|
||||||
def py__iter__(self, contextualized_node=None):
|
def py__iter__(self, valueualized_node=None):
|
||||||
for set_ in self._iterate():
|
for set_ in self._iterate():
|
||||||
yield LazyKnownContexts(set_)
|
yield LazyKnownContexts(set_)
|
||||||
|
|
||||||
@@ -209,7 +209,7 @@ class ComprehensionMixin(object):
|
|||||||
|
|
||||||
class _DictMixin(object):
|
class _DictMixin(object):
|
||||||
def _get_generics(self):
|
def _get_generics(self):
|
||||||
return tuple(c_set.py__class__() for c_set in self.get_mapping_item_contexts())
|
return tuple(c_set.py__class__() for c_set in self.get_mapping_item_values())
|
||||||
|
|
||||||
|
|
||||||
class Sequence(LazyAttributeOverwrite, IterableMixin):
|
class Sequence(LazyAttributeOverwrite, IterableMixin):
|
||||||
@@ -222,7 +222,7 @@ class Sequence(LazyAttributeOverwrite, IterableMixin):
|
|||||||
def _get_generics(self):
|
def _get_generics(self):
|
||||||
return (self.merge_types_of_iterate().py__class__(),)
|
return (self.merge_types_of_iterate().py__class__(),)
|
||||||
|
|
||||||
def _get_wrapped_context(self):
|
def _get_wrapped_value(self):
|
||||||
from jedi.inference.gradual.typing import GenericClass
|
from jedi.inference.gradual.typing import GenericClass
|
||||||
klass = compiled.builtin_from_name(self.infer_state, self.array_type)
|
klass = compiled.builtin_from_name(self.infer_state, self.array_type)
|
||||||
c, = GenericClass(klass, self._get_generics()).execute_annotation()
|
c, = GenericClass(klass, self._get_generics()).execute_annotation()
|
||||||
@@ -238,17 +238,17 @@ class Sequence(LazyAttributeOverwrite, IterableMixin):
|
|||||||
def parent(self):
|
def parent(self):
|
||||||
return self.infer_state.builtins_module
|
return self.infer_state.builtins_module
|
||||||
|
|
||||||
def py__getitem__(self, index_context_set, contextualized_node):
|
def py__getitem__(self, index_value_set, valueualized_node):
|
||||||
if self.array_type == 'dict':
|
if self.array_type == 'dict':
|
||||||
return self._dict_values()
|
return self._dict_values()
|
||||||
return iterate_contexts(ContextSet([self]))
|
return iterate_values(ContextSet([self]))
|
||||||
|
|
||||||
|
|
||||||
class _BaseComprehension(ComprehensionMixin):
|
class _BaseComprehension(ComprehensionMixin):
|
||||||
def __init__(self, infer_state, defining_context, sync_comp_for_node, entry_node):
|
def __init__(self, infer_state, defining_value, sync_comp_for_node, entry_node):
|
||||||
assert sync_comp_for_node.type == 'sync_comp_for'
|
assert sync_comp_for_node.type == 'sync_comp_for'
|
||||||
super(_BaseComprehension, self).__init__(infer_state)
|
super(_BaseComprehension, self).__init__(infer_state)
|
||||||
self._defining_context = defining_context
|
self._defining_value = defining_value
|
||||||
self._sync_comp_for_node = sync_comp_for_node
|
self._sync_comp_for_node = sync_comp_for_node
|
||||||
self._entry_node = entry_node
|
self._entry_node = entry_node
|
||||||
|
|
||||||
@@ -262,8 +262,8 @@ class ListComprehension(_BaseComprehension, Sequence):
|
|||||||
|
|
||||||
all_types = list(self.py__iter__())
|
all_types = list(self.py__iter__())
|
||||||
with reraise_getitem_errors(IndexError, TypeError):
|
with reraise_getitem_errors(IndexError, TypeError):
|
||||||
lazy_context = all_types[index]
|
lazy_value = all_types[index]
|
||||||
return lazy_context.infer()
|
return lazy_value.infer()
|
||||||
|
|
||||||
|
|
||||||
class SetComprehension(_BaseComprehension, Sequence):
|
class SetComprehension(_BaseComprehension, Sequence):
|
||||||
@@ -277,15 +277,15 @@ class GeneratorComprehension(_BaseComprehension, GeneratorBase):
|
|||||||
class DictComprehension(ComprehensionMixin, Sequence):
|
class DictComprehension(ComprehensionMixin, Sequence):
|
||||||
array_type = u'dict'
|
array_type = u'dict'
|
||||||
|
|
||||||
def __init__(self, infer_state, defining_context, sync_comp_for_node, key_node, value_node):
|
def __init__(self, infer_state, defining_value, sync_comp_for_node, key_node, value_node):
|
||||||
assert sync_comp_for_node.type == 'sync_comp_for'
|
assert sync_comp_for_node.type == 'sync_comp_for'
|
||||||
super(DictComprehension, self).__init__(infer_state)
|
super(DictComprehension, self).__init__(infer_state)
|
||||||
self._defining_context = defining_context
|
self._defining_value = defining_value
|
||||||
self._sync_comp_for_node = sync_comp_for_node
|
self._sync_comp_for_node = sync_comp_for_node
|
||||||
self._entry_node = key_node
|
self._entry_node = key_node
|
||||||
self._value_node = value_node
|
self._value_node = value_node
|
||||||
|
|
||||||
def py__iter__(self, contextualized_node=None):
|
def py__iter__(self, valueualized_node=None):
|
||||||
for keys, values in self._iterate():
|
for keys, values in self._iterate():
|
||||||
yield LazyKnownContexts(keys)
|
yield LazyKnownContexts(keys)
|
||||||
|
|
||||||
@@ -307,12 +307,12 @@ class DictComprehension(ComprehensionMixin, Sequence):
|
|||||||
|
|
||||||
@publish_method('values')
|
@publish_method('values')
|
||||||
def _imitate_values(self):
|
def _imitate_values(self):
|
||||||
lazy_context = LazyKnownContexts(self._dict_values())
|
lazy_value = LazyKnownContexts(self._dict_values())
|
||||||
return ContextSet([FakeSequence(self.infer_state, u'list', [lazy_context])])
|
return ContextSet([FakeSequence(self.infer_state, u'list', [lazy_value])])
|
||||||
|
|
||||||
@publish_method('items')
|
@publish_method('items')
|
||||||
def _imitate_items(self):
|
def _imitate_items(self):
|
||||||
lazy_contexts = [
|
lazy_values = [
|
||||||
LazyKnownContext(
|
LazyKnownContext(
|
||||||
FakeSequence(
|
FakeSequence(
|
||||||
self.infer_state,
|
self.infer_state,
|
||||||
@@ -324,9 +324,9 @@ class DictComprehension(ComprehensionMixin, Sequence):
|
|||||||
for key, value in self._iterate()
|
for key, value in self._iterate()
|
||||||
]
|
]
|
||||||
|
|
||||||
return ContextSet([FakeSequence(self.infer_state, u'list', lazy_contexts)])
|
return ContextSet([FakeSequence(self.infer_state, u'list', lazy_values)])
|
||||||
|
|
||||||
def get_mapping_item_contexts(self):
|
def get_mapping_item_values(self):
|
||||||
return self._dict_keys(), self._dict_values()
|
return self._dict_keys(), self._dict_values()
|
||||||
|
|
||||||
def exact_key_items(self):
|
def exact_key_items(self):
|
||||||
@@ -341,10 +341,10 @@ class SequenceLiteralContext(Sequence):
|
|||||||
'[': u'list',
|
'[': u'list',
|
||||||
'{': u'set'}
|
'{': u'set'}
|
||||||
|
|
||||||
def __init__(self, infer_state, defining_context, atom):
|
def __init__(self, infer_state, defining_value, atom):
|
||||||
super(SequenceLiteralContext, self).__init__(infer_state)
|
super(SequenceLiteralContext, self).__init__(infer_state)
|
||||||
self.atom = atom
|
self.atom = atom
|
||||||
self._defining_context = defining_context
|
self._defining_value = defining_value
|
||||||
|
|
||||||
if self.atom.type in self._TUPLE_LIKE:
|
if self.atom.type in self._TUPLE_LIKE:
|
||||||
self.array_type = u'tuple'
|
self.array_type = u'tuple'
|
||||||
@@ -357,14 +357,14 @@ class SequenceLiteralContext(Sequence):
|
|||||||
if self.array_type == u'dict':
|
if self.array_type == u'dict':
|
||||||
compiled_obj_index = compiled.create_simple_object(self.infer_state, index)
|
compiled_obj_index = compiled.create_simple_object(self.infer_state, index)
|
||||||
for key, value in self.get_tree_entries():
|
for key, value in self.get_tree_entries():
|
||||||
for k in self._defining_context.infer_node(key):
|
for k in self._defining_value.infer_node(key):
|
||||||
try:
|
try:
|
||||||
method = k.execute_operation
|
method = k.execute_operation
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
if method(compiled_obj_index, u'==').get_safe_value():
|
if method(compiled_obj_index, u'==').get_safe_value():
|
||||||
return self._defining_context.infer_node(value)
|
return self._defining_value.infer_node(value)
|
||||||
raise SimpleGetItemNotFound('No key found in dictionary %s.' % self)
|
raise SimpleGetItemNotFound('No key found in dictionary %s.' % self)
|
||||||
|
|
||||||
if isinstance(index, slice):
|
if isinstance(index, slice):
|
||||||
@@ -372,9 +372,9 @@ class SequenceLiteralContext(Sequence):
|
|||||||
else:
|
else:
|
||||||
with reraise_getitem_errors(TypeError, KeyError, IndexError):
|
with reraise_getitem_errors(TypeError, KeyError, IndexError):
|
||||||
node = self.get_tree_entries()[index]
|
node = self.get_tree_entries()[index]
|
||||||
return self._defining_context.infer_node(node)
|
return self._defining_value.infer_node(node)
|
||||||
|
|
||||||
def py__iter__(self, contextualized_node=None):
|
def py__iter__(self, valueualized_node=None):
|
||||||
"""
|
"""
|
||||||
While values returns the possible values for any array field, this
|
While values returns the possible values for any array field, this
|
||||||
function returns the value for a certain index.
|
function returns the value for a certain index.
|
||||||
@@ -383,7 +383,7 @@ class SequenceLiteralContext(Sequence):
|
|||||||
# Get keys.
|
# Get keys.
|
||||||
types = NO_CONTEXTS
|
types = NO_CONTEXTS
|
||||||
for k, _ in self.get_tree_entries():
|
for k, _ in self.get_tree_entries():
|
||||||
types |= self._defining_context.infer_node(k)
|
types |= self._defining_value.infer_node(k)
|
||||||
# We don't know which dict index comes first, therefore always
|
# We don't know which dict index comes first, therefore always
|
||||||
# yield all the types.
|
# yield all the types.
|
||||||
for _ in types:
|
for _ in types:
|
||||||
@@ -393,10 +393,10 @@ class SequenceLiteralContext(Sequence):
|
|||||||
if node == ':' or node.type == 'subscript':
|
if node == ':' or node.type == 'subscript':
|
||||||
# TODO this should probably use at least part of the code
|
# TODO this should probably use at least part of the code
|
||||||
# of infer_subscript_list.
|
# of infer_subscript_list.
|
||||||
yield LazyKnownContext(Slice(self._defining_context, None, None, None))
|
yield LazyKnownContext(Slice(self._defining_value, None, None, None))
|
||||||
else:
|
else:
|
||||||
yield LazyTreeContext(self._defining_context, node)
|
yield LazyTreeContext(self._defining_value, node)
|
||||||
for addition in check_array_additions(self._defining_context, self):
|
for addition in check_array_additions(self._defining_value, self):
|
||||||
yield addition
|
yield addition
|
||||||
|
|
||||||
def py__len__(self):
|
def py__len__(self):
|
||||||
@@ -405,7 +405,7 @@ class SequenceLiteralContext(Sequence):
|
|||||||
|
|
||||||
def _dict_values(self):
|
def _dict_values(self):
|
||||||
return ContextSet.from_sets(
|
return ContextSet.from_sets(
|
||||||
self._defining_context.infer_node(v)
|
self._defining_value.infer_node(v)
|
||||||
for k, v in self.get_tree_entries()
|
for k, v in self.get_tree_entries()
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -457,12 +457,12 @@ class SequenceLiteralContext(Sequence):
|
|||||||
def exact_key_items(self):
|
def exact_key_items(self):
|
||||||
"""
|
"""
|
||||||
Returns a generator of tuples like dict.items(), where the key is
|
Returns a generator of tuples like dict.items(), where the key is
|
||||||
resolved (as a string) and the values are still lazy contexts.
|
resolved (as a string) and the values are still lazy values.
|
||||||
"""
|
"""
|
||||||
for key_node, value in self.get_tree_entries():
|
for key_node, value in self.get_tree_entries():
|
||||||
for key in self._defining_context.infer_node(key_node):
|
for key in self._defining_value.infer_node(key_node):
|
||||||
if is_string(key):
|
if is_string(key):
|
||||||
yield key.get_safe_value(), LazyTreeContext(self._defining_context, value)
|
yield key.get_safe_value(), LazyTreeContext(self._defining_value, value)
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "<%s of %s>" % (self.__class__.__name__, self.atom)
|
return "<%s of %s>" % (self.__class__.__name__, self.atom)
|
||||||
@@ -471,35 +471,35 @@ class SequenceLiteralContext(Sequence):
|
|||||||
class DictLiteralContext(_DictMixin, SequenceLiteralContext):
|
class DictLiteralContext(_DictMixin, SequenceLiteralContext):
|
||||||
array_type = u'dict'
|
array_type = u'dict'
|
||||||
|
|
||||||
def __init__(self, infer_state, defining_context, atom):
|
def __init__(self, infer_state, defining_value, atom):
|
||||||
super(SequenceLiteralContext, self).__init__(infer_state)
|
super(SequenceLiteralContext, self).__init__(infer_state)
|
||||||
self._defining_context = defining_context
|
self._defining_value = defining_value
|
||||||
self.atom = atom
|
self.atom = atom
|
||||||
|
|
||||||
@publish_method('values')
|
@publish_method('values')
|
||||||
def _imitate_values(self):
|
def _imitate_values(self):
|
||||||
lazy_context = LazyKnownContexts(self._dict_values())
|
lazy_value = LazyKnownContexts(self._dict_values())
|
||||||
return ContextSet([FakeSequence(self.infer_state, u'list', [lazy_context])])
|
return ContextSet([FakeSequence(self.infer_state, u'list', [lazy_value])])
|
||||||
|
|
||||||
@publish_method('items')
|
@publish_method('items')
|
||||||
def _imitate_items(self):
|
def _imitate_items(self):
|
||||||
lazy_contexts = [
|
lazy_values = [
|
||||||
LazyKnownContext(FakeSequence(
|
LazyKnownContext(FakeSequence(
|
||||||
self.infer_state, u'tuple',
|
self.infer_state, u'tuple',
|
||||||
(LazyTreeContext(self._defining_context, key_node),
|
(LazyTreeContext(self._defining_value, key_node),
|
||||||
LazyTreeContext(self._defining_context, value_node))
|
LazyTreeContext(self._defining_value, value_node))
|
||||||
)) for key_node, value_node in self.get_tree_entries()
|
)) for key_node, value_node in self.get_tree_entries()
|
||||||
]
|
]
|
||||||
|
|
||||||
return ContextSet([FakeSequence(self.infer_state, u'list', lazy_contexts)])
|
return ContextSet([FakeSequence(self.infer_state, u'list', lazy_values)])
|
||||||
|
|
||||||
def _dict_keys(self):
|
def _dict_keys(self):
|
||||||
return ContextSet.from_sets(
|
return ContextSet.from_sets(
|
||||||
self._defining_context.infer_node(k)
|
self._defining_value.infer_node(k)
|
||||||
for k, v in self.get_tree_entries()
|
for k, v in self.get_tree_entries()
|
||||||
)
|
)
|
||||||
|
|
||||||
def get_mapping_item_contexts(self):
|
def get_mapping_item_values(self):
|
||||||
return self._dict_keys(), self._dict_values()
|
return self._dict_keys(), self._dict_values()
|
||||||
|
|
||||||
|
|
||||||
@@ -512,29 +512,29 @@ class _FakeArray(SequenceLiteralContext):
|
|||||||
|
|
||||||
|
|
||||||
class FakeSequence(_FakeArray):
|
class FakeSequence(_FakeArray):
|
||||||
def __init__(self, infer_state, array_type, lazy_context_list):
|
def __init__(self, infer_state, array_type, lazy_value_list):
|
||||||
"""
|
"""
|
||||||
type should be one of "tuple", "list"
|
type should be one of "tuple", "list"
|
||||||
"""
|
"""
|
||||||
super(FakeSequence, self).__init__(infer_state, None, array_type)
|
super(FakeSequence, self).__init__(infer_state, None, array_type)
|
||||||
self._lazy_context_list = lazy_context_list
|
self._lazy_value_list = lazy_value_list
|
||||||
|
|
||||||
def py__simple_getitem__(self, index):
|
def py__simple_getitem__(self, index):
|
||||||
if isinstance(index, slice):
|
if isinstance(index, slice):
|
||||||
return ContextSet([self])
|
return ContextSet([self])
|
||||||
|
|
||||||
with reraise_getitem_errors(IndexError, TypeError):
|
with reraise_getitem_errors(IndexError, TypeError):
|
||||||
lazy_context = self._lazy_context_list[index]
|
lazy_value = self._lazy_value_list[index]
|
||||||
return lazy_context.infer()
|
return lazy_value.infer()
|
||||||
|
|
||||||
def py__iter__(self, contextualized_node=None):
|
def py__iter__(self, valueualized_node=None):
|
||||||
return self._lazy_context_list
|
return self._lazy_value_list
|
||||||
|
|
||||||
def py__bool__(self):
|
def py__bool__(self):
|
||||||
return bool(len(self._lazy_context_list))
|
return bool(len(self._lazy_value_list))
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "<%s of %s>" % (type(self).__name__, self._lazy_context_list)
|
return "<%s of %s>" % (type(self).__name__, self._lazy_value_list)
|
||||||
|
|
||||||
|
|
||||||
class FakeDict(_DictMixin, _FakeArray):
|
class FakeDict(_DictMixin, _FakeArray):
|
||||||
@@ -542,7 +542,7 @@ class FakeDict(_DictMixin, _FakeArray):
|
|||||||
super(FakeDict, self).__init__(infer_state, dct, u'dict')
|
super(FakeDict, self).__init__(infer_state, dct, u'dict')
|
||||||
self._dct = dct
|
self._dct = dct
|
||||||
|
|
||||||
def py__iter__(self, contextualized_node=None):
|
def py__iter__(self, valueualized_node=None):
|
||||||
for key in self._dct:
|
for key in self._dct:
|
||||||
yield LazyKnownContext(compiled.create_simple_object(self.infer_state, key))
|
yield LazyKnownContext(compiled.create_simple_object(self.infer_state, key))
|
||||||
|
|
||||||
@@ -563,8 +563,8 @@ class FakeDict(_DictMixin, _FakeArray):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
with reraise_getitem_errors(KeyError, TypeError):
|
with reraise_getitem_errors(KeyError, TypeError):
|
||||||
lazy_context = self._dct[index]
|
lazy_value = self._dct[index]
|
||||||
return lazy_context.infer()
|
return lazy_value.infer()
|
||||||
|
|
||||||
@publish_method('values')
|
@publish_method('values')
|
||||||
def _values(self):
|
def _values(self):
|
||||||
@@ -574,12 +574,12 @@ class FakeDict(_DictMixin, _FakeArray):
|
|||||||
)])
|
)])
|
||||||
|
|
||||||
def _dict_values(self):
|
def _dict_values(self):
|
||||||
return ContextSet.from_sets(lazy_context.infer() for lazy_context in self._dct.values())
|
return ContextSet.from_sets(lazy_value.infer() for lazy_value in self._dct.values())
|
||||||
|
|
||||||
def _dict_keys(self):
|
def _dict_keys(self):
|
||||||
return ContextSet.from_sets(lazy_context.infer() for lazy_context in self.py__iter__())
|
return ContextSet.from_sets(lazy_value.infer() for lazy_value in self.py__iter__())
|
||||||
|
|
||||||
def get_mapping_item_contexts(self):
|
def get_mapping_item_values(self):
|
||||||
return self._dict_keys(), self._dict_values()
|
return self._dict_keys(), self._dict_values()
|
||||||
|
|
||||||
def exact_key_items(self):
|
def exact_key_items(self):
|
||||||
@@ -591,13 +591,13 @@ class MergedArray(_FakeArray):
|
|||||||
super(MergedArray, self).__init__(infer_state, arrays, arrays[-1].array_type)
|
super(MergedArray, self).__init__(infer_state, arrays, arrays[-1].array_type)
|
||||||
self._arrays = arrays
|
self._arrays = arrays
|
||||||
|
|
||||||
def py__iter__(self, contextualized_node=None):
|
def py__iter__(self, valueualized_node=None):
|
||||||
for array in self._arrays:
|
for array in self._arrays:
|
||||||
for lazy_context in array.py__iter__():
|
for lazy_value in array.py__iter__():
|
||||||
yield lazy_context
|
yield lazy_value
|
||||||
|
|
||||||
def py__simple_getitem__(self, index):
|
def py__simple_getitem__(self, index):
|
||||||
return ContextSet.from_sets(lazy_context.infer() for lazy_context in self.py__iter__())
|
return ContextSet.from_sets(lazy_value.infer() for lazy_value in self.py__iter__())
|
||||||
|
|
||||||
def get_tree_entries(self):
|
def get_tree_entries(self):
|
||||||
for array in self._arrays:
|
for array in self._arrays:
|
||||||
@@ -608,33 +608,33 @@ class MergedArray(_FakeArray):
|
|||||||
return sum(len(a) for a in self._arrays)
|
return sum(len(a) for a in self._arrays)
|
||||||
|
|
||||||
|
|
||||||
def unpack_tuple_to_dict(context, types, exprlist):
|
def unpack_tuple_to_dict(value, types, exprlist):
|
||||||
"""
|
"""
|
||||||
Unpacking tuple assignments in for statements and expr_stmts.
|
Unpacking tuple assignments in for statements and expr_stmts.
|
||||||
"""
|
"""
|
||||||
if exprlist.type == 'name':
|
if exprlist.type == 'name':
|
||||||
return {exprlist.value: types}
|
return {exprlist.value: types}
|
||||||
elif exprlist.type == 'atom' and exprlist.children[0] in ('(', '['):
|
elif exprlist.type == 'atom' and exprlist.children[0] in ('(', '['):
|
||||||
return unpack_tuple_to_dict(context, types, exprlist.children[1])
|
return unpack_tuple_to_dict(value, types, exprlist.children[1])
|
||||||
elif exprlist.type in ('testlist', 'testlist_comp', 'exprlist',
|
elif exprlist.type in ('testlist', 'testlist_comp', 'exprlist',
|
||||||
'testlist_star_expr'):
|
'testlist_star_expr'):
|
||||||
dct = {}
|
dct = {}
|
||||||
parts = iter(exprlist.children[::2])
|
parts = iter(exprlist.children[::2])
|
||||||
n = 0
|
n = 0
|
||||||
for lazy_context in types.iterate(exprlist):
|
for lazy_value in types.iterate(exprlist):
|
||||||
n += 1
|
n += 1
|
||||||
try:
|
try:
|
||||||
part = next(parts)
|
part = next(parts)
|
||||||
except StopIteration:
|
except StopIteration:
|
||||||
# TODO this context is probably not right.
|
# TODO this value is probably not right.
|
||||||
analysis.add(context, 'value-error-too-many-values', part,
|
analysis.add(value, 'value-error-too-many-values', part,
|
||||||
message="ValueError: too many values to unpack (expected %s)" % n)
|
message="ValueError: too many values to unpack (expected %s)" % n)
|
||||||
else:
|
else:
|
||||||
dct.update(unpack_tuple_to_dict(context, lazy_context.infer(), part))
|
dct.update(unpack_tuple_to_dict(value, lazy_value.infer(), part))
|
||||||
has_parts = next(parts, None)
|
has_parts = next(parts, None)
|
||||||
if types and has_parts is not None:
|
if types and has_parts is not None:
|
||||||
# TODO this context is probably not right.
|
# TODO this value is probably not right.
|
||||||
analysis.add(context, 'value-error-too-few-values', has_parts,
|
analysis.add(value, 'value-error-too-few-values', has_parts,
|
||||||
message="ValueError: need more than %s values to unpack" % n)
|
message="ValueError: need more than %s values to unpack" % n)
|
||||||
return dct
|
return dct
|
||||||
elif exprlist.type == 'power' or exprlist.type == 'atom_expr':
|
elif exprlist.type == 'power' or exprlist.type == 'atom_expr':
|
||||||
@@ -648,18 +648,18 @@ def unpack_tuple_to_dict(context, types, exprlist):
|
|||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
|
|
||||||
def check_array_additions(context, sequence):
|
def check_array_additions(value, sequence):
|
||||||
""" Just a mapper function for the internal _check_array_additions """
|
""" Just a mapper function for the internal _check_array_additions """
|
||||||
if sequence.array_type not in ('list', 'set'):
|
if sequence.array_type not in ('list', 'set'):
|
||||||
# TODO also check for dict updates
|
# TODO also check for dict updates
|
||||||
return NO_CONTEXTS
|
return NO_CONTEXTS
|
||||||
|
|
||||||
return _check_array_additions(context, sequence)
|
return _check_array_additions(value, sequence)
|
||||||
|
|
||||||
|
|
||||||
@infer_state_method_cache(default=NO_CONTEXTS)
|
@infer_state_method_cache(default=NO_CONTEXTS)
|
||||||
@debug.increase_indent
|
@debug.increase_indent
|
||||||
def _check_array_additions(context, sequence):
|
def _check_array_additions(value, sequence):
|
||||||
"""
|
"""
|
||||||
Checks if a `Array` has "add" (append, insert, extend) statements:
|
Checks if a `Array` has "add" (append, insert, extend) statements:
|
||||||
|
|
||||||
@@ -669,22 +669,22 @@ def _check_array_additions(context, sequence):
|
|||||||
from jedi.inference import arguments
|
from jedi.inference import arguments
|
||||||
|
|
||||||
debug.dbg('Dynamic array search for %s' % sequence, color='MAGENTA')
|
debug.dbg('Dynamic array search for %s' % sequence, color='MAGENTA')
|
||||||
module_context = context.get_root_context()
|
module_value = value.get_root_value()
|
||||||
if not settings.dynamic_array_additions or isinstance(module_context, compiled.CompiledObject):
|
if not settings.dynamic_array_additions or isinstance(module_value, compiled.CompiledObject):
|
||||||
debug.dbg('Dynamic array search aborted.', color='MAGENTA')
|
debug.dbg('Dynamic array search aborted.', color='MAGENTA')
|
||||||
return NO_CONTEXTS
|
return NO_CONTEXTS
|
||||||
|
|
||||||
def find_additions(context, arglist, add_name):
|
def find_additions(value, arglist, add_name):
|
||||||
params = list(arguments.TreeArguments(context.infer_state, context, arglist).unpack())
|
params = list(arguments.TreeArguments(value.infer_state, value, arglist).unpack())
|
||||||
result = set()
|
result = set()
|
||||||
if add_name in ['insert']:
|
if add_name in ['insert']:
|
||||||
params = params[1:]
|
params = params[1:]
|
||||||
if add_name in ['append', 'add', 'insert']:
|
if add_name in ['append', 'add', 'insert']:
|
||||||
for key, lazy_context in params:
|
for key, lazy_value in params:
|
||||||
result.add(lazy_context)
|
result.add(lazy_value)
|
||||||
elif add_name in ['extend', 'update']:
|
elif add_name in ['extend', 'update']:
|
||||||
for key, lazy_context in params:
|
for key, lazy_value in params:
|
||||||
result |= set(lazy_context.infer().iterate())
|
result |= set(lazy_value.infer().iterate())
|
||||||
return result
|
return result
|
||||||
|
|
||||||
temp_param_add, settings.dynamic_params_for_other_modules = \
|
temp_param_add, settings.dynamic_params_for_other_modules = \
|
||||||
@@ -696,13 +696,13 @@ def _check_array_additions(context, sequence):
|
|||||||
added_types = set()
|
added_types = set()
|
||||||
for add_name in search_names:
|
for add_name in search_names:
|
||||||
try:
|
try:
|
||||||
possible_names = module_context.tree_node.get_used_names()[add_name]
|
possible_names = module_value.tree_node.get_used_names()[add_name]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
continue
|
continue
|
||||||
else:
|
else:
|
||||||
for name in possible_names:
|
for name in possible_names:
|
||||||
context_node = context.tree_node
|
value_node = value.tree_node
|
||||||
if not (context_node.start_pos < name.start_pos < context_node.end_pos):
|
if not (value_node.start_pos < name.start_pos < value_node.end_pos):
|
||||||
continue
|
continue
|
||||||
trailer = name.parent
|
trailer = name.parent
|
||||||
power = trailer.parent
|
power = trailer.parent
|
||||||
@@ -717,19 +717,19 @@ def _check_array_additions(context, sequence):
|
|||||||
or execution_trailer.children[1] == ')':
|
or execution_trailer.children[1] == ')':
|
||||||
continue
|
continue
|
||||||
|
|
||||||
random_context = context.create_context(name)
|
random_value = value.create_value(name)
|
||||||
|
|
||||||
with recursion.execution_allowed(context.infer_state, power) as allowed:
|
with recursion.execution_allowed(value.infer_state, power) as allowed:
|
||||||
if allowed:
|
if allowed:
|
||||||
found = infer_call_of_leaf(
|
found = infer_call_of_leaf(
|
||||||
random_context,
|
random_value,
|
||||||
name,
|
name,
|
||||||
cut_own_trailer=True
|
cut_own_trailer=True
|
||||||
)
|
)
|
||||||
if sequence in found:
|
if sequence in found:
|
||||||
# The arrays match. Now add the results
|
# The arrays match. Now add the results
|
||||||
added_types |= find_additions(
|
added_types |= find_additions(
|
||||||
random_context,
|
random_value,
|
||||||
execution_trailer.children[1],
|
execution_trailer.children[1],
|
||||||
add_name
|
add_name
|
||||||
)
|
)
|
||||||
@@ -761,29 +761,29 @@ class _ArrayInstance(HelperContextMixin):
|
|||||||
tuple_, = self.instance.infer_state.builtins_module.py__getattribute__('tuple')
|
tuple_, = self.instance.infer_state.builtins_module.py__getattribute__('tuple')
|
||||||
return tuple_
|
return tuple_
|
||||||
|
|
||||||
def py__iter__(self, contextualized_node=None):
|
def py__iter__(self, valueualized_node=None):
|
||||||
var_args = self.var_args
|
var_args = self.var_args
|
||||||
try:
|
try:
|
||||||
_, lazy_context = next(var_args.unpack())
|
_, lazy_value = next(var_args.unpack())
|
||||||
except StopIteration:
|
except StopIteration:
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
for lazy in lazy_context.infer().iterate():
|
for lazy in lazy_value.infer().iterate():
|
||||||
yield lazy
|
yield lazy
|
||||||
|
|
||||||
from jedi.inference import arguments
|
from jedi.inference import arguments
|
||||||
if isinstance(var_args, arguments.TreeArguments):
|
if isinstance(var_args, arguments.TreeArguments):
|
||||||
additions = _check_array_additions(var_args.context, self.instance)
|
additions = _check_array_additions(var_args.value, self.instance)
|
||||||
for addition in additions:
|
for addition in additions:
|
||||||
yield addition
|
yield addition
|
||||||
|
|
||||||
def iterate(self, contextualized_node=None, is_async=False):
|
def iterate(self, valueualized_node=None, is_async=False):
|
||||||
return self.py__iter__(contextualized_node)
|
return self.py__iter__(valueualized_node)
|
||||||
|
|
||||||
|
|
||||||
class Slice(object):
|
class Slice(object):
|
||||||
def __init__(self, context, start, stop, step):
|
def __init__(self, value, start, stop, step):
|
||||||
self._context = context
|
self._value = value
|
||||||
self._slice_object = None
|
self._slice_object = None
|
||||||
# All of them are either a Precedence or None.
|
# All of them are either a Precedence or None.
|
||||||
self._start = start
|
self._start = start
|
||||||
@@ -792,8 +792,8 @@ class Slice(object):
|
|||||||
|
|
||||||
def __getattr__(self, name):
|
def __getattr__(self, name):
|
||||||
if self._slice_object is None:
|
if self._slice_object is None:
|
||||||
context = compiled.builtin_from_name(self._context.infer_state, 'slice')
|
value = compiled.builtin_from_name(self._value.infer_state, 'slice')
|
||||||
self._slice_object, = context.execute_with_values()
|
self._slice_object, = value.execute_with_values()
|
||||||
return getattr(self._slice_object, name)
|
return getattr(self._slice_object, name)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@@ -806,14 +806,14 @@ class Slice(object):
|
|||||||
if element is None:
|
if element is None:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
result = self._context.infer_node(element)
|
result = self._value.infer_node(element)
|
||||||
if len(result) != 1:
|
if len(result) != 1:
|
||||||
# For simplicity, we want slices to be clear defined with just
|
# For simplicity, we want slices to be clear defined with just
|
||||||
# one type. Otherwise we will return an empty slice object.
|
# one type. Otherwise we will return an empty slice object.
|
||||||
raise IndexError
|
raise IndexError
|
||||||
|
|
||||||
context, = result
|
value, = result
|
||||||
return get_int_or_none(context)
|
return get_int_or_none(value)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
return slice(get(self._start), get(self._stop), get(self._step))
|
return slice(get(self._start), get(self._stop), get(self._step))
|
||||||
@@ -32,7 +32,7 @@ py__package__() -> List[str] Only on modules. For the import system.
|
|||||||
py__path__() Only on modules. For the import system.
|
py__path__() Only on modules. For the import system.
|
||||||
py__get__(call_object) Only on instances. Simulates
|
py__get__(call_object) Only on instances. Simulates
|
||||||
descriptors.
|
descriptors.
|
||||||
py__doc__() Returns the docstring for a context.
|
py__doc__() Returns the docstring for a value.
|
||||||
====================================== ========================================
|
====================================== ========================================
|
||||||
|
|
||||||
"""
|
"""
|
||||||
@@ -42,47 +42,47 @@ from jedi.parser_utils import get_cached_parent_scope
|
|||||||
from jedi.inference.cache import infer_state_method_cache, CachedMetaClass, \
|
from jedi.inference.cache import infer_state_method_cache, CachedMetaClass, \
|
||||||
infer_state_method_generator_cache
|
infer_state_method_generator_cache
|
||||||
from jedi.inference import compiled
|
from jedi.inference import compiled
|
||||||
from jedi.inference.lazy_context import LazyKnownContexts
|
from jedi.inference.lazy_value import LazyKnownContexts
|
||||||
from jedi.inference.filters import ParserTreeFilter
|
from jedi.inference.filters import ParserTreeFilter
|
||||||
from jedi.inference.names import TreeNameDefinition, ContextName
|
from jedi.inference.names import TreeNameDefinition, ContextName
|
||||||
from jedi.inference.arguments import unpack_arglist, ValuesArguments
|
from jedi.inference.arguments import unpack_arglist, ValuesArguments
|
||||||
from jedi.inference.base_value import ContextSet, iterator_to_context_set, \
|
from jedi.inference.base_value import ContextSet, iterator_to_value_set, \
|
||||||
NO_CONTEXTS
|
NO_CONTEXTS
|
||||||
from jedi.inference.context.function import FunctionAndClassBase
|
from jedi.inference.value.function import FunctionAndClassBase
|
||||||
from jedi.plugins import plugin_manager
|
from jedi.plugins import plugin_manager
|
||||||
|
|
||||||
|
|
||||||
def apply_py__get__(context, instance, class_context):
|
def apply_py__get__(value, instance, class_value):
|
||||||
try:
|
try:
|
||||||
method = context.py__get__
|
method = value.py__get__
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
yield context
|
yield value
|
||||||
else:
|
else:
|
||||||
for descriptor_context in method(instance, class_context):
|
for descriptor_value in method(instance, class_value):
|
||||||
yield descriptor_context
|
yield descriptor_value
|
||||||
|
|
||||||
|
|
||||||
class ClassName(TreeNameDefinition):
|
class ClassName(TreeNameDefinition):
|
||||||
def __init__(self, parent_context, tree_name, name_context, apply_decorators):
|
def __init__(self, parent_value, tree_name, name_value, apply_decorators):
|
||||||
super(ClassName, self).__init__(parent_context, tree_name)
|
super(ClassName, self).__init__(parent_value, tree_name)
|
||||||
self._name_context = name_context
|
self._name_value = name_value
|
||||||
self._apply_decorators = apply_decorators
|
self._apply_decorators = apply_decorators
|
||||||
|
|
||||||
@iterator_to_context_set
|
@iterator_to_value_set
|
||||||
def infer(self):
|
def infer(self):
|
||||||
# We're using a different context to infer, so we cannot call super().
|
# We're using a different value to infer, so we cannot call super().
|
||||||
from jedi.inference.syntax_tree import tree_name_to_contexts
|
from jedi.inference.syntax_tree import tree_name_to_values
|
||||||
inferred = tree_name_to_contexts(
|
inferred = tree_name_to_values(
|
||||||
self.parent_context.infer_state, self._name_context, self.tree_name)
|
self.parent_value.infer_state, self._name_value, self.tree_name)
|
||||||
|
|
||||||
for result_context in inferred:
|
for result_value in inferred:
|
||||||
if self._apply_decorators:
|
if self._apply_decorators:
|
||||||
for c in apply_py__get__(result_context,
|
for c in apply_py__get__(result_value,
|
||||||
instance=None,
|
instance=None,
|
||||||
class_context=self.parent_context):
|
class_value=self.parent_value):
|
||||||
yield c
|
yield c
|
||||||
else:
|
else:
|
||||||
yield result_context
|
yield result_value
|
||||||
|
|
||||||
|
|
||||||
class ClassFilter(ParserTreeFilter):
|
class ClassFilter(ParserTreeFilter):
|
||||||
@@ -95,9 +95,9 @@ class ClassFilter(ParserTreeFilter):
|
|||||||
def _convert_names(self, names):
|
def _convert_names(self, names):
|
||||||
return [
|
return [
|
||||||
self.name_class(
|
self.name_class(
|
||||||
parent_context=self.context,
|
parent_value=self.value,
|
||||||
tree_name=name,
|
tree_name=name,
|
||||||
name_context=self._node_context,
|
name_value=self._node_value,
|
||||||
apply_decorators=not self._is_instance,
|
apply_decorators=not self._is_instance,
|
||||||
) for name in names
|
) for name in names
|
||||||
]
|
]
|
||||||
@@ -105,7 +105,7 @@ class ClassFilter(ParserTreeFilter):
|
|||||||
def _equals_origin_scope(self):
|
def _equals_origin_scope(self):
|
||||||
node = self._origin_scope
|
node = self._origin_scope
|
||||||
while node is not None:
|
while node is not None:
|
||||||
if node == self._parser_scope or node == self.context:
|
if node == self._parser_scope or node == self.value:
|
||||||
return True
|
return True
|
||||||
node = get_cached_parent_scope(self._used_names, node)
|
node = get_cached_parent_scope(self._used_names, node)
|
||||||
return False
|
return False
|
||||||
@@ -138,10 +138,10 @@ class ClassMixin(object):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
def py__call__(self, arguments=None):
|
def py__call__(self, arguments=None):
|
||||||
from jedi.inference.context import TreeInstance
|
from jedi.inference.value import TreeInstance
|
||||||
if arguments is None:
|
if arguments is None:
|
||||||
arguments = ValuesArguments([])
|
arguments = ValuesArguments([])
|
||||||
return ContextSet([TreeInstance(self.infer_state, self.parent_context, self, arguments)])
|
return ContextSet([TreeInstance(self.infer_state, self.parent_value, self, arguments)])
|
||||||
|
|
||||||
def py__class__(self):
|
def py__class__(self):
|
||||||
return compiled.builtin_from_name(self.infer_state, u'type')
|
return compiled.builtin_from_name(self.infer_state, u'type')
|
||||||
@@ -154,9 +154,9 @@ class ClassMixin(object):
|
|||||||
return self.name.string_name
|
return self.name.string_name
|
||||||
|
|
||||||
def get_param_names(self):
|
def get_param_names(self):
|
||||||
for context_ in self.py__getattribute__(u'__init__'):
|
for value_ in self.py__getattribute__(u'__init__'):
|
||||||
if context_.is_function():
|
if value_.is_function():
|
||||||
return list(context_.get_param_names())[1:]
|
return list(value_.get_param_names())[1:]
|
||||||
return []
|
return []
|
||||||
|
|
||||||
@infer_state_method_generator_cache()
|
@infer_state_method_generator_cache()
|
||||||
@@ -208,7 +208,7 @@ class ClassMixin(object):
|
|||||||
yield filter
|
yield filter
|
||||||
else:
|
else:
|
||||||
yield ClassFilter(
|
yield ClassFilter(
|
||||||
self.infer_state, self, node_context=cls,
|
self.infer_state, self, node_value=cls,
|
||||||
origin_scope=origin_scope,
|
origin_scope=origin_scope,
|
||||||
is_instance=is_instance
|
is_instance=is_instance
|
||||||
)
|
)
|
||||||
@@ -231,7 +231,7 @@ class ClassMixin(object):
|
|||||||
def get_global_filter(self, until_position=None, origin_scope=None):
|
def get_global_filter(self, until_position=None, origin_scope=None):
|
||||||
return ParserTreeFilter(
|
return ParserTreeFilter(
|
||||||
self.infer_state,
|
self.infer_state,
|
||||||
context=self,
|
value=self,
|
||||||
until_position=until_position,
|
until_position=until_position,
|
||||||
origin_scope=origin_scope
|
origin_scope=origin_scope
|
||||||
)
|
)
|
||||||
@@ -252,7 +252,7 @@ class ClassContext(use_metaclass(CachedMetaClass, ClassMixin, FunctionAndClassBa
|
|||||||
continue # These are not relevant for this search.
|
continue # These are not relevant for this search.
|
||||||
|
|
||||||
from jedi.inference.gradual.annotation import find_unknown_type_vars
|
from jedi.inference.gradual.annotation import find_unknown_type_vars
|
||||||
for type_var in find_unknown_type_vars(self.parent_context, node):
|
for type_var in find_unknown_type_vars(self.parent_value, node):
|
||||||
if type_var not in found:
|
if type_var not in found:
|
||||||
# The order matters and it's therefore a list.
|
# The order matters and it's therefore a list.
|
||||||
found.append(type_var)
|
found.append(type_var)
|
||||||
@@ -262,7 +262,7 @@ class ClassContext(use_metaclass(CachedMetaClass, ClassMixin, FunctionAndClassBa
|
|||||||
arglist = self.tree_node.get_super_arglist()
|
arglist = self.tree_node.get_super_arglist()
|
||||||
if arglist:
|
if arglist:
|
||||||
from jedi.inference import arguments
|
from jedi.inference import arguments
|
||||||
return arguments.TreeArguments(self.infer_state, self.parent_context, arglist)
|
return arguments.TreeArguments(self.infer_state, self.parent_value, arglist)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@infer_state_method_cache(default=())
|
@infer_state_method_cache(default=())
|
||||||
@@ -274,23 +274,23 @@ class ClassContext(use_metaclass(CachedMetaClass, ClassMixin, FunctionAndClassBa
|
|||||||
return lst
|
return lst
|
||||||
|
|
||||||
if self.py__name__() == 'object' \
|
if self.py__name__() == 'object' \
|
||||||
and self.parent_context == self.infer_state.builtins_module:
|
and self.parent_value == self.infer_state.builtins_module:
|
||||||
return []
|
return []
|
||||||
return [LazyKnownContexts(
|
return [LazyKnownContexts(
|
||||||
self.infer_state.builtins_module.py__getattribute__('object')
|
self.infer_state.builtins_module.py__getattribute__('object')
|
||||||
)]
|
)]
|
||||||
|
|
||||||
def py__getitem__(self, index_context_set, contextualized_node):
|
def py__getitem__(self, index_value_set, valueualized_node):
|
||||||
from jedi.inference.gradual.typing import LazyGenericClass
|
from jedi.inference.gradual.typing import LazyGenericClass
|
||||||
if not index_context_set:
|
if not index_value_set:
|
||||||
return ContextSet([self])
|
return ContextSet([self])
|
||||||
return ContextSet(
|
return ContextSet(
|
||||||
LazyGenericClass(
|
LazyGenericClass(
|
||||||
self,
|
self,
|
||||||
index_context,
|
index_value,
|
||||||
context_of_index=contextualized_node.context,
|
value_of_index=valueualized_node.value,
|
||||||
)
|
)
|
||||||
for index_context in index_context_set
|
for index_value in index_value_set
|
||||||
)
|
)
|
||||||
|
|
||||||
def define_generics(self, type_var_dict):
|
def define_generics(self, type_var_dict):
|
||||||
@@ -326,15 +326,15 @@ class ClassContext(use_metaclass(CachedMetaClass, ClassMixin, FunctionAndClassBa
|
|||||||
args = self._get_bases_arguments()
|
args = self._get_bases_arguments()
|
||||||
if args is not None:
|
if args is not None:
|
||||||
m = [value for key, value in args.unpack() if key == 'metaclass']
|
m = [value for key, value in args.unpack() if key == 'metaclass']
|
||||||
metaclasses = ContextSet.from_sets(lazy_context.infer() for lazy_context in m)
|
metaclasses = ContextSet.from_sets(lazy_value.infer() for lazy_value in m)
|
||||||
metaclasses = ContextSet(m for m in metaclasses if m.is_class())
|
metaclasses = ContextSet(m for m in metaclasses if m.is_class())
|
||||||
if metaclasses:
|
if metaclasses:
|
||||||
return metaclasses
|
return metaclasses
|
||||||
|
|
||||||
for lazy_base in self.py__bases__():
|
for lazy_base in self.py__bases__():
|
||||||
for context in lazy_base.infer():
|
for value in lazy_base.infer():
|
||||||
if context.is_class():
|
if value.is_class():
|
||||||
contexts = context.get_metaclasses()
|
values = value.get_metaclasses()
|
||||||
if contexts:
|
if values:
|
||||||
return contexts
|
return values
|
||||||
return NO_CONTEXTS
|
return NO_CONTEXTS
|
||||||
@@ -8,7 +8,7 @@ from jedi.inference.filters import GlobalNameFilter, ParserTreeFilter, DictFilte
|
|||||||
from jedi.inference import compiled
|
from jedi.inference import compiled
|
||||||
from jedi.inference.base_value import TreeContext
|
from jedi.inference.base_value import TreeContext
|
||||||
from jedi.inference.names import SubModuleName
|
from jedi.inference.names import SubModuleName
|
||||||
from jedi.inference.helpers import contexts_from_qualified_names
|
from jedi.inference.helpers import values_from_qualified_names
|
||||||
from jedi.inference.compiled import create_simple_object
|
from jedi.inference.compiled import create_simple_object
|
||||||
from jedi.inference.base_value import ContextSet
|
from jedi.inference.base_value import ContextSet
|
||||||
|
|
||||||
@@ -20,27 +20,27 @@ class _ModuleAttributeName(AbstractNameDefinition):
|
|||||||
api_type = u'instance'
|
api_type = u'instance'
|
||||||
|
|
||||||
def __init__(self, parent_module, string_name, string_value=None):
|
def __init__(self, parent_module, string_name, string_value=None):
|
||||||
self.parent_context = parent_module
|
self.parent_value = parent_module
|
||||||
self.string_name = string_name
|
self.string_name = string_name
|
||||||
self._string_value = string_value
|
self._string_value = string_value
|
||||||
|
|
||||||
def infer(self):
|
def infer(self):
|
||||||
if self._string_value is not None:
|
if self._string_value is not None:
|
||||||
s = self._string_value
|
s = self._string_value
|
||||||
if self.parent_context.infer_state.environment.version_info.major == 2 \
|
if self.parent_value.infer_state.environment.version_info.major == 2 \
|
||||||
and not isinstance(s, bytes):
|
and not isinstance(s, bytes):
|
||||||
s = s.encode('utf-8')
|
s = s.encode('utf-8')
|
||||||
return ContextSet([
|
return ContextSet([
|
||||||
create_simple_object(self.parent_context.infer_state, s)
|
create_simple_object(self.parent_value.infer_state, s)
|
||||||
])
|
])
|
||||||
return compiled.get_string_context_set(self.parent_context.infer_state)
|
return compiled.get_string_value_set(self.parent_value.infer_state)
|
||||||
|
|
||||||
|
|
||||||
class ModuleName(ContextNameMixin, AbstractNameDefinition):
|
class ModuleName(ContextNameMixin, AbstractNameDefinition):
|
||||||
start_pos = 1, 0
|
start_pos = 1, 0
|
||||||
|
|
||||||
def __init__(self, context, name):
|
def __init__(self, value, name):
|
||||||
self._context = context
|
self._value = value
|
||||||
self._name = name
|
self._name = name
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@@ -102,7 +102,7 @@ class ModuleMixin(SubModuleDictMixin):
|
|||||||
yield MergedFilter(
|
yield MergedFilter(
|
||||||
ParserTreeFilter(
|
ParserTreeFilter(
|
||||||
self.infer_state,
|
self.infer_state,
|
||||||
context=self,
|
value=self,
|
||||||
until_position=until_position,
|
until_position=until_position,
|
||||||
origin_scope=origin_scope
|
origin_scope=origin_scope
|
||||||
),
|
),
|
||||||
@@ -114,7 +114,7 @@ class ModuleMixin(SubModuleDictMixin):
|
|||||||
yield star_filter
|
yield star_filter
|
||||||
|
|
||||||
def py__class__(self):
|
def py__class__(self):
|
||||||
c, = contexts_from_qualified_names(self.infer_state, u'types', u'ModuleType')
|
c, = values_from_qualified_names(self.infer_state, u'types', u'ModuleType')
|
||||||
return c
|
return c
|
||||||
|
|
||||||
def is_module(self):
|
def is_module(self):
|
||||||
@@ -168,7 +168,7 @@ class ModuleMixin(SubModuleDictMixin):
|
|||||||
new = Importer(
|
new = Importer(
|
||||||
self.infer_state,
|
self.infer_state,
|
||||||
import_path=i.get_paths()[-1],
|
import_path=i.get_paths()[-1],
|
||||||
module_context=self,
|
module_value=self,
|
||||||
level=i.level
|
level=i.level
|
||||||
).follow()
|
).follow()
|
||||||
|
|
||||||
@@ -182,19 +182,19 @@ class ModuleMixin(SubModuleDictMixin):
|
|||||||
"""
|
"""
|
||||||
A module doesn't have a qualified name, but it's important to note that
|
A module doesn't have a qualified name, but it's important to note that
|
||||||
it's reachable and not `None`. With this information we can add
|
it's reachable and not `None`. With this information we can add
|
||||||
qualified names on top for all context children.
|
qualified names on top for all value children.
|
||||||
"""
|
"""
|
||||||
return ()
|
return ()
|
||||||
|
|
||||||
|
|
||||||
class ModuleContext(ModuleMixin, TreeContext):
|
class ModuleContext(ModuleMixin, TreeContext):
|
||||||
api_type = u'module'
|
api_type = u'module'
|
||||||
parent_context = None
|
parent_value = None
|
||||||
|
|
||||||
def __init__(self, infer_state, module_node, file_io, string_names, code_lines, is_package=False):
|
def __init__(self, infer_state, module_node, file_io, string_names, code_lines, is_package=False):
|
||||||
super(ModuleContext, self).__init__(
|
super(ModuleContext, self).__init__(
|
||||||
infer_state,
|
infer_state,
|
||||||
parent_context=None,
|
parent_value=None,
|
||||||
tree_node=module_node
|
tree_node=module_node
|
||||||
)
|
)
|
||||||
self.file_io = file_io
|
self.file_io = file_io
|
||||||
@@ -2,7 +2,7 @@ from jedi.inference.cache import infer_state_method_cache
|
|||||||
from jedi.inference.filters import DictFilter
|
from jedi.inference.filters import DictFilter
|
||||||
from jedi.inference.names import ContextNameMixin, AbstractNameDefinition
|
from jedi.inference.names import ContextNameMixin, AbstractNameDefinition
|
||||||
from jedi.inference.base_value import Context
|
from jedi.inference.base_value import Context
|
||||||
from jedi.inference.context.module import SubModuleDictMixin
|
from jedi.inference.value.module import SubModuleDictMixin
|
||||||
|
|
||||||
|
|
||||||
class ImplicitNSName(ContextNameMixin, AbstractNameDefinition):
|
class ImplicitNSName(ContextNameMixin, AbstractNameDefinition):
|
||||||
@@ -10,8 +10,8 @@ class ImplicitNSName(ContextNameMixin, AbstractNameDefinition):
|
|||||||
Accessing names for implicit namespace packages should infer to nothing.
|
Accessing names for implicit namespace packages should infer to nothing.
|
||||||
This object will prevent Jedi from raising exceptions
|
This object will prevent Jedi from raising exceptions
|
||||||
"""
|
"""
|
||||||
def __init__(self, implicit_ns_context, string_name):
|
def __init__(self, implicit_ns_value, string_name):
|
||||||
self._context = implicit_ns_context
|
self._value = implicit_ns_value
|
||||||
self.string_name = string_name
|
self.string_name = string_name
|
||||||
|
|
||||||
|
|
||||||
@@ -23,10 +23,10 @@ class ImplicitNamespaceContext(Context, SubModuleDictMixin):
|
|||||||
# folder foobar it will be available as an object:
|
# folder foobar it will be available as an object:
|
||||||
# <module 'foobar' (namespace)>.
|
# <module 'foobar' (namespace)>.
|
||||||
api_type = u'module'
|
api_type = u'module'
|
||||||
parent_context = None
|
parent_value = None
|
||||||
|
|
||||||
def __init__(self, infer_state, fullname, paths):
|
def __init__(self, infer_state, fullname, paths):
|
||||||
super(ImplicitNamespaceContext, self).__init__(infer_state, parent_context=None)
|
super(ImplicitNamespaceContext, self).__init__(infer_state, parent_value=None)
|
||||||
self.infer_state = infer_state
|
self.infer_state = infer_state
|
||||||
self._fullname = fullname
|
self._fullname = fullname
|
||||||
self._paths = paths
|
self._paths = paths
|
||||||
@@ -3,19 +3,19 @@ def import_module(callback):
|
|||||||
Handle "magic" Flask extension imports:
|
Handle "magic" Flask extension imports:
|
||||||
``flask.ext.foo`` is really ``flask_foo`` or ``flaskext.foo``.
|
``flask.ext.foo`` is really ``flask_foo`` or ``flaskext.foo``.
|
||||||
"""
|
"""
|
||||||
def wrapper(infer_state, import_names, module_context, *args, **kwargs):
|
def wrapper(infer_state, import_names, module_value, *args, **kwargs):
|
||||||
if len(import_names) == 3 and import_names[:2] == ('flask', 'ext'):
|
if len(import_names) == 3 and import_names[:2] == ('flask', 'ext'):
|
||||||
# New style.
|
# New style.
|
||||||
ipath = (u'flask_' + import_names[2]),
|
ipath = (u'flask_' + import_names[2]),
|
||||||
context_set = callback(infer_state, ipath, None, *args, **kwargs)
|
value_set = callback(infer_state, ipath, None, *args, **kwargs)
|
||||||
if context_set:
|
if value_set:
|
||||||
return context_set
|
return value_set
|
||||||
context_set = callback(infer_state, (u'flaskext',), None, *args, **kwargs)
|
value_set = callback(infer_state, (u'flaskext',), None, *args, **kwargs)
|
||||||
return callback(
|
return callback(
|
||||||
infer_state,
|
infer_state,
|
||||||
(u'flaskext', import_names[2]),
|
(u'flaskext', import_names[2]),
|
||||||
next(iter(context_set)),
|
next(iter(value_set)),
|
||||||
*args, **kwargs
|
*args, **kwargs
|
||||||
)
|
)
|
||||||
return callback(infer_state, import_names, module_context, *args, **kwargs)
|
return callback(infer_state, import_names, module_value, *args, **kwargs)
|
||||||
return wrapper
|
return wrapper
|
||||||
|
|||||||
+114
-114
@@ -20,15 +20,15 @@ from jedi.inference.arguments import ValuesArguments, \
|
|||||||
repack_with_argument_clinic, AbstractArguments, TreeArgumentsWrapper
|
repack_with_argument_clinic, AbstractArguments, TreeArgumentsWrapper
|
||||||
from jedi.inference import analysis
|
from jedi.inference import analysis
|
||||||
from jedi.inference import compiled
|
from jedi.inference import compiled
|
||||||
from jedi.inference.context.instance import BoundMethod, InstanceArguments
|
from jedi.inference.value.instance import BoundMethod, InstanceArguments
|
||||||
from jedi.inference.base_value import ContextualizedNode, \
|
from jedi.inference.base_value import ContextualizedNode, \
|
||||||
NO_CONTEXTS, ContextSet, ContextWrapper, LazyContextWrapper
|
NO_CONTEXTS, ContextSet, ContextWrapper, LazyContextWrapper
|
||||||
from jedi.inference.context import ClassContext, ModuleContext, \
|
from jedi.inference.value import ClassContext, ModuleContext, \
|
||||||
FunctionExecutionContext
|
FunctionExecutionContext
|
||||||
from jedi.inference.context.klass import ClassMixin
|
from jedi.inference.value.klass import ClassMixin
|
||||||
from jedi.inference.context.function import FunctionMixin
|
from jedi.inference.value.function import FunctionMixin
|
||||||
from jedi.inference.context import iterable
|
from jedi.inference.value import iterable
|
||||||
from jedi.inference.lazy_context import LazyTreeContext, LazyKnownContext, \
|
from jedi.inference.lazy_value import LazyTreeContext, LazyKnownContext, \
|
||||||
LazyKnownContexts
|
LazyKnownContexts
|
||||||
from jedi.inference.names import ContextName, BaseTreeParamName
|
from jedi.inference.names import ContextName, BaseTreeParamName
|
||||||
from jedi.inference.syntax_tree import is_string
|
from jedi.inference.syntax_tree import is_string
|
||||||
@@ -105,34 +105,34 @@ _NAMEDTUPLE_FIELD_TEMPLATE = '''\
|
|||||||
|
|
||||||
|
|
||||||
def execute(callback):
|
def execute(callback):
|
||||||
def wrapper(context, arguments):
|
def wrapper(value, arguments):
|
||||||
def call():
|
def call():
|
||||||
return callback(context, arguments=arguments)
|
return callback(value, arguments=arguments)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
obj_name = context.name.string_name
|
obj_name = value.name.string_name
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
if context.parent_context == context.infer_state.builtins_module:
|
if value.parent_value == value.infer_state.builtins_module:
|
||||||
module_name = 'builtins'
|
module_name = 'builtins'
|
||||||
elif context.parent_context is not None and context.parent_context.is_module():
|
elif value.parent_value is not None and value.parent_value.is_module():
|
||||||
module_name = context.parent_context.py__name__()
|
module_name = value.parent_value.py__name__()
|
||||||
else:
|
else:
|
||||||
return call()
|
return call()
|
||||||
|
|
||||||
if isinstance(context, BoundMethod):
|
if isinstance(value, BoundMethod):
|
||||||
if module_name == 'builtins':
|
if module_name == 'builtins':
|
||||||
if context.py__name__() == '__get__':
|
if value.py__name__() == '__get__':
|
||||||
if context.class_context.py__name__() == 'property':
|
if value.class_value.py__name__() == 'property':
|
||||||
return builtins_property(
|
return builtins_property(
|
||||||
context,
|
value,
|
||||||
arguments=arguments,
|
arguments=arguments,
|
||||||
callback=call,
|
callback=call,
|
||||||
)
|
)
|
||||||
elif context.py__name__() in ('deleter', 'getter', 'setter'):
|
elif value.py__name__() in ('deleter', 'getter', 'setter'):
|
||||||
if context.class_context.py__name__() == 'property':
|
if value.class_value.py__name__() == 'property':
|
||||||
return ContextSet([context.instance])
|
return ContextSet([value.instance])
|
||||||
|
|
||||||
return call()
|
return call()
|
||||||
|
|
||||||
@@ -142,7 +142,7 @@ def execute(callback):
|
|||||||
except KeyError:
|
except KeyError:
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
return func(context, arguments=arguments, callback=call)
|
return func(value, arguments=arguments, callback=call)
|
||||||
return call()
|
return call()
|
||||||
|
|
||||||
return wrapper
|
return wrapper
|
||||||
@@ -150,14 +150,14 @@ def execute(callback):
|
|||||||
|
|
||||||
def _follow_param(infer_state, arguments, index):
|
def _follow_param(infer_state, arguments, index):
|
||||||
try:
|
try:
|
||||||
key, lazy_context = list(arguments.unpack())[index]
|
key, lazy_value = list(arguments.unpack())[index]
|
||||||
except IndexError:
|
except IndexError:
|
||||||
return NO_CONTEXTS
|
return NO_CONTEXTS
|
||||||
else:
|
else:
|
||||||
return lazy_context.infer()
|
return lazy_value.infer()
|
||||||
|
|
||||||
|
|
||||||
def argument_clinic(string, want_obj=False, want_context=False,
|
def argument_clinic(string, want_obj=False, want_value=False,
|
||||||
want_arguments=False, want_infer_state=False,
|
want_arguments=False, want_infer_state=False,
|
||||||
want_callback=False):
|
want_callback=False):
|
||||||
"""
|
"""
|
||||||
@@ -173,8 +173,8 @@ def argument_clinic(string, want_obj=False, want_context=False,
|
|||||||
assert not kwargs # Python 2...
|
assert not kwargs # Python 2...
|
||||||
debug.dbg('builtin start %s' % obj, color='MAGENTA')
|
debug.dbg('builtin start %s' % obj, color='MAGENTA')
|
||||||
result = NO_CONTEXTS
|
result = NO_CONTEXTS
|
||||||
if want_context:
|
if want_value:
|
||||||
kwargs['context'] = arguments.context
|
kwargs['value'] = arguments.value
|
||||||
if want_obj:
|
if want_obj:
|
||||||
kwargs['obj'] = obj
|
kwargs['obj'] = obj
|
||||||
if want_infer_state:
|
if want_infer_state:
|
||||||
@@ -194,12 +194,12 @@ def argument_clinic(string, want_obj=False, want_context=False,
|
|||||||
@argument_clinic('obj, type, /', want_obj=True, want_arguments=True)
|
@argument_clinic('obj, type, /', want_obj=True, want_arguments=True)
|
||||||
def builtins_property(objects, types, obj, arguments):
|
def builtins_property(objects, types, obj, arguments):
|
||||||
property_args = obj.instance.var_args.unpack()
|
property_args = obj.instance.var_args.unpack()
|
||||||
key, lazy_context = next(property_args, (None, None))
|
key, lazy_value = next(property_args, (None, None))
|
||||||
if key is not None or lazy_context is None:
|
if key is not None or lazy_value is None:
|
||||||
debug.warning('property expected a first param, not %s', arguments)
|
debug.warning('property expected a first param, not %s', arguments)
|
||||||
return NO_CONTEXTS
|
return NO_CONTEXTS
|
||||||
|
|
||||||
return lazy_context.infer().py__call__(arguments=ValuesArguments([objects]))
|
return lazy_value.infer().py__call__(arguments=ValuesArguments([objects]))
|
||||||
|
|
||||||
|
|
||||||
@argument_clinic('iterator[, default], /', want_infer_state=True)
|
@argument_clinic('iterator[, default], /', want_infer_state=True)
|
||||||
@@ -252,7 +252,7 @@ class SuperInstance(LazyContextWrapper):
|
|||||||
def _get_bases(self):
|
def _get_bases(self):
|
||||||
return self._instance.py__class__().py__bases__()
|
return self._instance.py__class__().py__bases__()
|
||||||
|
|
||||||
def _get_wrapped_context(self):
|
def _get_wrapped_value(self):
|
||||||
objs = self._get_bases()[0].infer().execute_with_values()
|
objs = self._get_bases()[0].infer().execute_with_values()
|
||||||
if not objs:
|
if not objs:
|
||||||
# This is just a fallback and will only be used, if it's not
|
# This is just a fallback and will only be used, if it's not
|
||||||
@@ -267,11 +267,11 @@ class SuperInstance(LazyContextWrapper):
|
|||||||
yield f
|
yield f
|
||||||
|
|
||||||
|
|
||||||
@argument_clinic('[type[, obj]], /', want_context=True)
|
@argument_clinic('[type[, obj]], /', want_value=True)
|
||||||
def builtins_super(types, objects, context):
|
def builtins_super(types, objects, value):
|
||||||
if isinstance(context, FunctionExecutionContext):
|
if isinstance(value, FunctionExecutionContext):
|
||||||
if isinstance(context.var_args, InstanceArguments):
|
if isinstance(value.var_args, InstanceArguments):
|
||||||
instance = context.var_args.instance
|
instance = value.var_args.instance
|
||||||
# TODO if a class is given it doesn't have to be the direct super
|
# TODO if a class is given it doesn't have to be the direct super
|
||||||
# class, it can be an anecestor from long ago.
|
# class, it can be an anecestor from long ago.
|
||||||
return ContextSet({SuperInstance(instance.infer_state, instance)})
|
return ContextSet({SuperInstance(instance.infer_state, instance)})
|
||||||
@@ -285,14 +285,14 @@ class ReversedObject(AttributeOverwrite):
|
|||||||
self._iter_list = iter_list
|
self._iter_list = iter_list
|
||||||
|
|
||||||
@publish_method('__iter__')
|
@publish_method('__iter__')
|
||||||
def py__iter__(self, contextualized_node=None):
|
def py__iter__(self, valueualized_node=None):
|
||||||
return self._iter_list
|
return self._iter_list
|
||||||
|
|
||||||
@publish_method('next', python_version_match=2)
|
@publish_method('next', python_version_match=2)
|
||||||
@publish_method('__next__', python_version_match=3)
|
@publish_method('__next__', python_version_match=3)
|
||||||
def py__next__(self):
|
def py__next__(self):
|
||||||
return ContextSet.from_sets(
|
return ContextSet.from_sets(
|
||||||
lazy_context.infer() for lazy_context in self._iter_list
|
lazy_value.infer() for lazy_value in self._iter_list
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -301,11 +301,11 @@ def builtins_reversed(sequences, obj, arguments):
|
|||||||
# While we could do without this variable (just by using sequences), we
|
# While we could do without this variable (just by using sequences), we
|
||||||
# want static analysis to work well. Therefore we need to generated the
|
# want static analysis to work well. Therefore we need to generated the
|
||||||
# values again.
|
# values again.
|
||||||
key, lazy_context = next(arguments.unpack())
|
key, lazy_value = next(arguments.unpack())
|
||||||
cn = None
|
cn = None
|
||||||
if isinstance(lazy_context, LazyTreeContext):
|
if isinstance(lazy_value, LazyTreeContext):
|
||||||
# TODO access private
|
# TODO access private
|
||||||
cn = ContextualizedNode(lazy_context.context, lazy_context.data)
|
cn = ContextualizedNode(lazy_value.value, lazy_value.data)
|
||||||
ordered = list(sequences.iterate(cn))
|
ordered = list(sequences.iterate(cn))
|
||||||
|
|
||||||
# Repack iterator values and then run it the normal way. This is
|
# Repack iterator values and then run it the normal way. This is
|
||||||
@@ -336,21 +336,21 @@ def builtins_isinstance(objects, types, arguments, infer_state):
|
|||||||
if cls_or_tup.is_class():
|
if cls_or_tup.is_class():
|
||||||
bool_results.add(cls_or_tup in mro)
|
bool_results.add(cls_or_tup in mro)
|
||||||
elif cls_or_tup.name.string_name == 'tuple' \
|
elif cls_or_tup.name.string_name == 'tuple' \
|
||||||
and cls_or_tup.get_root_context() == infer_state.builtins_module:
|
and cls_or_tup.get_root_value() == infer_state.builtins_module:
|
||||||
# Check for tuples.
|
# Check for tuples.
|
||||||
classes = ContextSet.from_sets(
|
classes = ContextSet.from_sets(
|
||||||
lazy_context.infer()
|
lazy_value.infer()
|
||||||
for lazy_context in cls_or_tup.iterate()
|
for lazy_value in cls_or_tup.iterate()
|
||||||
)
|
)
|
||||||
bool_results.add(any(cls in mro for cls in classes))
|
bool_results.add(any(cls in mro for cls in classes))
|
||||||
else:
|
else:
|
||||||
_, lazy_context = list(arguments.unpack())[1]
|
_, lazy_value = list(arguments.unpack())[1]
|
||||||
if isinstance(lazy_context, LazyTreeContext):
|
if isinstance(lazy_value, LazyTreeContext):
|
||||||
node = lazy_context.data
|
node = lazy_value.data
|
||||||
message = 'TypeError: isinstance() arg 2 must be a ' \
|
message = 'TypeError: isinstance() arg 2 must be a ' \
|
||||||
'class, type, or tuple of classes and types, ' \
|
'class, type, or tuple of classes and types, ' \
|
||||||
'not %s.' % cls_or_tup
|
'not %s.' % cls_or_tup
|
||||||
analysis.add(lazy_context.context, 'type-error-isinstance', node, message)
|
analysis.add(lazy_value.value, 'type-error-isinstance', node, message)
|
||||||
|
|
||||||
return ContextSet(
|
return ContextSet(
|
||||||
compiled.builtin_from_name(infer_state, force_unicode(str(b)))
|
compiled.builtin_from_name(infer_state, force_unicode(str(b)))
|
||||||
@@ -360,10 +360,10 @@ def builtins_isinstance(objects, types, arguments, infer_state):
|
|||||||
|
|
||||||
class StaticMethodObject(AttributeOverwrite, ContextWrapper):
|
class StaticMethodObject(AttributeOverwrite, ContextWrapper):
|
||||||
def get_object(self):
|
def get_object(self):
|
||||||
return self._wrapped_context
|
return self._wrapped_value
|
||||||
|
|
||||||
def py__get__(self, instance, klass):
|
def py__get__(self, instance, klass):
|
||||||
return ContextSet([self._wrapped_context])
|
return ContextSet([self._wrapped_value])
|
||||||
|
|
||||||
|
|
||||||
@argument_clinic('sequence, /')
|
@argument_clinic('sequence, /')
|
||||||
@@ -377,12 +377,12 @@ class ClassMethodObject(AttributeOverwrite, ContextWrapper):
|
|||||||
self._function = function
|
self._function = function
|
||||||
|
|
||||||
def get_object(self):
|
def get_object(self):
|
||||||
return self._wrapped_context
|
return self._wrapped_value
|
||||||
|
|
||||||
def py__get__(self, obj, class_context):
|
def py__get__(self, obj, class_value):
|
||||||
return ContextSet([
|
return ContextSet([
|
||||||
ClassMethodGet(__get__, class_context, self._function)
|
ClassMethodGet(__get__, class_value, self._function)
|
||||||
for __get__ in self._wrapped_context.py__getattribute__('__get__')
|
for __get__ in self._wrapped_value.py__getattribute__('__get__')
|
||||||
])
|
])
|
||||||
|
|
||||||
|
|
||||||
@@ -396,7 +396,7 @@ class ClassMethodGet(AttributeOverwrite, ContextWrapper):
|
|||||||
return self._function.get_signatures()
|
return self._function.get_signatures()
|
||||||
|
|
||||||
def get_object(self):
|
def get_object(self):
|
||||||
return self._wrapped_context
|
return self._wrapped_value
|
||||||
|
|
||||||
def py__call__(self, arguments):
|
def py__call__(self, arguments):
|
||||||
return self._function.execute(ClassMethodArguments(self._class, arguments))
|
return self._function.execute(ClassMethodArguments(self._class, arguments))
|
||||||
@@ -441,18 +441,18 @@ def collections_namedtuple(obj, arguments, callback):
|
|||||||
break
|
break
|
||||||
|
|
||||||
# TODO here we only use one of the types, we should use all.
|
# TODO here we only use one of the types, we should use all.
|
||||||
param_contexts = _follow_param(infer_state, arguments, 1)
|
param_values = _follow_param(infer_state, arguments, 1)
|
||||||
if not param_contexts:
|
if not param_values:
|
||||||
return NO_CONTEXTS
|
return NO_CONTEXTS
|
||||||
_fields = list(param_contexts)[0]
|
_fields = list(param_values)[0]
|
||||||
string = get_str_or_none(_fields)
|
string = get_str_or_none(_fields)
|
||||||
if string is not None:
|
if string is not None:
|
||||||
fields = force_unicode(string).replace(',', ' ').split()
|
fields = force_unicode(string).replace(',', ' ').split()
|
||||||
elif isinstance(_fields, iterable.Sequence):
|
elif isinstance(_fields, iterable.Sequence):
|
||||||
fields = [
|
fields = [
|
||||||
force_unicode(get_str_or_none(v))
|
force_unicode(get_str_or_none(v))
|
||||||
for lazy_context in _fields.py__iter__()
|
for lazy_value in _fields.py__iter__()
|
||||||
for v in lazy_context.infer()
|
for v in lazy_value.infer()
|
||||||
]
|
]
|
||||||
fields = [f for f in fields if f is not None]
|
fields = [f for f in fields if f is not None]
|
||||||
else:
|
else:
|
||||||
@@ -472,30 +472,30 @@ def collections_namedtuple(obj, arguments, callback):
|
|||||||
# Parse source code
|
# Parse source code
|
||||||
module = infer_state.grammar.parse(code)
|
module = infer_state.grammar.parse(code)
|
||||||
generated_class = next(module.iter_classdefs())
|
generated_class = next(module.iter_classdefs())
|
||||||
parent_context = ModuleContext(
|
parent_value = ModuleContext(
|
||||||
infer_state, module,
|
infer_state, module,
|
||||||
file_io=None,
|
file_io=None,
|
||||||
string_names=None,
|
string_names=None,
|
||||||
code_lines=parso.split_lines(code, keepends=True),
|
code_lines=parso.split_lines(code, keepends=True),
|
||||||
)
|
)
|
||||||
|
|
||||||
return ContextSet([ClassContext(infer_state, parent_context, generated_class)])
|
return ContextSet([ClassContext(infer_state, parent_value, generated_class)])
|
||||||
|
|
||||||
|
|
||||||
class PartialObject(object):
|
class PartialObject(object):
|
||||||
def __init__(self, actual_context, arguments):
|
def __init__(self, actual_value, arguments):
|
||||||
self._actual_context = actual_context
|
self._actual_value = actual_value
|
||||||
self._arguments = arguments
|
self._arguments = arguments
|
||||||
|
|
||||||
def __getattr__(self, name):
|
def __getattr__(self, name):
|
||||||
return getattr(self._actual_context, name)
|
return getattr(self._actual_value, name)
|
||||||
|
|
||||||
def _get_function(self, unpacked_arguments):
|
def _get_function(self, unpacked_arguments):
|
||||||
key, lazy_context = next(unpacked_arguments, (None, None))
|
key, lazy_value = next(unpacked_arguments, (None, None))
|
||||||
if key is not None or lazy_context is None:
|
if key is not None or lazy_value is None:
|
||||||
debug.warning("Partial should have a proper function %s", self._arguments)
|
debug.warning("Partial should have a proper function %s", self._arguments)
|
||||||
return None
|
return None
|
||||||
return lazy_context.infer()
|
return lazy_value.infer()
|
||||||
|
|
||||||
def get_signatures(self):
|
def get_signatures(self):
|
||||||
unpacked_arguments = self._arguments.unpack()
|
unpacked_arguments = self._arguments.unpack()
|
||||||
@@ -543,10 +543,10 @@ class MergedPartialArguments(AbstractArguments):
|
|||||||
# Ignore this one, it's the function. It was checked before that it's
|
# Ignore this one, it's the function. It was checked before that it's
|
||||||
# there.
|
# there.
|
||||||
next(unpacked)
|
next(unpacked)
|
||||||
for key_lazy_context in unpacked:
|
for key_lazy_value in unpacked:
|
||||||
yield key_lazy_context
|
yield key_lazy_value
|
||||||
for key_lazy_context in self._call_arguments.unpack(funcdef):
|
for key_lazy_value in self._call_arguments.unpack(funcdef):
|
||||||
yield key_lazy_context
|
yield key_lazy_value
|
||||||
|
|
||||||
|
|
||||||
def functools_partial(obj, arguments, callback):
|
def functools_partial(obj, arguments, callback):
|
||||||
@@ -564,9 +564,9 @@ def _return_first_param(firsts):
|
|||||||
@argument_clinic('seq')
|
@argument_clinic('seq')
|
||||||
def _random_choice(sequences):
|
def _random_choice(sequences):
|
||||||
return ContextSet.from_sets(
|
return ContextSet.from_sets(
|
||||||
lazy_context.infer()
|
lazy_value.infer()
|
||||||
for sequence in sequences
|
for sequence in sequences
|
||||||
for lazy_context in sequence.py__iter__()
|
for lazy_value in sequence.py__iter__()
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -597,7 +597,7 @@ class DataclassWrapper(ContextWrapper, ClassMixin):
|
|||||||
else:
|
else:
|
||||||
default = annassign.children[3]
|
default = annassign.children[3]
|
||||||
param_names.append(DataclassParamName(
|
param_names.append(DataclassParamName(
|
||||||
parent_context=cls.parent_context,
|
parent_value=cls.parent_value,
|
||||||
tree_name=name.tree_name,
|
tree_name=name.tree_name,
|
||||||
annotation_node=annassign.children[1],
|
annotation_node=annassign.children[1],
|
||||||
default_node=default,
|
default_node=default,
|
||||||
@@ -606,8 +606,8 @@ class DataclassWrapper(ContextWrapper, ClassMixin):
|
|||||||
|
|
||||||
|
|
||||||
class DataclassSignature(AbstractSignature):
|
class DataclassSignature(AbstractSignature):
|
||||||
def __init__(self, context, param_names):
|
def __init__(self, value, param_names):
|
||||||
super(DataclassSignature, self).__init__(context)
|
super(DataclassSignature, self).__init__(value)
|
||||||
self._param_names = param_names
|
self._param_names = param_names
|
||||||
|
|
||||||
def get_param_names(self, resolve_stars=False):
|
def get_param_names(self, resolve_stars=False):
|
||||||
@@ -615,8 +615,8 @@ class DataclassSignature(AbstractSignature):
|
|||||||
|
|
||||||
|
|
||||||
class DataclassParamName(BaseTreeParamName):
|
class DataclassParamName(BaseTreeParamName):
|
||||||
def __init__(self, parent_context, tree_name, annotation_node, default_node):
|
def __init__(self, parent_value, tree_name, annotation_node, default_node):
|
||||||
super(DataclassParamName, self).__init__(parent_context, tree_name)
|
super(DataclassParamName, self).__init__(parent_value, tree_name)
|
||||||
self.annotation_node = annotation_node
|
self.annotation_node = annotation_node
|
||||||
self.default_node = default_node
|
self.default_node = default_node
|
||||||
|
|
||||||
@@ -627,32 +627,32 @@ class DataclassParamName(BaseTreeParamName):
|
|||||||
if self.annotation_node is None:
|
if self.annotation_node is None:
|
||||||
return NO_CONTEXTS
|
return NO_CONTEXTS
|
||||||
else:
|
else:
|
||||||
return self.parent_context.infer_node(self.annotation_node)
|
return self.parent_value.infer_node(self.annotation_node)
|
||||||
|
|
||||||
|
|
||||||
class ItemGetterCallable(ContextWrapper):
|
class ItemGetterCallable(ContextWrapper):
|
||||||
def __init__(self, instance, args_context_set):
|
def __init__(self, instance, args_value_set):
|
||||||
super(ItemGetterCallable, self).__init__(instance)
|
super(ItemGetterCallable, self).__init__(instance)
|
||||||
self._args_context_set = args_context_set
|
self._args_value_set = args_value_set
|
||||||
|
|
||||||
@repack_with_argument_clinic('item, /')
|
@repack_with_argument_clinic('item, /')
|
||||||
def py__call__(self, item_context_set):
|
def py__call__(self, item_value_set):
|
||||||
context_set = NO_CONTEXTS
|
value_set = NO_CONTEXTS
|
||||||
for args_context in self._args_context_set:
|
for args_value in self._args_value_set:
|
||||||
lazy_contexts = list(args_context.py__iter__())
|
lazy_values = list(args_value.py__iter__())
|
||||||
if len(lazy_contexts) == 1:
|
if len(lazy_values) == 1:
|
||||||
# TODO we need to add the contextualized context.
|
# TODO we need to add the valueualized value.
|
||||||
context_set |= item_context_set.get_item(lazy_contexts[0].infer(), None)
|
value_set |= item_value_set.get_item(lazy_values[0].infer(), None)
|
||||||
else:
|
else:
|
||||||
context_set |= ContextSet([iterable.FakeSequence(
|
value_set |= ContextSet([iterable.FakeSequence(
|
||||||
self._wrapped_context.infer_state,
|
self._wrapped_value.infer_state,
|
||||||
'list',
|
'list',
|
||||||
[
|
[
|
||||||
LazyKnownContexts(item_context_set.get_item(lazy_context.infer(), None))
|
LazyKnownContexts(item_value_set.get_item(lazy_value.infer(), None))
|
||||||
for lazy_context in lazy_contexts
|
for lazy_value in lazy_values
|
||||||
],
|
],
|
||||||
)])
|
)])
|
||||||
return context_set
|
return value_set
|
||||||
|
|
||||||
|
|
||||||
@argument_clinic('func, /')
|
@argument_clinic('func, /')
|
||||||
@@ -661,12 +661,12 @@ def _functools_wraps(funcs):
|
|||||||
|
|
||||||
|
|
||||||
class WrapsCallable(ContextWrapper):
|
class WrapsCallable(ContextWrapper):
|
||||||
# XXX this is not the correct wrapped context, it should be a weird
|
# XXX this is not the correct wrapped value, it should be a weird
|
||||||
# partials object, but it doesn't matter, because it's always used as a
|
# partials object, but it doesn't matter, because it's always used as a
|
||||||
# decorator anyway.
|
# decorator anyway.
|
||||||
@repack_with_argument_clinic('func, /')
|
@repack_with_argument_clinic('func, /')
|
||||||
def py__call__(self, funcs):
|
def py__call__(self, funcs):
|
||||||
return ContextSet({Wrapped(func, self._wrapped_context) for func in funcs})
|
return ContextSet({Wrapped(func, self._wrapped_value) for func in funcs})
|
||||||
|
|
||||||
|
|
||||||
class Wrapped(ContextWrapper, FunctionMixin):
|
class Wrapped(ContextWrapper, FunctionMixin):
|
||||||
@@ -683,9 +683,9 @@ class Wrapped(ContextWrapper, FunctionMixin):
|
|||||||
|
|
||||||
|
|
||||||
@argument_clinic('*args, /', want_obj=True, want_arguments=True)
|
@argument_clinic('*args, /', want_obj=True, want_arguments=True)
|
||||||
def _operator_itemgetter(args_context_set, obj, arguments):
|
def _operator_itemgetter(args_value_set, obj, arguments):
|
||||||
return ContextSet([
|
return ContextSet([
|
||||||
ItemGetterCallable(instance, args_context_set)
|
ItemGetterCallable(instance, args_value_set)
|
||||||
for instance in obj.py__call__(arguments)
|
for instance in obj.py__call__(arguments)
|
||||||
])
|
])
|
||||||
|
|
||||||
@@ -694,14 +694,14 @@ def _create_string_input_function(func):
|
|||||||
@argument_clinic('string, /', want_obj=True, want_arguments=True)
|
@argument_clinic('string, /', want_obj=True, want_arguments=True)
|
||||||
def wrapper(strings, obj, arguments):
|
def wrapper(strings, obj, arguments):
|
||||||
def iterate():
|
def iterate():
|
||||||
for context in strings:
|
for value in strings:
|
||||||
s = get_str_or_none(context)
|
s = get_str_or_none(value)
|
||||||
if s is not None:
|
if s is not None:
|
||||||
s = func(s)
|
s = func(s)
|
||||||
yield compiled.create_simple_object(context.infer_state, s)
|
yield compiled.create_simple_object(value.infer_state, s)
|
||||||
contexts = ContextSet(iterate())
|
values = ContextSet(iterate())
|
||||||
if contexts:
|
if values:
|
||||||
return contexts
|
return values
|
||||||
return obj.py__call__(arguments)
|
return obj.py__call__(arguments)
|
||||||
return wrapper
|
return wrapper
|
||||||
|
|
||||||
@@ -712,11 +712,11 @@ def _os_path_join(args_set, callback):
|
|||||||
string = u''
|
string = u''
|
||||||
sequence, = args_set
|
sequence, = args_set
|
||||||
is_first = True
|
is_first = True
|
||||||
for lazy_context in sequence.py__iter__():
|
for lazy_value in sequence.py__iter__():
|
||||||
string_contexts = lazy_context.infer()
|
string_values = lazy_value.infer()
|
||||||
if len(string_contexts) != 1:
|
if len(string_values) != 1:
|
||||||
break
|
break
|
||||||
s = get_str_or_none(next(iter(string_contexts)))
|
s = get_str_or_none(next(iter(string_values)))
|
||||||
if s is None:
|
if s is None:
|
||||||
break
|
break
|
||||||
if not is_first:
|
if not is_first:
|
||||||
@@ -792,8 +792,8 @@ def get_metaclass_filters(func):
|
|||||||
def wrapper(cls, metaclasses):
|
def wrapper(cls, metaclasses):
|
||||||
for metaclass in metaclasses:
|
for metaclass in metaclasses:
|
||||||
if metaclass.py__name__() == 'EnumMeta' \
|
if metaclass.py__name__() == 'EnumMeta' \
|
||||||
and metaclass.get_root_context().py__name__() == 'enum':
|
and metaclass.get_root_value().py__name__() == 'enum':
|
||||||
filter_ = ParserTreeFilter(cls.infer_state, context=cls)
|
filter_ = ParserTreeFilter(cls.infer_state, value=cls)
|
||||||
return [DictFilter({
|
return [DictFilter({
|
||||||
name.string_name: EnumInstance(cls, name).name for name in filter_.values()
|
name.string_name: EnumInstance(cls, name).name for name in filter_.values()
|
||||||
})]
|
})]
|
||||||
@@ -812,7 +812,7 @@ class EnumInstance(LazyContextWrapper):
|
|||||||
def name(self):
|
def name(self):
|
||||||
return ContextName(self, self._name.tree_name)
|
return ContextName(self, self._name.tree_name)
|
||||||
|
|
||||||
def _get_wrapped_context(self):
|
def _get_wrapped_value(self):
|
||||||
obj, = self._cls.execute_with_values()
|
obj, = self._cls.execute_with_values()
|
||||||
return obj
|
return obj
|
||||||
|
|
||||||
@@ -821,15 +821,15 @@ class EnumInstance(LazyContextWrapper):
|
|||||||
name=compiled.create_simple_object(self.infer_state, self._name.string_name).name,
|
name=compiled.create_simple_object(self.infer_state, self._name.string_name).name,
|
||||||
value=self._name,
|
value=self._name,
|
||||||
))
|
))
|
||||||
for f in self._get_wrapped_context().get_filters():
|
for f in self._get_wrapped_value().get_filters():
|
||||||
yield f
|
yield f
|
||||||
|
|
||||||
|
|
||||||
def tree_name_to_contexts(func):
|
def tree_name_to_values(func):
|
||||||
def wrapper(infer_state, context, tree_name):
|
def wrapper(infer_state, value, tree_name):
|
||||||
if tree_name.value == 'sep' and context.is_module() and context.py__name__() == 'os.path':
|
if tree_name.value == 'sep' and value.is_module() and value.py__name__() == 'os.path':
|
||||||
return ContextSet({
|
return ContextSet({
|
||||||
compiled.create_simple_object(infer_state, os.path.sep),
|
compiled.create_simple_object(infer_state, os.path.sep),
|
||||||
})
|
})
|
||||||
return func(infer_state, context, tree_name)
|
return func(infer_state, value, tree_name)
|
||||||
return wrapper
|
return wrapper
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
"""
|
"""
|
||||||
Special cases of completions (typically special positions that caused issues
|
Special cases of completions (typically special positions that caused issues
|
||||||
with context parsing.
|
with value parsing.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def pass_decorator(func):
|
def pass_decorator(func):
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ definition = 0
|
|||||||
str(def
|
str(def
|
||||||
|
|
||||||
|
|
||||||
# It might be hard to determine the context
|
# It might be hard to determine the value
|
||||||
class Foo(object):
|
class Foo(object):
|
||||||
@property
|
@property
|
||||||
#? ['str']
|
#? ['str']
|
||||||
|
|||||||
+9
-9
@@ -126,7 +126,7 @@ from jedi.api.classes import Definition
|
|||||||
from jedi.api.completion import get_user_scope
|
from jedi.api.completion import get_user_scope
|
||||||
from jedi import parser_utils
|
from jedi import parser_utils
|
||||||
from jedi.api.environment import get_default_environment, get_system_environment
|
from jedi.api.environment import get_default_environment, get_system_environment
|
||||||
from jedi.inference.gradual.conversion import convert_contexts
|
from jedi.inference.gradual.conversion import convert_values
|
||||||
|
|
||||||
|
|
||||||
TEST_COMPLETIONS = 0
|
TEST_COMPLETIONS = 0
|
||||||
@@ -225,14 +225,14 @@ class IntegrationTestCase(object):
|
|||||||
parser = grammar36.parse(string, start_symbol='eval_input', error_recovery=False)
|
parser = grammar36.parse(string, start_symbol='eval_input', error_recovery=False)
|
||||||
parser_utils.move(parser.get_root_node(), self.line_nr)
|
parser_utils.move(parser.get_root_node(), self.line_nr)
|
||||||
element = parser.get_root_node()
|
element = parser.get_root_node()
|
||||||
module_context = script._get_module()
|
module_value = script._get_module()
|
||||||
# The context shouldn't matter for the test results.
|
# The value shouldn't matter for the test results.
|
||||||
user_context = get_user_scope(module_context, (self.line_nr, 0))
|
user_value = get_user_scope(module_value, (self.line_nr, 0))
|
||||||
if user_context.api_type == 'function':
|
if user_value.api_type == 'function':
|
||||||
user_context = user_context.get_function_execution()
|
user_value = user_value.get_function_execution()
|
||||||
element.parent = user_context.tree_node
|
element.parent = user_value.tree_node
|
||||||
results = convert_contexts(
|
results = convert_values(
|
||||||
infer_state.infer_element(user_context, element),
|
infer_state.infer_element(user_value, element),
|
||||||
)
|
)
|
||||||
if not results:
|
if not results:
|
||||||
raise Exception('Could not resolve %s on line %s'
|
raise Exception('Could not resolve %s on line %s'
|
||||||
|
|||||||
@@ -398,7 +398,7 @@ def test_import_alias(names):
|
|||||||
n = nms[0].goto_assignments()[0]
|
n = nms[0].goto_assignments()[0]
|
||||||
assert n.name == 'json'
|
assert n.name == 'json'
|
||||||
assert n.type == 'module'
|
assert n.type == 'module'
|
||||||
assert n._name._context.tree_node.type == 'file_input'
|
assert n._name._value.tree_node.type == 'file_input'
|
||||||
|
|
||||||
assert nms[1].name == 'foo'
|
assert nms[1].name == 'foo'
|
||||||
assert nms[1].type == 'module'
|
assert nms[1].type == 'module'
|
||||||
@@ -407,7 +407,7 @@ def test_import_alias(names):
|
|||||||
assert len(ass) == 1
|
assert len(ass) == 1
|
||||||
assert ass[0].name == 'json'
|
assert ass[0].name == 'json'
|
||||||
assert ass[0].type == 'module'
|
assert ass[0].type == 'module'
|
||||||
assert ass[0]._name._context.tree_node.type == 'file_input'
|
assert ass[0]._name._value.tree_node.type == 'file_input'
|
||||||
|
|
||||||
|
|
||||||
def test_added_equals_to_params(Script):
|
def test_added_equals_to_params(Script):
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ def test_in_empty_space(Script):
|
|||||||
assert def_.name == 'X'
|
assert def_.name == 'X'
|
||||||
|
|
||||||
|
|
||||||
def test_indent_context(Script):
|
def test_indent_value(Script):
|
||||||
"""
|
"""
|
||||||
If an INDENT is the next supposed token, we should still be able to
|
If an INDENT is the next supposed token, we should still be able to
|
||||||
complete.
|
complete.
|
||||||
@@ -44,7 +44,7 @@ def test_indent_context(Script):
|
|||||||
assert comp.name == 'isinstance'
|
assert comp.name == 'isinstance'
|
||||||
|
|
||||||
|
|
||||||
def test_keyword_context(Script):
|
def test_keyword_value(Script):
|
||||||
def get_names(*args, **kwargs):
|
def get_names(*args, **kwargs):
|
||||||
return [d.name for d in Script(*args, **kwargs).completions()]
|
return [d.name for d in Script(*args, **kwargs).completions()]
|
||||||
|
|
||||||
@@ -101,8 +101,8 @@ def test_fake_subnodes(Script):
|
|||||||
for i in range(2):
|
for i in range(2):
|
||||||
completions = Script('').completions()
|
completions = Script('').completions()
|
||||||
c = get_str_completion(completions)
|
c = get_str_completion(completions)
|
||||||
str_context, = c._name.infer()
|
str_value, = c._name.infer()
|
||||||
n = len(str_context.tree_node.children[-1].children)
|
n = len(str_value.tree_node.children[-1].children)
|
||||||
if i == 0:
|
if i == 0:
|
||||||
limit = n
|
limit = n
|
||||||
else:
|
else:
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import pytest
|
|||||||
|
|
||||||
import jedi
|
import jedi
|
||||||
from jedi._compatibility import is_py3, py_version
|
from jedi._compatibility import is_py3, py_version
|
||||||
from jedi.inference.compiled import mixed, context
|
from jedi.inference.compiled import mixed, value
|
||||||
from importlib import import_module
|
from importlib import import_module
|
||||||
|
|
||||||
if py_version > 30:
|
if py_version > 30:
|
||||||
@@ -101,8 +101,8 @@ def test_side_effect_completion():
|
|||||||
side_effect = get_completion('SideEffectContainer', _GlobalNameSpace.__dict__)
|
side_effect = get_completion('SideEffectContainer', _GlobalNameSpace.__dict__)
|
||||||
|
|
||||||
# It's a class that contains MixedObject.
|
# It's a class that contains MixedObject.
|
||||||
context, = side_effect._name.infer()
|
value, = side_effect._name.infer()
|
||||||
assert isinstance(context, mixed.MixedObject)
|
assert isinstance(value, mixed.MixedObject)
|
||||||
foo = get_completion('SideEffectContainer.foo', _GlobalNameSpace.__dict__)
|
foo = get_completion('SideEffectContainer.foo', _GlobalNameSpace.__dict__)
|
||||||
assert foo.name == 'foo'
|
assert foo.name == 'foo'
|
||||||
|
|
||||||
|
|||||||
@@ -10,8 +10,8 @@ from ..helpers import cwd_at
|
|||||||
|
|
||||||
|
|
||||||
def check_module_test(Script, code):
|
def check_module_test(Script, code):
|
||||||
module_context = Script(code)._get_module()
|
module_value = Script(code)._get_module()
|
||||||
return check_sys_path_modifications(module_context)
|
return check_sys_path_modifications(module_value)
|
||||||
|
|
||||||
|
|
||||||
@cwd_at('test/examples/buildout_project/src/proj_name')
|
@cwd_at('test/examples/buildout_project/src/proj_name')
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import pytest
|
|||||||
|
|
||||||
from jedi.inference import compiled
|
from jedi.inference import compiled
|
||||||
from jedi.inference.compiled.access import DirectObjectAccess
|
from jedi.inference.compiled.access import DirectObjectAccess
|
||||||
from jedi.inference.gradual.conversion import _stub_to_python_context_set
|
from jedi.inference.gradual.conversion import _stub_to_python_value_set
|
||||||
|
|
||||||
|
|
||||||
def test_simple(infer_state, environment):
|
def test_simple(infer_state, environment):
|
||||||
@@ -34,7 +34,7 @@ def test_next_docstr(infer_state):
|
|||||||
next_ = compiled.builtin_from_name(infer_state, u'next')
|
next_ = compiled.builtin_from_name(infer_state, u'next')
|
||||||
assert next_.tree_node is not None
|
assert next_.tree_node is not None
|
||||||
assert next_.py__doc__() == '' # It's a stub
|
assert next_.py__doc__() == '' # It's a stub
|
||||||
for non_stub in _stub_to_python_context_set(next_):
|
for non_stub in _stub_to_python_value_set(next_):
|
||||||
assert non_stub.py__doc__() == next.__doc__
|
assert non_stub.py__doc__() == next.__doc__
|
||||||
|
|
||||||
|
|
||||||
@@ -44,7 +44,7 @@ def test_parse_function_doc_illegal_docstr():
|
|||||||
|
|
||||||
doesn't have a closing bracket.
|
doesn't have a closing bracket.
|
||||||
"""
|
"""
|
||||||
assert ('', '') == compiled.context._parse_function_doc(docstr)
|
assert ('', '') == compiled.value._parse_function_doc(docstr)
|
||||||
|
|
||||||
|
|
||||||
def test_doc(infer_state):
|
def test_doc(infer_state):
|
||||||
@@ -122,7 +122,7 @@ def _return_int():
|
|||||||
('ret_int', '_return_int', 'test.test_inference.test_compiled'),
|
('ret_int', '_return_int', 'test.test_inference.test_compiled'),
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
def test_parent_context(same_process_infer_state, attribute, expected_name, expected_parent):
|
def test_parent_value(same_process_infer_state, attribute, expected_name, expected_parent):
|
||||||
import decimal
|
import decimal
|
||||||
|
|
||||||
class C:
|
class C:
|
||||||
@@ -140,11 +140,11 @@ def test_parent_context(same_process_infer_state, attribute, expected_name, expe
|
|||||||
)
|
)
|
||||||
x, = o.py__getattribute__(attribute)
|
x, = o.py__getattribute__(attribute)
|
||||||
assert x.py__name__() == expected_name
|
assert x.py__name__() == expected_name
|
||||||
module_name = x.parent_context.py__name__()
|
module_name = x.parent_value.py__name__()
|
||||||
if module_name == '__builtin__':
|
if module_name == '__builtin__':
|
||||||
module_name = 'builtins' # Python 2
|
module_name = 'builtins' # Python 2
|
||||||
assert module_name == expected_parent
|
assert module_name == expected_parent
|
||||||
assert x.parent_context.parent_context is None
|
assert x.parent_value.parent_value is None
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.skipif(sys.version_info[0] == 2, reason="Ignore Python 2, because EOL")
|
@pytest.mark.skipif(sys.version_info[0] == 2, reason="Ignore Python 2, because EOL")
|
||||||
|
|||||||
@@ -13,9 +13,9 @@ def test_module_attributes(Script):
|
|||||||
def test_module__file__(Script, environment):
|
def test_module__file__(Script, environment):
|
||||||
assert not Script('__file__').goto_definitions()
|
assert not Script('__file__').goto_definitions()
|
||||||
def_, = Script('__file__', path='example.py').goto_definitions()
|
def_, = Script('__file__', path='example.py').goto_definitions()
|
||||||
value = force_unicode(def_._name._context.get_safe_value())
|
value = force_unicode(def_._name._value.get_safe_value())
|
||||||
assert value.endswith('example.py')
|
assert value.endswith('example.py')
|
||||||
|
|
||||||
def_, = Script('import antigravity; antigravity.__file__').goto_definitions()
|
def_, = Script('import antigravity; antigravity.__file__').goto_definitions()
|
||||||
value = force_unicode(def_._name._context.get_safe_value())
|
value = force_unicode(def_._name._value.get_safe_value())
|
||||||
assert value.endswith('.py')
|
assert value.endswith('.py')
|
||||||
|
|||||||
@@ -3,8 +3,8 @@ import os
|
|||||||
import pytest
|
import pytest
|
||||||
from parso.utils import PythonVersionInfo
|
from parso.utils import PythonVersionInfo
|
||||||
|
|
||||||
from jedi.inference.gradual import typeshed, stub_context
|
from jedi.inference.gradual import typeshed, stub_value
|
||||||
from jedi.inference.context import TreeInstance, BoundMethod, FunctionContext, \
|
from jedi.inference.value import TreeInstance, BoundMethod, FunctionContext, \
|
||||||
MethodContext, ClassContext
|
MethodContext, ClassContext
|
||||||
|
|
||||||
TYPESHED_PYTHON3 = os.path.join(typeshed.TYPESHED_PATH, 'stdlib', '3')
|
TYPESHED_PYTHON3 = os.path.join(typeshed.TYPESHED_PATH, 'stdlib', '3')
|
||||||
@@ -47,15 +47,15 @@ def test_get_stub_files():
|
|||||||
def test_function(Script, environment):
|
def test_function(Script, environment):
|
||||||
code = 'import threading; threading.current_thread'
|
code = 'import threading; threading.current_thread'
|
||||||
def_, = Script(code).goto_definitions()
|
def_, = Script(code).goto_definitions()
|
||||||
context = def_._name._context
|
value = def_._name._value
|
||||||
assert isinstance(context, FunctionContext), context
|
assert isinstance(value, FunctionContext), value
|
||||||
|
|
||||||
def_, = Script(code + '()').goto_definitions()
|
def_, = Script(code + '()').goto_definitions()
|
||||||
context = def_._name._context
|
value = def_._name._value
|
||||||
assert isinstance(context, TreeInstance)
|
assert isinstance(value, TreeInstance)
|
||||||
|
|
||||||
def_, = Script('import threading; threading.Thread').goto_definitions()
|
def_, = Script('import threading; threading.Thread').goto_definitions()
|
||||||
assert isinstance(def_._name._context, ClassContext), def_
|
assert isinstance(def_._name._value, ClassContext), def_
|
||||||
|
|
||||||
|
|
||||||
def test_keywords_variable(Script):
|
def test_keywords_variable(Script):
|
||||||
@@ -69,33 +69,33 @@ def test_keywords_variable(Script):
|
|||||||
|
|
||||||
def test_class(Script):
|
def test_class(Script):
|
||||||
def_, = Script('import threading; threading.Thread').goto_definitions()
|
def_, = Script('import threading; threading.Thread').goto_definitions()
|
||||||
context = def_._name._context
|
value = def_._name._value
|
||||||
assert isinstance(context, ClassContext), context
|
assert isinstance(value, ClassContext), value
|
||||||
|
|
||||||
|
|
||||||
def test_instance(Script):
|
def test_instance(Script):
|
||||||
def_, = Script('import threading; threading.Thread()').goto_definitions()
|
def_, = Script('import threading; threading.Thread()').goto_definitions()
|
||||||
context = def_._name._context
|
value = def_._name._value
|
||||||
assert isinstance(context, TreeInstance)
|
assert isinstance(value, TreeInstance)
|
||||||
|
|
||||||
|
|
||||||
def test_class_function(Script):
|
def test_class_function(Script):
|
||||||
def_, = Script('import threading; threading.Thread.getName').goto_definitions()
|
def_, = Script('import threading; threading.Thread.getName').goto_definitions()
|
||||||
context = def_._name._context
|
value = def_._name._value
|
||||||
assert isinstance(context, MethodContext), context
|
assert isinstance(value, MethodContext), value
|
||||||
|
|
||||||
|
|
||||||
def test_method(Script):
|
def test_method(Script):
|
||||||
code = 'import threading; threading.Thread().getName'
|
code = 'import threading; threading.Thread().getName'
|
||||||
def_, = Script(code).goto_definitions()
|
def_, = Script(code).goto_definitions()
|
||||||
context = def_._name._context
|
value = def_._name._value
|
||||||
assert isinstance(context, BoundMethod), context
|
assert isinstance(value, BoundMethod), value
|
||||||
assert isinstance(context._wrapped_context, MethodContext), context
|
assert isinstance(value._wrapped_value, MethodContext), value
|
||||||
|
|
||||||
def_, = Script(code + '()').goto_definitions()
|
def_, = Script(code + '()').goto_definitions()
|
||||||
context = def_._name._context
|
value = def_._name._value
|
||||||
assert isinstance(context, TreeInstance)
|
assert isinstance(value, TreeInstance)
|
||||||
assert context.class_context.py__name__() == 'str'
|
assert value.class_value.py__name__() == 'str'
|
||||||
|
|
||||||
|
|
||||||
def test_sys_exc_info(Script):
|
def test_sys_exc_info(Script):
|
||||||
@@ -125,7 +125,7 @@ def test_sys_getwindowsversion(Script, environment):
|
|||||||
def test_sys_hexversion(Script):
|
def test_sys_hexversion(Script):
|
||||||
script = Script('import sys; sys.hexversion')
|
script = Script('import sys; sys.hexversion')
|
||||||
def_, = script.completions()
|
def_, = script.completions()
|
||||||
assert isinstance(def_._name, stub_context._StubName), def_._name
|
assert isinstance(def_._name, stub_value._StubName), def_._name
|
||||||
assert typeshed.TYPESHED_PATH in def_.module_path
|
assert typeshed.TYPESHED_PATH in def_.module_path
|
||||||
def_, = script.goto_definitions()
|
def_, = script.goto_definitions()
|
||||||
assert def_.name == 'int'
|
assert def_.name == 'int'
|
||||||
@@ -134,8 +134,8 @@ def test_sys_hexversion(Script):
|
|||||||
def test_math(Script):
|
def test_math(Script):
|
||||||
def_, = Script('import math; math.acos()').goto_definitions()
|
def_, = Script('import math; math.acos()').goto_definitions()
|
||||||
assert def_.name == 'float'
|
assert def_.name == 'float'
|
||||||
context = def_._name._context
|
value = def_._name._value
|
||||||
assert context
|
assert value
|
||||||
|
|
||||||
|
|
||||||
def test_type_var(Script):
|
def test_type_var(Script):
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ from jedi._compatibility import find_module_py33, find_module
|
|||||||
from jedi.inference import compiled
|
from jedi.inference import compiled
|
||||||
from jedi.inference import imports
|
from jedi.inference import imports
|
||||||
from jedi.api.project import Project
|
from jedi.api.project import Project
|
||||||
from jedi.inference.gradual.conversion import _stub_to_python_context_set
|
from jedi.inference.gradual.conversion import _stub_to_python_value_set
|
||||||
from ..helpers import cwd_at, get_example_dir, test_dir, root_dir
|
from ..helpers import cwd_at, get_example_dir, test_dir, root_dir
|
||||||
|
|
||||||
THIS_DIR = os.path.dirname(__file__)
|
THIS_DIR = os.path.dirname(__file__)
|
||||||
@@ -88,12 +88,12 @@ def test_correct_zip_package_behavior(Script, infer_state, environment, code,
|
|||||||
file, package, path, skip_python2):
|
file, package, path, skip_python2):
|
||||||
sys_path = environment.get_sys_path() + [pkg_zip_path]
|
sys_path = environment.get_sys_path() + [pkg_zip_path]
|
||||||
pkg, = Script(code, sys_path=sys_path).goto_definitions()
|
pkg, = Script(code, sys_path=sys_path).goto_definitions()
|
||||||
context, = pkg._name.infer()
|
value, = pkg._name.infer()
|
||||||
assert context.py__file__() == os.path.join(pkg_zip_path, 'pkg', file)
|
assert value.py__file__() == os.path.join(pkg_zip_path, 'pkg', file)
|
||||||
assert '.'.join(context.py__package__()) == package
|
assert '.'.join(value.py__package__()) == package
|
||||||
assert context.is_package is (path is not None)
|
assert value.is_package is (path is not None)
|
||||||
if path is not None:
|
if path is not None:
|
||||||
assert context.py__path__() == [os.path.join(pkg_zip_path, path)]
|
assert value.py__path__() == [os.path.join(pkg_zip_path, path)]
|
||||||
|
|
||||||
|
|
||||||
def test_find_module_not_package_zipped(Script, infer_state, environment):
|
def test_find_module_not_package_zipped(Script, infer_state, environment):
|
||||||
@@ -156,8 +156,8 @@ def test_not_importable_file(Script):
|
|||||||
def test_import_unique(Script):
|
def test_import_unique(Script):
|
||||||
src = "import os; os.path"
|
src = "import os; os.path"
|
||||||
defs = Script(src, path='example.py').goto_definitions()
|
defs = Script(src, path='example.py').goto_definitions()
|
||||||
parent_contexts = [d._name._context for d in defs]
|
parent_values = [d._name._value for d in defs]
|
||||||
assert len(parent_contexts) == len(set(parent_contexts))
|
assert len(parent_values) == len(set(parent_values))
|
||||||
|
|
||||||
|
|
||||||
def test_cache_works_with_sys_path_param(Script, tmpdir):
|
def test_cache_works_with_sys_path_param(Script, tmpdir):
|
||||||
@@ -300,8 +300,8 @@ def test_compiled_import_none(monkeypatch, Script):
|
|||||||
monkeypatch.setattr(compiled, 'load_module', lambda *args, **kwargs: None)
|
monkeypatch.setattr(compiled, 'load_module', lambda *args, **kwargs: None)
|
||||||
def_, = script.goto_definitions()
|
def_, = script.goto_definitions()
|
||||||
assert def_.type == 'module'
|
assert def_.type == 'module'
|
||||||
context, = def_._name.infer()
|
value, = def_._name.infer()
|
||||||
assert not _stub_to_python_context_set(context)
|
assert not _stub_to_python_value_set(value)
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
import pytest
|
import pytest
|
||||||
from jedi.inference.context import TreeInstance
|
from jedi.inference.value import TreeInstance
|
||||||
|
|
||||||
|
|
||||||
def _infer_literal(Script, code, is_fstring=False):
|
def _infer_literal(Script, code, is_fstring=False):
|
||||||
def_, = Script(code).goto_definitions()
|
def_, = Script(code).goto_definitions()
|
||||||
if is_fstring:
|
if is_fstring:
|
||||||
assert def_.name == 'str'
|
assert def_.name == 'str'
|
||||||
assert isinstance(def_._name._context, TreeInstance)
|
assert isinstance(def_._name._value, TreeInstance)
|
||||||
return ''
|
return ''
|
||||||
else:
|
else:
|
||||||
return def_._name._context.get_safe_value()
|
return def_._name._value.get_safe_value()
|
||||||
|
|
||||||
|
|
||||||
def test_f_strings(Script, environment):
|
def test_f_strings(Script, environment):
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ from textwrap import dedent
|
|||||||
|
|
||||||
def get_definition_and_infer_state(Script, source):
|
def get_definition_and_infer_state(Script, source):
|
||||||
first, = Script(dedent(source)).goto_definitions()
|
first, = Script(dedent(source)).goto_definitions()
|
||||||
return first._name._context, first._infer_state
|
return first._name._value, first._infer_state
|
||||||
|
|
||||||
|
|
||||||
def test_function_execution(Script):
|
def test_function_execution(Script):
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import re
|
|||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from jedi.inference.gradual.conversion import _stub_to_python_context_set
|
from jedi.inference.gradual.conversion import _stub_to_python_value_set
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
@@ -30,8 +30,8 @@ def test_compiled_signature(Script, environment, code, sig, names, op, version):
|
|||||||
return # The test right next to it should take over.
|
return # The test right next to it should take over.
|
||||||
|
|
||||||
d, = Script(code).goto_definitions()
|
d, = Script(code).goto_definitions()
|
||||||
context, = d._name.infer()
|
value, = d._name.infer()
|
||||||
compiled, = _stub_to_python_context_set(context)
|
compiled, = _stub_to_python_value_set(value)
|
||||||
signature, = compiled.get_signatures()
|
signature, = compiled.get_signatures()
|
||||||
assert signature.to_string() == sig
|
assert signature.to_string() == sig
|
||||||
assert [n.string_name for n in signature.get_param_names()] == names
|
assert [n.string_name for n in signature.get_param_names()] == names
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ def test_add_to_end(Script):
|
|||||||
|
|
||||||
def test_tokenizer_with_string_literal_backslash(Script):
|
def test_tokenizer_with_string_literal_backslash(Script):
|
||||||
c = Script("statement = u'foo\\\n'; statement").goto_definitions()
|
c = Script("statement = u'foo\\\n'; statement").goto_definitions()
|
||||||
assert c[0]._name._context.get_safe_value() == 'foo'
|
assert c[0]._name._value.get_safe_value() == 'foo'
|
||||||
|
|
||||||
|
|
||||||
def test_ellipsis_without_getitem(Script, environment):
|
def test_ellipsis_without_getitem(Script, environment):
|
||||||
|
|||||||
@@ -14,8 +14,8 @@ def auto_import_json(monkeypatch):
|
|||||||
def test_base_auto_import_modules(auto_import_json, Script):
|
def test_base_auto_import_modules(auto_import_json, Script):
|
||||||
loads, = Script('import json; json.loads').goto_definitions()
|
loads, = Script('import json; json.loads').goto_definitions()
|
||||||
assert isinstance(loads._name, ContextName)
|
assert isinstance(loads._name, ContextName)
|
||||||
context, = loads._name.infer()
|
value, = loads._name.infer()
|
||||||
assert isinstance(context.parent_context, StubModuleContext)
|
assert isinstance(value.parent_value, StubModuleContext)
|
||||||
|
|
||||||
|
|
||||||
def test_auto_import_modules_imports(auto_import_json, Script):
|
def test_auto_import_modules_imports(auto_import_json, Script):
|
||||||
|
|||||||
Reference in New Issue
Block a user