context -> value

This commit is contained in:
Dave Halter
2019-08-15 01:23:06 +02:00
parent 9e23f4d67b
commit ad4f546aca
68 changed files with 1931 additions and 1931 deletions
+7 -7
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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(),
) )
+5 -5
View File
@@ -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
View File
@@ -1 +1 @@
from jedi.common.context import BaseContextSet, BaseContext from jedi.common.value import BaseContextSet, BaseContext
+1 -1
View File
@@ -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:
+11 -11
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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 {}
+82 -82
View File
@@ -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))
+6 -6
View File
@@ -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()
+3 -3
View File
@@ -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
+30 -30
View File
@@ -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)
-6
View File
@@ -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
-15
View File
@@ -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__()
+32 -32
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
+10 -10
View File
@@ -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()]
+88 -88
View File
@@ -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)
+46 -46
View File
@@ -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
+40 -40
View File
@@ -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
View File
@@ -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()
+3 -3
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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()]
+1 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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,
+7 -7
View File
@@ -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):
+6
View File
@@ -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
+15
View File
@@ -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
+7 -7
View File
@@ -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
View File
@@ -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 -1
View File
@@ -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):
+1 -1
View File
@@ -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
View File
@@ -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'
+2 -2
View File
@@ -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):
+4 -4
View File
@@ -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:
+3 -3
View File
@@ -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')
+6 -6
View File
@@ -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")
+2 -2
View File
@@ -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):
+10 -10
View File
@@ -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(
+3 -3
View File
@@ -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):
+1 -1
View File
@@ -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):
+3 -3
View File
@@ -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
+1 -1
View File
@@ -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):
+2 -2
View File
@@ -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):