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
Inference Contexts (inference/base_value.py)
Inference Values (inference/base_value.py)
++++++++++++++++++++++++++++++++++++++++++++++++++++++
.. automodule:: jedi.inference.base_value
.. inheritance-diagram::
jedi.inference.context.instance.TreeInstance
jedi.inference.context.klass.ClassContext
jedi.inference.context.function.FunctionContext
jedi.inference.context.function.FunctionExecutionContext
jedi.inference.value.instance.TreeInstance
jedi.inference.value.klass.Classvalue
jedi.inference.value.function.FunctionContext
jedi.inference.value.function.FunctionExecutionContext
:parts: 1
@@ -124,13 +124,13 @@ without some features.
.. _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
dynamic features of Python like lists that are filled after creation:
.. automodule:: jedi.inference.context.iterable
.. automodule:: jedi.inference.value.iterable
.. _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.sys_path import transform_path_to_dotted
from jedi.inference.names import TreeNameDefinition, ParamName
from jedi.inference.syntax_tree import tree_name_to_contexts
from jedi.inference.context import ModuleContext
from jedi.inference.syntax_tree import tree_name_to_values
from jedi.inference.value import ModuleContext
from jedi.inference.base_value import ContextSet
from jedi.inference.context.iterable import unpack_tuple_to_dict
from jedi.inference.gradual.conversion import convert_names, convert_contexts
from jedi.inference.value.iterable import unpack_tuple_to_dict
from jedi.inference.gradual.conversion import convert_names, convert_values
from jedi.inference.gradual.utils import load_proper_stub_module
# 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:
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)
contexts = convert_contexts(
contexts,
values = helpers.infer_goto_definition(self._infer_state, value, leaf)
values = convert_values(
values,
only_stubs=only_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
# API sense. In the internals we want to separate more things than in
# the API.
@@ -299,8 +299,8 @@ class Script(object):
# Without a name we really just want to jump to the result e.g.
# executed by `foo()`, if we the cursor is after `)`.
return self.goto_definitions(only_stubs=only_stubs, prefer_stubs=prefer_stubs)
context = self._infer_state.create_context(self._get_module(), tree_name)
names = list(self._infer_state.goto(context, tree_name))
value = self._infer_state.create_value(self._get_module(), tree_name)
names = list(self._infer_state.goto(value, tree_name))
if follow_imports:
names = filter_follow_imports(names, lambda name: name.is_import())
@@ -368,21 +368,21 @@ class Script(object):
if call_details is None:
return []
context = self._infer_state.create_context(
value = self._infer_state.create_value(
self._get_module(),
call_details.bracket_leaf
)
definitions = helpers.cache_call_signatures(
self._infer_state,
context,
value,
call_details.bracket_leaf,
self._code_lines,
self._pos
)
debug.speed('func_call followed')
# TODO here we use stubs instead of the actual contexts. We should use
# the signatures from stubs, but the actual contexts, probably?!
# TODO here we use stubs instead of the actual values. We should use
# the signatures from stubs, but the actual values, probably?!
return [classes.CallSignature(self._infer_state, signature, call_details)
for signature in definitions.get_signatures()]
@@ -392,26 +392,26 @@ class Script(object):
module = self._get_module()
try:
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'):
# 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):
import_names = set(node.get_defined_names())
if node.is_nested():
import_names |= set(path[-1] for path in node.get_paths())
for n in import_names:
imports.infer_import(context, n)
imports.infer_import(value, n)
elif node.type == 'expr_stmt':
types = context.infer_node(node)
types = value.infer_node(node)
for testlist in node.children[:-1:2]:
# Iterate tuples.
unpack_tuple_to_dict(context, types, testlist)
unpack_tuple_to_dict(value, types, testlist)
else:
if node.type == 'name':
defs = self._infer_state.goto_definitions(context, node)
defs = self._infer_state.goto_definitions(value, node)
else:
defs = infer_call_of_leaf(context, node)
defs = infer_call_of_leaf(value, node)
try_iter_content(defs)
self._infer_state.reset_recursion_limitations()
@@ -505,13 +505,13 @@ def names(source=None, path=None, encoding='utf-8', all_scopes=False,
else:
cls = TreeNameDefinition
return cls(
module_context.create_context(name),
module_value.create_value(name),
name
)
# Set line/column to a random position, because they don't matter.
script = Script(source, line=1, column=0, path=path, encoding=encoding, environment=environment)
module_context = script._get_module()
module_value = script._get_module()
defs = [
classes.Definition(
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 compiled
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.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.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))
def defined_names(infer_state, context):
def defined_names(infer_state, value):
"""
List sub-definitions (e.g., methods in class).
:type scope: Scope
: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()]
return [Definition(infer_state, n) for n in _sort_names_by_start_pos(names)]
def _contexts_to_definitions(contexts):
return [Definition(c.infer_state, c.name) for c in contexts]
def _values_to_definitions(values):
return [Definition(c.infer_state, c.name) for c in values]
class BaseDefinition(object):
@@ -75,7 +75,7 @@ class BaseDefinition(object):
# This can take a while to complete, because in the worst case of
# imports (consider `import a` completions), we need to load all
# modules starting with a first.
return self._name.get_root_context()
return self._name.get_root_value()
@property
def module_path(self):
@@ -167,8 +167,8 @@ class BaseDefinition(object):
resolve = True
if isinstance(self._name, imports.SubModuleName) or resolve:
for context in self._name.infer():
return context.api_type
for value in self._name.infer():
return value.api_type
return self._name.api_type
@property
@@ -188,8 +188,8 @@ class BaseDefinition(object):
def in_builtin_module(self):
"""Whether this is a builtin module."""
if isinstance(self._get_module(), StubModuleContext):
return any(isinstance(context, compiled.CompiledObject)
for context in self._get_module().non_stub_context_set)
return any(isinstance(value, compiled.CompiledObject)
for value in self._get_module().non_stub_value_set)
return isinstance(self._get_module(), compiled.CompiledObject)
@property
@@ -270,7 +270,7 @@ class BaseDefinition(object):
be ``<module 'posixpath' ...>```. However most users find the latter
more practical.
"""
if not self._name.is_context_name:
if not self._name.is_value_name:
return None
names = self._name.get_qualified_names(include_module_names=True)
@@ -286,10 +286,10 @@ class BaseDefinition(object):
return '.'.join(names)
def is_stub(self):
if not self._name.is_context_name:
if not self._name.is_value_name:
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...
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):
assert not (only_stubs and prefer_stubs)
if not self._name.is_context_name:
if not self._name.is_value_name:
return []
names = convert_names(
@@ -316,19 +316,19 @@ class BaseDefinition(object):
def _infer(self, only_stubs=False, prefer_stubs=False):
assert not (only_stubs and prefer_stubs)
if not self._name.is_context_name:
if not self._name.is_value_name:
return []
# 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
# results of Python objects instead of stubs.
names = convert_names([self._name], prefer_stubs=True)
contexts = convert_contexts(
values = convert_values(
ContextSet.from_sets(n.infer() for n in names),
only_stubs=only_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)
for n in resulting_names]
@@ -343,8 +343,8 @@ class BaseDefinition(object):
"""
# Only return the first one. There might be multiple one, especially
# with overloading.
for context in self._name.infer():
for signature in context.get_signatures():
for value in self._name.infer():
for signature in value.get_signatures():
return [
Definition(self._infer_state, n)
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.')
def parent(self):
if not self._name.is_context_name:
if not self._name.is_value_name:
return None
context = self._name.parent_context
if context is None:
value = self._name.parent_value
if value is None:
return None
if isinstance(context, FunctionExecutionContext):
context = context.function_context
return Definition(self._infer_state, context.name)
if isinstance(value, FunctionExecutionContext):
value = value.function_value
return Definition(self._infer_state, value.name)
def __repr__(self):
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
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 ''
lines = self._name.get_root_context().code_lines
lines = self._name.get_root_value().code_lines
index = self._name.start_pos[0] - 1
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()]
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):
@@ -680,7 +680,7 @@ class ParamDefinition(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):
"""
@@ -689,7 +689,7 @@ class ParamDefinition(Definition):
:param execute_annotation: If False, the values are not executed and
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):
return self._name.to_string()
@@ -709,10 +709,10 @@ class ParamDefinition(Definition):
return self._name.get_kind()
def _format_signatures(context):
def _format_signatures(value):
return '\n'.join(
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
@memoize_method
def _get_contexts(self, fast):
def _get_values(self, fast):
if isinstance(self._name, ImportName) and fast:
return {}
@@ -742,20 +742,20 @@ class _Help(object):
"""
full_doc = ''
# 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:
# 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.
full_doc += '\n' + '-' * 30 + '\n'
doc = context.py__doc__()
doc = value.py__doc__()
signature_text = ''
if self._name.is_context_name:
if self._name.is_value_name:
if not raw:
signature_text = _format_signatures(context)
if not doc and context.is_stub():
for c in convert_contexts(ContextSet({context}), ignore_compiled=False):
signature_text = _format_signatures(value)
if not doc and value.is_stub():
for c in convert_values(ContextSet({value}), ignore_compiled=False):
doc = c.py__doc__()
if doc:
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.helpers import infer_call_of_leaf, parse_dotted_names
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
@@ -52,11 +52,11 @@ def filter_names(infer_state, completion_names, stack, like_name):
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.
"""
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:
def scan(scope):
for s in scope.children:
@@ -68,12 +68,12 @@ def get_user_scope(module_context, position):
return scan(s)
return None
scanned_node = scan(module_context.tree_node)
scanned_node = scan(module_value.tree_node)
if scanned_node:
return module_context.create_context(scanned_node, node_is_context=True)
return module_context
return module_value.create_value(scanned_node, node_is_value=True)
return module_value
else:
return module_context.create_context(user_stmt)
return module_value.create_value(user_stmt)
def get_flow_scope_node(module_node, position):
@@ -87,7 +87,7 @@ def get_flow_scope_node(module_node, position):
class Completion:
def __init__(self, infer_state, module, code_lines, position, call_signatures_callback):
self._infer_state = infer_state
self._module_context = module
self._module_value = module
self._module_node = module.tree_node
self._code_lines = code_lines
@@ -104,14 +104,14 @@ class Completion:
string, start_leaf = _extract_string_while_in_string(leaf, self._position)
if string is not None:
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._code_lines, self._original_position
))
if 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,
self.stack, self._like_name)
@@ -120,9 +120,9 @@ class Completion:
x.name.startswith('_'),
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.
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.
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()
allowed_transitions = \
@@ -208,7 +208,7 @@ class Completion:
if nodes and nodes[-1] in ('as', 'def', 'class'):
# No completions for ``with x as foo`` and ``import x as foo``.
# Also true for defining names as a class or function.
return list(self._get_class_context_completions(is_function=True))
return list(self._get_class_value_completions(is_function=True))
elif "import_stmt" 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())
else:
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:
call_signatures = self._call_signatures_callback()
@@ -237,12 +237,12 @@ class Completion:
yield keywords.KeywordName(self._infer_state, k)
def _global_completions(self):
context = get_user_scope(self._module_context, self._position)
debug.dbg('global completion scope: %s', context)
value = get_user_scope(self._module_value, self._position)
debug.dbg('global completion scope: %s', value)
flow_scope_node = get_flow_scope_node(self._module_node, self._position)
filters = get_global_filters(
self._infer_state,
context,
value,
self._position,
origin_scope=flow_scope_node
)
@@ -252,34 +252,34 @@ class Completion:
return completion_names
def _trailer_completions(self, previous_leaf):
user_context = get_user_scope(self._module_context, self._position)
inferred_context = self._infer_state.create_context(
self._module_context, previous_leaf
user_value = get_user_scope(self._module_value, self._position)
inferred_value = self._infer_state.create_value(
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 = []
debug.dbg('trailer completion contexts: %s', contexts, color='MAGENTA')
for context in contexts:
for filter in context.get_filters(
debug.dbg('trailer completion values: %s', values, color='MAGENTA')
for value in values:
for filter in value.get_filters(
search_global=False,
origin_scope=user_context.tree_node):
origin_scope=user_value.tree_node):
completion_names += filter.values()
python_contexts = convert_contexts(contexts)
for c in python_contexts:
if c not in contexts:
python_values = convert_values(values)
for c in python_values:
if c not in values:
for filter in c.get_filters(
search_global=False,
origin_scope=user_context.tree_node):
origin_scope=user_value.tree_node):
completion_names += filter.values()
return completion_names
def _get_importer_names(self, names, level=0, only_modules=True):
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)
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.
"""
@@ -287,9 +287,9 @@ class Completion:
cls = tree.search_ancestor(leaf, 'classdef')
if isinstance(cls, (tree.Class, tree.Function)):
# 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,
node_is_context=True
node_is_value=True
)
else:
return
@@ -297,7 +297,7 @@ class Completion:
if cls.start_pos[1] >= leaf.start_pos[1]:
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.
next(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
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):
# First we want to find out what can actually be changed as a 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:
return
string = addition + string
@@ -25,7 +25,7 @@ def file_name_completions(infer_state, module_context, start_leaf, string,
sigs = call_signatures_callback()
is_in_os_path_join = sigs and all(s.full_name == 'os.path.join' for s in sigs)
if is_in_os_path_join:
to_be_added = _add_os_path_join(module_context, start_leaf, sigs[0].bracket_start)
to_be_added = _add_os_path_join(module_value, start_leaf, sigs[0].bracket_start)
if to_be_added is None:
is_in_os_path_join = False
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():
node = addition.parent
was_addition = True
@@ -77,18 +77,18 @@ def _get_string_additions(module_context, start_leaf):
addition = start_leaf.get_previous_leaf()
if addition != '+':
return ''
context = module_context.create_context(start_leaf)
return _add_strings(context, reversed(list(iterate_nodes())))
value = module_value.create_value(start_leaf)
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 = ''
first = True
for child_node in nodes:
contexts = context.infer_node(child_node)
if len(contexts) != 1:
values = value.infer_node(child_node)
if len(values) != 1:
return None
c, = contexts
c, = values
s = get_str_or_none(c)
if s is None:
return None
@@ -101,25 +101,25 @@ def _add_strings(context, nodes, add_slash=False):
class FileName(AbstractArbitraryName):
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):
if maybe_bracket.start_pos != bracket_start:
return None
if not nodes:
return ''
context = module_context.create_context(nodes[0])
return _add_strings(context, nodes, add_slash=True) or ''
value = module_value.create_value(nodes[0])
return _add_strings(value, nodes, add_slash=True) or ''
if start_leaf.type == 'error_leaf':
# Unfinished string literal, like `join('`
context_node = start_leaf.parent
index = context_node.children.index(start_leaf)
value_node = start_leaf.parent
index = value_node.children.index(start_leaf)
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:
index = -2
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.syntax_tree import infer_atom
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
@@ -87,7 +87,7 @@ def _get_code_for_stack(code_lines, leaf, position):
if is_after_newline:
if user_stmt.start_pos[1] > position[1]:
# 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('')
# 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':
# In case of a name we can just use goto_definition which does all the
# magic itself.
return infer_state.goto_definitions(context, leaf)
return infer_state.goto_definitions(value, leaf)
parent = leaf.parent
definitions = NO_CONTEXTS
if parent.type == 'atom':
# e.g. `(a + b)`
definitions = context.infer_node(leaf.parent)
definitions = value.infer_node(leaf.parent)
elif parent.type == 'trailer':
# e.g. `a()`
definitions = infer_call_of_leaf(context, leaf)
definitions = infer_call_of_leaf(value, leaf)
elif isinstance(leaf, tree.Literal):
# 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'):
return get_string_context_set(infer_state)
return get_string_value_set(infer_state)
return definitions
@@ -376,7 +376,7 @@ def get_call_signature_details(module, position):
@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."""
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])
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:
yield None # Don't cache!
else:
yield (module_path, before_bracket, bracket_leaf.start_pos)
yield infer_goto_definition(
infer_state,
context,
value,
bracket_leaf.get_previous_leaf(),
)
+5 -5
View File
@@ -2,7 +2,7 @@
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.compiled import mixed
from jedi.inference.compiled.access import create_access_path
@@ -24,24 +24,24 @@ class MixedModuleContext(ContextWrapper):
type = 'mixed_module'
def __init__(self, infer_state, tree_module, namespaces, file_io, code_lines):
module_context = ModuleContext(
module_value = ModuleContext(
infer_state, tree_module,
file_io=file_io,
string_names=('__main__',),
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]
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
for namespace_obj in self._namespace_objects:
compiled_object = _create(self.infer_state, namespace_obj)
mixed_object = mixed.MixedObject(
compiled_object=compiled_object,
tree_context=self._wrapped_context
tree_value=self._wrapped_value
)
for filter in mixed_object.get_filters(*args, **kwargs):
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
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)
try:
+11 -11
View File
@@ -1,21 +1,21 @@
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.parent_context = parent_context
self.parent_value = parent_value
def get_root_context(self):
context = self
def get_root_value(self):
value = self
while True:
if context.parent_context is None:
return context
context = context.parent_context
if value.parent_value is None:
return value
value = value.parent_value
class BaseContextSet(object):
def __init__(self, iterable):
self._set = frozenset(iterable)
for context in iterable:
assert not isinstance(context, BaseContextSet)
for value in iterable:
assert not isinstance(value, BaseContextSet)
@classmethod
def _from_frozen_set(cls, frozenset_):
@@ -61,8 +61,8 @@ class BaseContextSet(object):
def __getattr__(self, name):
def mapper(*args, **kwargs):
return self.from_sets(
getattr(context, name)(*args, **kwargs)
for context in self._set
getattr(value, name)(*args, **kwargs)
for value in self._set
)
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.names import TreeNameDefinition, ParamName
from jedi.inference.base_value import ContextualizedName, ContextualizedNode, \
ContextSet, NO_CONTEXTS, iterate_contexts
from jedi.inference.context import ClassContext, FunctionContext, \
ContextSet, NO_CONTEXTS, iterate_values
from jedi.inference.value import ClassContext, FunctionContext, \
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, \
infer_node, check_tuple_assignments
from jedi.plugins import plugin_manager
@@ -111,21 +111,21 @@ class InferState(object):
self.reset_recursion_limitations()
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):
if sys_path is None:
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)
@staticmethod
@plugin_manager.decorate()
def execute(context, arguments):
debug.dbg('execute: %s %s', context, arguments)
def execute(value, arguments):
debug.dbg('execute: %s %s', value, arguments)
with debug.increase_indent_cm():
context_set = context.py__call__(arguments=arguments)
debug.dbg('execute result: %s in %s', context_set, context)
return context_set
value_set = value.py__call__(arguments=arguments)
debug.dbg('execute result: %s in %s', value_set, value)
return value_set
@property
@infer_state_function_cache()
@@ -150,9 +150,9 @@ class InferState(object):
"""Convenience function"""
return self.project._get_sys_path(self, environment=self.environment, **kwargs)
def infer_element(self, context, element):
if isinstance(context, CompForContext):
return infer_node(context, element)
def infer_element(self, value, element):
if isinstance(value, CompForContext):
return infer_node(value, element)
if_stmt = element
while if_stmt is not None:
@@ -162,7 +162,7 @@ class InferState(object):
if parser_utils.is_scope(if_stmt):
if_stmt = None
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
# this in a different way. Caching should only be active in certain
# cases and this all sucks.
@@ -171,7 +171,7 @@ class InferState(object):
if_stmt_test = if_stmt.children[1]
name_dicts = [{}]
# 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
# the content.
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]
if any(i.value in str_element_names for i 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
# causes the complexity to rise. The complexity should
# never fall below 1.
@@ -210,65 +210,65 @@ class InferState(object):
if len(name_dicts) > 1:
result = NO_CONTEXTS
for name_dict in name_dicts:
with helpers.predefine_names(context, if_stmt, name_dict):
result |= infer_node(context, element)
with helpers.predefine_names(value, if_stmt, name_dict):
result |= infer_node(value, element)
return result
else:
return self._infer_element_if_inferred(context, element)
return self._infer_element_if_inferred(value, element)
else:
if predefined_if_name_dict:
return infer_node(context, element)
return infer_node(value, element)
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.
"""
parent = element
while parent is not None:
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:
return infer_node(context, element)
return self._infer_element_cached(context, element)
return infer_node(value, element)
return self._infer_element_cached(value, element)
@infer_state_function_cache(default=NO_CONTEXTS)
def _infer_element_cached(self, context, element):
return infer_node(context, element)
def _infer_element_cached(self, value, 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)
if def_ is not None:
type_ = def_.type
is_classdef = type_ == 'classdef'
if is_classdef or type_ == 'funcdef':
if is_classdef:
c = ClassContext(self, context, name.parent)
c = ClassContext(self, value, name.parent)
else:
c = FunctionContext.from_context(context, name.parent)
c = FunctionContext.from_value(value, name.parent)
return ContextSet([c])
if type_ == 'expr_stmt':
is_simple_name = name.parent.type not in ('power', 'trailer')
if is_simple_name:
return infer_expr_stmt(context, def_, name)
return infer_expr_stmt(value, def_, name)
if type_ == 'for_stmt':
container_types = context.infer_node(def_.children[3])
cn = ContextualizedNode(context, def_.children[3])
for_types = iterate_contexts(container_types, cn)
c_node = ContextualizedName(context, name)
container_types = value.infer_node(def_.children[3])
cn = ContextualizedNode(value, def_.children[3])
for_types = iterate_values(container_types, cn)
c_node = ContextualizedName(value, name)
return check_tuple_assignments(self, c_node, for_types)
if type_ in ('import_from', 'import_name'):
return imports.infer_import(context, name)
return imports.infer_import(value, name)
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:
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')
if error_node is not None:
# 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,
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
def goto(self, context, name):
def goto(self, value, name):
definition = name.get_definition(import_name_always=True)
if definition is not None:
type_ = definition.type
@@ -304,18 +304,18 @@ class InferState(object):
# a name it's something you can "goto" again.
is_simple_name = name.parent.type not in ('power', 'trailer')
if is_simple_name:
return [TreeNameDefinition(context, name)]
return [TreeNameDefinition(value, name)]
elif type_ == 'param':
return [ParamName(context, name)]
return [ParamName(value, 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
else:
return [TreeNameDefinition(context, name)]
return [TreeNameDefinition(value, name)]
else:
contexts = self._follow_error_node_imports_if_possible(context, name)
if contexts is not None:
return [context.name for context in contexts]
values = self._follow_error_node_imports_if_possible(value, name)
if values is not None:
return [value.name for value in values]
par = name.parent
node_type = par.type
@@ -326,18 +326,18 @@ class InferState(object):
trailer = trailer.parent
if trailer.type != 'classdef':
if trailer.type == 'decorator':
context_set = context.infer_node(trailer.children[1])
value_set = value.infer_node(trailer.children[1])
else:
i = trailer.parent.children.index(trailer)
to_infer = trailer.parent.children[:i]
if to_infer[0] == 'await':
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:]:
context_set = infer_trailer(context, context_set, trailer)
value_set = infer_trailer(value, value_set, trailer)
param_names = []
for context in context_set:
for signature in context.get_signatures():
for value in value_set:
for signature in value.get_signatures():
for param_name in signature.get_param_names():
if param_name.string_name == name.value:
param_names.append(param_name)
@@ -347,28 +347,28 @@ class InferState(object):
if index > 0:
new_dotted = helpers.deep_ast_copy(par)
new_dotted.children[index - 1:] = []
values = context.infer_node(new_dotted)
values = value.infer_node(new_dotted)
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
)
if node_type == 'trailer' and par.children[0] == '.':
values = helpers.infer_call_of_leaf(context, name, cut_own_trailer=True)
return values.py__getattribute__(name, name_context=context, is_goto=True)
values = helpers.infer_call_of_leaf(value, name, cut_own_trailer=True)
return values.py__getattribute__(name, name_value=value, is_goto=True)
else:
stmt = tree.search_ancestor(
name, 'expr_stmt', 'lambdef'
) or name
if stmt.type == 'lambdef':
stmt = name
return context.py__getattribute__(
return value.py__getattribute__(
name,
position=stmt.start_pos,
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):
while True:
node = node.parent
@@ -390,13 +390,13 @@ class InferState(object):
is_funcdef = scope_node.type in ('funcdef', 'lambdef')
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:
func = FunctionContext.from_context(parent_context, scope_node)
if parent_context.is_class():
func = FunctionContext.from_value(parent_value, scope_node)
if parent_value.is_class():
instance = AnonymousInstance(
self, parent_context.parent_context, parent_context)
self, parent_value.parent_value, parent_value)
func = BoundMethod(
instance=instance,
function=func
@@ -406,16 +406,16 @@ class InferState(object):
return func.get_function_execution()
return func
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'):
if node.start_pos >= scope_node.children[-1].start_pos:
return parent_context
return CompForContext.from_comp_for(parent_context, scope_node)
return parent_value
return CompForContext.from_comp_for(parent_value, scope_node)
raise Exception("There's a scope that was not managed.")
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
else:
scope_node = parent_scope(node)
+27 -27
View File
@@ -77,17 +77,17 @@ class Warning(Error):
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]
if _check_for_exception_catch(node_context, node, exception, payload):
if _check_for_exception_catch(node_value, node, exception, payload):
return
# TODO this path is probably not right
module_context = node_context.get_root_context()
module_path = module_context.py__file__()
module_value = node_value.get_root_value()
module_path = module_value.py__file__()
issue_instance = typ(error_name, module_path, node.start_pos, message)
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
@@ -95,7 +95,7 @@ def _check_for_setattr(instance):
"""
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
if node is None:
# 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)
def add_attribute_error(name_context, lookup_context, name):
message = ('AttributeError: %s has no attribute %s.' % (lookup_context, name))
from jedi.inference.context.instance import CompiledInstanceName
def add_attribute_error(name_value, lookup_value, name):
message = ('AttributeError: %s has no attribute %s.' % (lookup_value, name))
from jedi.inference.value.instance import CompiledInstanceName
# Check for __getattr__/__getattribute__ existance and issue a warning
# instead of an error, if that happens.
typ = Error
if lookup_context.is_instance() and not lookup_context.is_compiled():
slot_names = lookup_context.get_function_slot_names(u'__getattr__') + \
lookup_context.get_function_slot_names(u'__getattribute__')
if lookup_value.is_instance() and not lookup_value.is_compiled():
slot_names = lookup_value.get_function_slot_names(u'__getattr__') + \
lookup_value.get_function_slot_names(u'__getattribute__')
for n in slot_names:
# TODO do we even get here?
if isinstance(name, CompiledInstanceName) and \
n.parent_context.obj == object:
n.parent_value.obj == object:
typ = Warning
break
if _check_for_setattr(lookup_context):
if _check_for_setattr(lookup_value):
typ = Warning
payload = lookup_context, name
add(name_context, 'attribute-error', name, message, typ, payload)
payload = lookup_value, name
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
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():
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 False
@@ -167,14 +167,14 @@ def _check_for_exception_catch(node_context, jedi_name, exception, payload=None)
if node is None:
return True # An exception block that catches everything.
else:
except_classes = node_context.infer_node(node)
except_classes = node_value.infer_node(node)
for cls in except_classes:
from jedi.inference.context import iterable
from jedi.inference.value import iterable
if isinstance(cls, iterable.Sequence) and \
cls.array_type == 'tuple':
# multiple exceptions
for lazy_context in cls.py__iter__():
for typ in lazy_context.infer():
for lazy_value in cls.py__iter__():
for typ in lazy_value.infer():
if check_match(typ, exception):
return True
else:
@@ -192,19 +192,19 @@ def _check_for_exception_catch(node_context, jedi_name, exception, payload=None)
arglist = trailer.children[1]
assert arglist.type == 'arglist'
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
assert len(args) == 2
# Check name
key, lazy_context = args[1]
names = list(lazy_context.infer())
key, lazy_value = args[1]
names = list(lazy_value.infer())
assert len(names) == 1 and is_string(names[0])
assert force_unicode(names[0].get_safe_value()) == payload[1].value
# Check objects
key, lazy_context = args[0]
objects = lazy_context.infer()
key, lazy_value = args[0]
objects = lazy_value.infer()
return payload[0] in objects
except AssertionError:
return False
+46 -46
View File
@@ -6,11 +6,11 @@ from jedi._compatibility import zip_longest
from jedi import debug
from jedi.inference.utils import PushBackIterator
from jedi.inference import analysis
from jedi.inference.lazy_context import LazyKnownContext, LazyKnownContexts, \
LazyTreeContext, get_merged_lazy_context
from jedi.inference.lazy_value import LazyKnownContext, LazyKnownContexts, \
LazyTreeContext, get_merged_lazy_value
from jedi.inference.names import ParamName, TreeNameDefinition
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.param import get_executed_params_and_issues, ExecutedParam
@@ -28,8 +28,8 @@ def try_iter_content(types, depth=0):
except AttributeError:
pass
else:
for lazy_context in f():
try_iter_content(lazy_context.infer(), depth + 1)
for lazy_value in f():
try_iter_content(lazy_value.infer(), depth + 1)
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))
def decorator(func):
def wrapper(context, *args, **kwargs):
def wrapper(value, *args, **kwargs):
if keep_arguments_param:
arguments = kwargs['arguments']
else:
@@ -59,14 +59,14 @@ def repack_with_argument_clinic(string, keep_arguments_param=False, keep_callbac
kwargs.pop('callback', None)
try:
args += tuple(_iterate_argument_clinic(
context.infer_state,
value.infer_state,
arguments,
clinic_args
))
except ParamIssue:
return NO_CONTEXTS
else:
return func(context, *args, **kwargs)
return func(value, *args, **kwargs)
return wrapper
return decorator
@@ -77,15 +77,15 @@ def _iterate_argument_clinic(infer_state, arguments, parameters):
iterator = PushBackIterator(arguments.unpack())
for i, (name, optional, allow_kwargs, stars) in enumerate(parameters):
if stars == 1:
lazy_contexts = []
lazy_values = []
for key, argument in iterator:
if key is not None:
iterator.push_back((key, argument))
break
lazy_contexts.append(argument)
yield ContextSet([iterable.FakeSequence(infer_state, u'tuple', lazy_contexts)])
lazy_contexts
lazy_values.append(argument)
yield ContextSet([iterable.FakeSequence(infer_state, u'tuple', lazy_values)])
lazy_values
continue
elif stars == 2:
raise NotImplementedError()
@@ -98,15 +98,15 @@ def _iterate_argument_clinic(infer_state, arguments, parameters):
name, len(parameters), i)
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,
# that's ok, maybe something is too hard to resolve, however,
# we will not proceed with the type inference of that function.
debug.warning('argument_clinic "%s" not resolvable.', name)
raise ParamIssue
yield context_set
yield value_set
def _parse_argument_clinic(string):
@@ -137,33 +137,33 @@ class _AbstractArgumentsMixin(object):
Inferes all arguments as a support for static analysis
(normally Jedi).
"""
for key, lazy_context in self.unpack():
types = lazy_context.infer()
for key, lazy_value in self.unpack():
types = lazy_value.infer()
try_iter_content(types)
def unpack(self, funcdef=None):
raise NotImplementedError
def get_executed_params_and_issues(self, execution_context):
return get_executed_params_and_issues(execution_context, self)
def get_executed_params_and_issues(self, execution_value):
return get_executed_params_and_issues(execution_value, self)
def get_calling_nodes(self):
return []
class AbstractArguments(_AbstractArgumentsMixin):
context = None
value = None
argument_node = None
trailer = None
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
return search_params(
execution_context.infer_state,
execution_context,
execution_context.tree_node
execution_value.infer_state,
execution_value,
execution_value.tree_node
), []
def __repr__(self):
@@ -198,12 +198,12 @@ def unpack_arglist(arglist):
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.
"""
self.argument_node = argument_node
self.context = context
self.value = value
self._infer_state = infer_state
self.trailer = trailer # Can be None, e.g. in a class definition.
@@ -216,25 +216,25 @@ class TreeArguments(AbstractArguments):
named_args = []
for star_count, el in unpack_arglist(self.argument_node):
if star_count == 1:
arrays = self.context.infer_node(el)
iterators = [_iterate_star_args(self.context, a, el, funcdef)
arrays = self.value.infer_node(el)
iterators = [_iterate_star_args(self.value, a, el, funcdef)
for a in arrays]
for values in list(zip_longest(*iterators)):
# TODO zip_longest yields None, that means this would raise
# an exception?
yield None, get_merged_lazy_context(
yield None, get_merged_lazy_value(
[v for v in values if v is not None]
)
elif star_count == 2:
arrays = self.context.infer_node(el)
arrays = self.value.infer_node(el)
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
else:
if el.type == 'argument':
c = el.children
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.
# Include the brackets with the parent.
sync_comp_for = el.children[1]
@@ -242,13 +242,13 @@ class TreeArguments(AbstractArguments):
sync_comp_for = sync_comp_for.children[1]
comp = iterable.GeneratorComprehension(
self._infer_state,
defining_context=self.context,
defining_value=self.value,
sync_comp_for_node=sync_comp_for,
entry_node=el.children[0],
)
yield None, LazyKnownContext(comp)
else:
yield None, LazyTreeContext(self.context, el)
yield None, LazyTreeContext(self.value, el)
# Reordering arguments is necessary, because star args sometimes appear
# 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):
continue
yield TreeNameDefinition(self.context, name)
yield TreeNameDefinition(self.value, name)
def __repr__(self):
return '<%s: %s>' % (self.__class__.__name__, self.argument_node)
@@ -302,9 +302,9 @@ class TreeArguments(AbstractArguments):
break
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:
return [ContextualizedNode(arguments.context, arguments.trailer)]
return [ContextualizedNode(arguments.value, arguments.trailer)]
return []
@@ -325,8 +325,8 @@ class TreeArgumentsWrapper(_AbstractArgumentsMixin):
self._wrapped_arguments = arguments
@property
def context(self):
return self._wrapped_arguments.context
def value(self):
return self._wrapped_arguments.value
@property
def argument_node(self):
@@ -346,24 +346,24 @@ class TreeArgumentsWrapper(_AbstractArgumentsMixin):
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 funcdef is not None:
# TODO this funcdef should not be needed.
m = "TypeError: %s() argument after * must be a sequence, not %s" \
% (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:
iter_ = array.py__iter__
except AttributeError:
pass
else:
for lazy_context in iter_():
yield lazy_context
for lazy_value in iter_():
yield lazy_value
def _star_star_dict(context, array, input_node, funcdef):
from jedi.inference.context.instance import CompiledInstance
def _star_star_dict(value, array, input_node, funcdef):
from jedi.inference.value.instance import CompiledInstance
if isinstance(array, CompiledInstance) and array.name.string_name == 'dict':
# For now ignore this case. In the future add proper iterators and just
# 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:
m = "TypeError: %s argument after ** must be a mapping, not %s" \
% (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 {}
+82 -82
View File
@@ -1,6 +1,6 @@
"""
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
static analysis operation. In jedi there are always multiple returns and not
@@ -23,12 +23,12 @@ _sentinel = object()
class HelperContextMixin(object):
def get_root_context(self):
context = self
def get_root_value(self):
value = self
while True:
if context.parent_context is None:
return context
context = context.parent_context
if value.parent_value is None:
return value
value = value.parent_value
@classmethod
@infer_state_as_method_param_cache()
@@ -49,22 +49,22 @@ class HelperContextMixin(object):
def gather_annotation_classes(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(
lazy_context.infer()
for lazy_context in self.iterate(contextualized_node, is_async)
lazy_value.infer()
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,
analysis_errors=True):
"""
:param position: Position of the last statement -> tuple of line, column
"""
if name_context is None:
name_context = self
if name_value is None:
name_value = self
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)
filters = f.get_filters(search_global)
if is_goto:
@@ -72,22 +72,22 @@ class HelperContextMixin(object):
return f.find(filters, attribute_lookup=not search_global)
def py__await__(self):
await_context_set = self.py__getattribute__(u"__await__")
if not await_context_set:
debug.warning('Tried to run __await__ on context %s', self)
return await_context_set.execute_with_values()
await_value_set = self.py__getattribute__(u"__await__")
if not await_value_set:
debug.warning('Tried to run __await__ on value %s', self)
return await_value_set.execute_with_values()
def infer_node(self, node):
return self.infer_state.infer_element(self, node)
def create_context(self, node, node_is_context=False, node_is_object=False):
return self.infer_state.create_context(self, node, node_is_context, node_is_object)
def create_value(self, node, node_is_value=False, node_is_object=False):
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)
if is_async:
from jedi.inference.lazy_context import LazyKnownContexts
# TODO if no __aiter__ contexts are there, error should be:
from jedi.inference.lazy_value import LazyKnownContexts
# TODO if no __aiter__ values are there, error should be:
# TypeError: 'async for' requires an object with __aiter__ method, got int
return iter([
LazyKnownContexts(
@@ -97,11 +97,11 @@ class HelperContextMixin(object):
.py__stop_iteration_returns()
) # 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__():
if cls.is_same_class(class_context):
if cls.is_same_class(class_value):
return True
return False
@@ -128,24 +128,24 @@ class Context(HelperContextMixin, BaseContext):
# overwritten.
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
# TODO this context is probably not right.
# TODO this value is probably not right.
analysis.add(
contextualized_node.context,
valueualized_node.value,
'type-error-not-subscriptable',
contextualized_node.node,
valueualized_node.node,
message="TypeError: '%s' object is not subscriptable" % self
)
return NO_CONTEXTS
def py__iter__(self, contextualized_node=None):
if contextualized_node is not None:
def py__iter__(self, valueualized_node=None):
if valueualized_node is not None:
from jedi.inference import analysis
analysis.add(
contextualized_node.context,
valueualized_node.value,
'type-error-not-iterable',
contextualized_node.node,
valueualized_node.node,
message="TypeError: '%s' object is not iterable" % self)
return iter([])
@@ -191,7 +191,7 @@ class Context(HelperContextMixin, BaseContext):
def get_safe_value(self, default=_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
def py__call__(self, arguments):
@@ -207,18 +207,18 @@ class Context(HelperContextMixin, BaseContext):
return None
def is_stub(self):
# The root context knows if it's a stub or not.
return self.parent_context.is_stub()
# The root value knows if it's a stub or not.
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
all contexts that the iterate functions yield.
Calls `iterate`, on all values but ignores the ordering and just returns
all values that the iterate functions yield.
"""
return ContextSet.from_sets(
lazy_context.infer()
for lazy_context in contexts.iterate(contextualized_node, is_async=is_async)
lazy_value.infer()
for lazy_value in values.iterate(valueualized_node, is_async=is_async)
)
@@ -228,7 +228,7 @@ class _ContextWrapperBase(HelperContextMixin):
@safe_property
def name(self):
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:
return ContextName(self, wrapped_name.tree_name)
else:
@@ -241,35 +241,35 @@ class _ContextWrapperBase(HelperContextMixin):
return cls(*args, **kwargs)
def __getattr__(self, name):
assert name != '_wrapped_context', 'Problem with _get_wrapped_context'
return getattr(self._wrapped_context, name)
assert name != '_wrapped_value', 'Problem with _get_wrapped_value'
return getattr(self._wrapped_value, name)
class LazyContextWrapper(_ContextWrapperBase):
@safe_property
@memoize_method
def _wrapped_context(self):
with debug.increase_indent_cm('Resolve lazy context wrapper'):
return self._get_wrapped_context()
def _wrapped_value(self):
with debug.increase_indent_cm('Resolve lazy value wrapper'):
return self._get_wrapped_value()
def __repr__(self):
return '<%s>' % (self.__class__.__name__)
def _get_wrapped_context(self):
def _get_wrapped_value(self):
raise NotImplementedError
class ContextWrapper(_ContextWrapperBase):
def __init__(self, wrapped_context):
self._wrapped_context = wrapped_context
def __init__(self, wrapped_value):
self._wrapped_value = wrapped_value
def __repr__(self):
return '%s(%s)' % (self.__class__.__name__, self._wrapped_context)
return '%s(%s)' % (self.__class__.__name__, self._wrapped_value)
class TreeContext(Context):
def __init__(self, infer_state, parent_context, tree_node):
super(TreeContext, self).__init__(infer_state, parent_context)
def __init__(self, infer_state, parent_value, tree_node):
super(TreeContext, self).__init__(infer_state, parent_value)
self.predefined_names = {}
self.tree_node = tree_node
@@ -278,18 +278,18 @@ class TreeContext(Context):
class ContextualizedNode(object):
def __init__(self, context, node):
self.context = context
def __init__(self, value, node):
self.value = value
self.node = node
def get_root_context(self):
return self.context.get_root_context()
def get_root_value(self):
return self.value.get_root_value()
def infer(self):
return self.context.infer_node(self.node)
return self.value.infer_node(self.node)
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):
@@ -340,18 +340,18 @@ class ContextualizedName(ContextualizedNode):
return indexes
def _getitem(context, index_contexts, contextualized_node):
from jedi.inference.context.iterable import Slice
def _getitem(value, index_values, valueualized_node):
from jedi.inference.value.iterable import Slice
# The actual getitem call.
simple_getitem = getattr(context, 'py__simple_getitem__', None)
simple_getitem = getattr(value, 'py__simple_getitem__', None)
result = NO_CONTEXTS
unused_contexts = set()
for index_context in index_contexts:
unused_values = set()
for index_value in index_values:
if simple_getitem is not None:
index = index_context
if isinstance(index_context, Slice):
index = index_value
if isinstance(index_value, Slice):
index = index.obj
try:
@@ -368,15 +368,15 @@ def _getitem(context, index_contexts, contextualized_node):
except SimpleGetItemNotFound:
pass
unused_contexts.add(index_context)
unused_values.add(index_value)
# 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.
if unused_contexts or not index_contexts:
result |= context.py__getitem__(
ContextSet(unused_contexts),
contextualized_node
if unused_values or not index_values:
result |= value.py__getitem__(
ContextSet(unused_values),
valueualized_node
)
debug.dbg('py__getitem__ result: %s', result)
return result
@@ -386,12 +386,12 @@ class ContextSet(BaseContextSet):
def py__class__(self):
return ContextSet(c.py__class__() for c in self._set)
def iterate(self, contextualized_node=None, is_async=False):
from jedi.inference.lazy_context import get_merged_lazy_context
type_iters = [c.iterate(contextualized_node, is_async=is_async) for c in self._set]
for lazy_contexts in zip_longest(*type_iters):
yield get_merged_lazy_context(
[l for l in lazy_contexts if l is not None]
def iterate(self, valueualized_node=None, is_async=False):
from jedi.inference.lazy_value import get_merged_lazy_value
type_iters = [c.iterate(valueualized_node, is_async=is_async) for c in self._set]
for lazy_values in zip_longest(*type_iters):
yield get_merged_lazy_value(
[l for l in lazy_values if l is not None]
)
def execute(self, arguments):
@@ -409,15 +409,15 @@ class ContextSet(BaseContextSet):
return ContextSet.from_sets(_getitem(c, *args, **kwargs) for c in self._set)
def try_merge(self, function_name):
context_set = self.__class__([])
value_set = self.__class__([])
for c in self._set:
try:
method = getattr(c, function_name)
except AttributeError:
pass
else:
context_set |= method()
return context_set
value_set |= method()
return value_set
def gather_annotation_classes(self):
return ContextSet.from_sets([c.gather_annotation_classes() for c in self._set])
@@ -429,7 +429,7 @@ class ContextSet(BaseContextSet):
NO_CONTEXTS = ContextSet([])
def iterator_to_context_set(func):
def iterator_to_value_set(func):
def wrapper(*args, **kwargs):
return ContextSet(func(*args, **kwargs))
+6 -6
View File
@@ -1,5 +1,5 @@
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
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):
typing_builtins_module = infer_state.builtins_module
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())
else:
filter_ = next(typing_builtins_module.get_filters())
name, = filter_.get(string)
context, = name.infer()
return context
value, = name.infer()
return value
class CompiledValue(LazyContextWrapper):
@@ -27,7 +27,7 @@ class CompiledValue(LazyContextWrapper):
return getattr(self._compiled_obj, name)
return super(CompiledValue, self).__getattribute__(name)
def _get_wrapped_context(self):
def _get_wrapped_value(self):
instance, = builtin_from_name(
self.infer_state, self._compiled_obj.name.string_name).execute_with_values()
return instance
@@ -49,7 +49,7 @@ def create_simple_object(infer_state, 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()
+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
hashable.
"""
def wrapper(infer_state, obj, parent_context=None):
def wrapper(infer_state, obj, parent_value=None):
cache = getattr(infer_state, attribute_name)
# Do a very cheap form of caching here.
key = id(obj)
@@ -119,11 +119,11 @@ def compiled_objects_cache(attribute_name):
except KeyError:
# TODO wuaaaarrghhhhhhhh
if attribute_name == 'mixed_cache':
result = func(infer_state, obj, parent_context)
result = func(infer_state, obj, parent_value)
else:
result = func(infer_state, obj)
# 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 wrapper
+30 -30
View File
@@ -14,12 +14,12 @@ from jedi.cache import underscore_memoization
from jedi.file_io import FileIO
from jedi.inference.base_value import ContextSet, ContextWrapper
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.compiled.getattr_static import getattr_static
from jedi.inference.compiled.access import compiled_objects_cache, \
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
_sentinel = object()
@@ -42,8 +42,8 @@ class MixedObject(ContextWrapper):
fewer special cases, because we in Python you don't have the same freedoms
to modify the runtime.
"""
def __init__(self, compiled_object, tree_context):
super(MixedObject, self).__init__(tree_context)
def __init__(self, compiled_object, tree_value):
super(MixedObject, self).__init__(tree_value)
self.compiled_object = compiled_object
self.access_handle = compiled_object.access_handle
@@ -56,7 +56,7 @@ class MixedObject(ContextWrapper):
return self.compiled_object.get_signatures()
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):
if default is _sentinel:
@@ -83,11 +83,11 @@ class MixedName(compiled.CompiledName):
"""
@property
def start_pos(self):
contexts = list(self.infer())
if not contexts:
values = list(self.infer())
if not values:
# This means a start_pos that doesn't exist (compiled objects).
return 0, 0
return contexts[0].name.start_pos
return values[0].name.start_pos
@start_pos.setter
def start_pos(self, value):
@@ -97,20 +97,20 @@ class MixedName(compiled.CompiledName):
@underscore_memoization
def infer(self):
# 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,
default=None
)
assert len(access_paths)
contexts = [None]
values = [None]
for access in access_paths:
contexts = ContextSet.from_sets(
_create(self._infer_state, access, parent_context=c)
values = ContextSet.from_sets(
_create(self._infer_state, access, parent_value=c)
if c is None or isinstance(c, MixedObject)
else ContextSet({create_cached_compiled_object(c.infer_state, access, c)})
for c in contexts
for c in values
)
return contexts
return values
@property
def api_type(self):
@@ -230,11 +230,11 @@ def _find_syntax_node_name(infer_state, python_object):
@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(
infer_state,
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,
@@ -246,17 +246,17 @@ def _create(infer_state, access_handle, parent_context, *args):
if type(python_object) in (dict, list, tuple):
return ContextSet({compiled_object})
tree_contexts = to_stub(compiled_object)
if not tree_contexts:
tree_values = to_stub(compiled_object)
if not tree_values:
return ContextSet({compiled_object})
else:
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.
name = compiled_object.get_root_context().py__name__()
name = compiled_object.get_root_value().py__name__()
string_names = tuple(name.split('.'))
module_context = ModuleContext(
module_value = ModuleContext(
infer_state, module_node,
file_io=file_io,
string_names=string_names,
@@ -264,28 +264,28 @@ def _create(infer_state, access_handle, parent_context, *args):
is_package=hasattr(compiled_object, 'py__path__'),
)
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:
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
# TypeVar('foo'), where Jedi uses 'foo' as the name and
# Python's TypeVar('foo').__module__ will be typing.
return ContextSet({compiled_object})
module_context = parent_context.get_root_context()
module_value = parent_value.get_root_value()
tree_contexts = ContextSet({
module_context.create_context(
tree_values = ContextSet({
module_value.create_value(
tree_node,
node_is_context=True,
node_is_value=True,
node_is_object=True
)
})
if tree_node.type == 'classdef':
if not access_handle.is_class():
# Is an instance, not a class.
tree_contexts = tree_contexts.execute_with_values()
tree_values = tree_values.execute_with_values()
return ContextSet(
MixedObject(compiled_object, tree_context=tree_context)
for tree_context in tree_contexts
MixedObject(compiled_object, tree_value=tree_value)
for tree_value in tree_values
)
@@ -12,7 +12,7 @@ from jedi.inference.filters import AbstractFilter
from jedi.inference.names import AbstractNameDefinition, ContextNameMixin, \
ParamNameInterface
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.cache import infer_state_function_cache
from jedi.inference.helpers import reraise_getitem_errors
@@ -41,8 +41,8 @@ class CheckAttribute(object):
class CompiledObject(Context):
def __init__(self, infer_state, access_handle, parent_context=None):
super(CompiledObject, self).__init__(infer_state, parent_context)
def __init__(self, infer_state, access_handle, parent_value=None):
super(CompiledObject, self).__init__(infer_state, parent_value)
self.access_handle = access_handle
def py__call__(self, arguments):
@@ -57,9 +57,9 @@ class CompiledObject(Context):
return super(CompiledObject, self).py__call__(arguments)
else:
if self.access_handle.is_class():
from jedi.inference.context import CompiledInstance
from jedi.inference.value import CompiledInstance
return ContextSet([
CompiledInstance(self.infer_state, self.parent_context, self, arguments)
CompiledInstance(self.infer_state, self.parent_value, self, arguments)
])
else:
return ContextSet(self._execute_function(arguments))
@@ -189,24 +189,24 @@ class CompiledObject(Context):
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()
if all_access_paths is None:
# This means basically that no __getitem__ has been defined on this
# 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(
create_from_access_path(self.infer_state, access)
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
# the __iter__ function as long as __getitem__ is defined (it will
# just start with __getitem__(0). This is especially true for
# Python 2 strings, where `str.__iter__` is not even defined.
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
access_path_list = self.access_handle.py__iter__list()
@@ -269,18 +269,18 @@ class CompiledObject(Context):
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.parent_context = parent_context
self.parent_value = parent_value
self.string_name = name
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,)
def __repr__(self):
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:
name = None
return '<%s: (%s).%s>' % (self.__class__.__name__, name, self.string_name)
@@ -296,13 +296,13 @@ class CompiledName(AbstractNameDefinition):
@underscore_memoization
def infer(self):
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):
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
@property
@@ -322,19 +322,19 @@ class SignatureParamName(ParamNameInterface, AbstractNameDefinition):
def infer(self):
p = self._signature_param
infer_state = self.parent_context.infer_state
contexts = NO_CONTEXTS
infer_state = self.parent_value.infer_state
values = NO_CONTEXTS
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:
annotation = create_from_access_path(infer_state, p.annotation)
contexts |= annotation.execute_with_values()
return contexts
values |= annotation.execute_with_values()
return values
class UnresolvableParamName(ParamNameInterface, AbstractNameDefinition):
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._default = default
@@ -352,10 +352,10 @@ class UnresolvableParamName(ParamNameInterface, AbstractNameDefinition):
class CompiledContextName(ContextNameMixin, AbstractNameDefinition):
def __init__(self, context, name):
def __init__(self, value, name):
self.string_name = name
self._context = context
self.parent_context = context.parent_context
self._value = value
self.parent_value = value.parent_value
class EmptyCompiledName(AbstractNameDefinition):
@@ -365,7 +365,7 @@ class EmptyCompiledName(AbstractNameDefinition):
nothing.
"""
def __init__(self, infer_state, name):
self.parent_context = infer_state.builtins_module
self.parent_value = infer_state.builtins_module
self.string_name = name
def infer(self):
@@ -509,33 +509,33 @@ def _parse_function_doc(doc):
def _create_from_name(infer_state, compiled_object, name):
access_paths = compiled_object.access_handle.getattr_paths(name, default=None)
parent_context = compiled_object
if parent_context.is_class():
parent_context = parent_context.parent_context
parent_value = compiled_object
if parent_value.is_class():
parent_value = parent_value.parent_value
context = None
value = None
for access_path in access_paths:
context = create_cached_compiled_object(
infer_state, access_path, parent_context=context
value = create_cached_compiled_object(
infer_state, access_path, parent_value=value
)
return context
return value
def _normalize_create_args(func):
"""The cache doesn't care about keyword vs. normal args."""
def wrapper(infer_state, obj, parent_context=None):
return func(infer_state, obj, parent_context)
def wrapper(infer_state, obj, parent_value=None):
return func(infer_state, obj, parent_value)
return wrapper
def create_from_access_path(infer_state, access_path):
parent_context = None
parent_value = None
for name, access in access_path.accesses:
parent_context = create_cached_compiled_object(infer_state, access, parent_context)
return parent_context
parent_value = create_cached_compiled_object(infer_state, access, parent_value)
return parent_value
@_normalize_create_args
@infer_state_function_cache()
def create_cached_compiled_object(infer_state, access_handle, parent_context):
return CompiledObject(infer_state, access_handle, parent_context)
def create_cached_compiled_object(infer_state, access_handle, parent_value):
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.inference.utils import indent_block
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
from jedi.inference.lazy_context import LazyKnownContexts
from jedi.inference.lazy_value import LazyKnownContexts
DOCSTRING_PARAM_PATTERNS = [
@@ -183,7 +183,7 @@ def _strip_rst_role(type_str):
return type_str
def _infer_for_statement_string(module_context, string):
def _infer_for_statement_string(module_value, string):
code = dedent(u("""
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
# don't need to conform with the current grammar.
debug.dbg('Parse docstring code %s', string, color='BLUE')
grammar = module_context.infer_state.latest_grammar
grammar = module_value.infer_state.latest_grammar
try:
module = grammar.parse(code.format(indent_block(string)), error_recovery=False)
except ParserSyntaxError:
@@ -221,29 +221,29 @@ def _infer_for_statement_string(module_context, string):
if stmt.type not in ('name', 'atom', 'atom_expr'):
return []
from jedi.inference.context import FunctionContext
function_context = FunctionContext(
module_context.infer_state,
module_context,
from jedi.inference.value import FunctionContext
function_value = FunctionContext(
module_value.infer_state,
module_value,
funcdef
)
func_execution_context = function_context.get_function_execution()
func_execution_value = function_value.get_function_execution()
# Use the module of the param.
# 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.
# 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
doesn't include tuple, list and dict literals, because the stuff they
contain is executed. (Used as type information).
"""
definitions = module_context.infer_node(stmt)
definitions = module_value.infer_node(stmt)
return ContextSet.from_sets(
_execute_array_values(module_context.infer_state, d)
_execute_array_values(module_value.infer_state, d)
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
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):
values = []
for lazy_context in array.py__iter__():
for lazy_value in array.py__iter__():
objects = ContextSet.from_sets(
_execute_array_values(infer_state, typ)
for typ in lazy_context.infer()
for typ in lazy_value.infer()
)
values.append(LazyKnownContexts(objects))
return {FakeSequence(infer_state, array.array_type, values)}
@@ -268,35 +268,35 @@ def _execute_array_values(infer_state, array):
@infer_state_method_cache()
def infer_param(execution_context, param):
from jedi.inference.context.instance import InstanceArguments
from jedi.inference.context import FunctionExecutionContext
def infer_param(execution_value, param):
from jedi.inference.value.instance import InstanceArguments
from jedi.inference.value import FunctionExecutionContext
def infer_docstring(docstring):
return ContextSet(
p
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()
if func.type == 'lambdef':
return NO_CONTEXTS
types = infer_docstring(execution_context.py__doc__())
if isinstance(execution_context, FunctionExecutionContext) \
and isinstance(execution_context.var_args, InstanceArguments) \
and execution_context.function_context.py__name__() == '__init__':
class_context = execution_context.var_args.instance.class_context
types |= infer_docstring(class_context.py__doc__())
types = infer_docstring(execution_value.py__doc__())
if isinstance(execution_value, FunctionExecutionContext) \
and isinstance(execution_value.var_args, InstanceArguments) \
and execution_value.function_value.py__name__() == '__init__':
class_value = execution_value.var_args.instance.class_value
types |= infer_docstring(class_value.py__doc__())
debug.dbg('Found param types for docstring: %s', types, color='BLUE')
return types
@infer_state_method_cache()
@iterator_to_context_set
def infer_return_types(function_context):
@iterator_to_value_set
def infer_return_types(function_value):
def search_return_in_docstr(code):
for p in DOCSTRING_RETURN_PATTERNS:
match = p.search(code)
@@ -306,6 +306,6 @@ def infer_return_types(function_context):
for type_ in _search_return_in_numpydocstr(code):
yield type_
for type_str in search_return_in_docstr(function_context.py__doc__()):
for context in _infer_for_statement_string(function_context.get_root_context(), type_str):
yield context
for type_str in search_return_in_docstr(function_value.py__doc__()):
for value in _infer_for_statement_string(function_value.get_root_value(), type_str):
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.utils import to_list
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 import recursion
@@ -54,7 +54,7 @@ class DynamicExecutedParams(object):
@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:
@@ -68,31 +68,31 @@ def search_params(infer_state, execution_context, funcdef):
is.
"""
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
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):
# 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).
# This makes everything slower. Just disable it and run the tests,
# 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':
string_name = _get_lambda_name(funcdef)
if string_name is None:
return create_default_params(execution_context, funcdef)
return create_default_params(execution_value, funcdef)
else:
string_name = funcdef.name.value
debug.dbg('Dynamic param search in %s.', string_name, color='MAGENTA')
try:
module_context = execution_context.get_root_context()
module_value = execution_value.get_root_value()
function_executions = _search_function_executions(
infer_state,
module_context,
module_value,
funcdef,
string_name=string_name,
)
@@ -105,7 +105,7 @@ def search_params(infer_state, execution_context, funcdef):
for executed_params in zipped_params]
# Inferes the ExecutedParams to types.
else:
return create_default_params(execution_context, funcdef)
return create_default_params(execution_value, funcdef)
finally:
debug.dbg('Dynamic param result finished', color='MAGENTA')
return params
@@ -115,7 +115,7 @@ def search_params(infer_state, execution_context, funcdef):
@infer_state_function_cache(default=None)
@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.
"""
@@ -128,11 +128,11 @@ def _search_function_executions(infer_state, module_context, funcdef, string_nam
found_executions = False
i = 0
for for_mod_context in imports.get_modules_containing_name(
infer_state, [module_context], string_name):
if not isinstance(module_context, ModuleContext):
for for_mod_value in imports.get_modules_containing_name(
infer_state, [module_value], string_name):
if not isinstance(module_value, ModuleContext):
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
# 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:
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(
infer_state, random_context, compare_node, name, trailer):
infer_state, random_value, compare_node, name, trailer):
found_executions = True
yield function_execution
@@ -165,9 +165,9 @@ def _get_lambda_name(node):
return None
def _get_possible_nodes(module_context, func_string_name):
def _get_possible_nodes(module_value, func_string_name):
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:
return
@@ -178,51 +178,51 @@ def _get_possible_nodes(module_context, func_string_name):
yield name, trailer
def _check_name_for_execution(infer_state, context, compare_node, name, trailer):
from jedi.inference.context.function import FunctionExecutionContext
def _check_name_for_execution(infer_state, value, compare_node, name, trailer):
from jedi.inference.value.function import FunctionExecutionContext
def create_func_excs():
arglist = trailer.children[1]
if arglist == ')':
arglist = None
args = TreeArguments(infer_state, context, arglist, trailer)
args = TreeArguments(infer_state, value, arglist, trailer)
if value_node.type == 'classdef':
created_instance = instance.TreeInstance(
infer_state,
value.parent_context,
value,
v.parent_value,
v,
args
)
for execution in created_instance.create_init_executions():
yield execution
else:
yield value.get_function_execution(args)
yield v.get_function_execution(args)
for value in infer_state.goto_definitions(context, name):
value_node = value.tree_node
for v in infer_state.goto_definitions(value, name):
value_node = v.tree_node
if compare_node == value_node:
for func_execution in create_func_excs():
yield func_execution
elif isinstance(value.parent_context, FunctionExecutionContext) and \
elif isinstance(v.parent_value, FunctionExecutionContext) and \
compare_node.type == 'funcdef':
# Here we're trying to find decorators by checking the first
# parameter. It's not very generic though. Should find a better
# 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:
continue
values = params[0].infer()
nodes = [v.tree_node for v in values]
if nodes == [compare_node]:
# Found a decorator.
module_context = context.get_root_context()
execution_context = next(create_func_excs())
for name, trailer in _get_possible_nodes(module_context, params[0].string_name):
module_value = value.get_root_value()
execution_value = next(create_func_excs())
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:
random_context = infer_state.create_context(execution_context, name)
random_value = infer_state.create_value(execution_value, name)
iterator = _check_name_for_execution(
infer_state,
random_context,
random_value,
compare_node,
name,
trailer
+47 -47
View File
@@ -68,11 +68,11 @@ def _get_definition_names(used_names, name_key):
class AbstractUsedNamesFilter(AbstractFilter):
name_class = TreeNameDefinition
def __init__(self, context, parser_scope):
def __init__(self, value, parser_scope):
self._parser_scope = parser_scope
self._module_node = self._parser_scope.get_root_node()
self._used_names = self._module_node.get_used_names()
self.context = context
self.value = value
def get(self, name, **filter_kwargs):
return self._convert_names(self._filter(
@@ -81,7 +81,7 @@ class AbstractUsedNamesFilter(AbstractFilter):
))
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):
return self._convert_names(
@@ -94,23 +94,23 @@ class AbstractUsedNamesFilter(AbstractFilter):
)
def __repr__(self):
return '<%s: %s>' % (self.__class__.__name__, self.context)
return '<%s: %s>' % (self.__class__.__name__, self.value)
class ParserTreeFilter(AbstractUsedNamesFilter):
# 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):
"""
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
context, but for some type inference it's important to have a local
context of the other classes.
value, but for some type inference it's important to have a local
value of the other classes.
"""
if node_context is None:
node_context = context
super(ParserTreeFilter, self).__init__(context, node_context.tree_node)
self._node_context = node_context
if node_value is None:
node_value = value
super(ParserTreeFilter, self).__init__(value, node_value.tree_node)
self._node_value = node_value
self._origin_scope = origin_scope
self._until_position = until_position
@@ -129,8 +129,8 @@ class ParserTreeFilter(AbstractUsedNamesFilter):
def _check_flows(self, names):
for name in sorted(names, key=lambda name: name.start_pos, reverse=True):
check = flow_analysis.reachability_check(
context=self._node_context,
context_scope=self._parser_scope,
value=self._node_value,
value_scope=self._parser_scope,
node=name,
origin_scope=self._origin_scope
)
@@ -144,12 +144,12 @@ class ParserTreeFilter(AbstractUsedNamesFilter):
class FunctionExecutionFilter(ParserTreeFilter):
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):
super(FunctionExecutionFilter, self).__init__(
infer_state,
context,
node_context,
value,
node_value,
until_position,
origin_scope
)
@@ -159,14 +159,14 @@ class FunctionExecutionFilter(ParserTreeFilter):
for name in names:
param = search_ancestor(name, 'param')
if param:
yield self.param_name(self.context, name)
yield self.param_name(self.value, name)
else:
yield TreeNameDefinition(self.context, name)
yield TreeNameDefinition(self.value, name)
class GlobalNameFilter(AbstractUsedNamesFilter):
def __init__(self, context, parser_scope):
super(GlobalNameFilter, self).__init__(context, parser_scope)
def __init__(self, value, parser_scope):
super(GlobalNameFilter, self).__init__(value, parser_scope)
def get(self, name):
try:
@@ -235,17 +235,17 @@ class _BuiltinMappedMethod(Context):
"""``Generator.__next__`` ``dict.values`` methods and so on."""
api_type = u'function'
def __init__(self, builtin_context, method, builtin_func):
def __init__(self, builtin_value, method, builtin_func):
super(_BuiltinMappedMethod, self).__init__(
builtin_context.infer_state,
parent_context=builtin_context
builtin_value.infer_state,
parent_value=builtin_value
)
self._method = method
self._builtin_func = builtin_func
def py__call__(self, arguments):
# 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):
return getattr(self._builtin_func, name)
@@ -259,19 +259,19 @@ class SpecialMethodFilter(DictFilter):
class SpecialMethodName(AbstractNameDefinition):
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
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
self.parent_context = parent_context
self.parent_value = parent_value
self.string_name = string_name
self._callable = callable_
self._builtin_context = builtin_context
self._builtin_value = builtin_value
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
# always only going to be one name. The same is true for the
# inferred values.
@@ -282,22 +282,22 @@ class SpecialMethodFilter(DictFilter):
continue
break
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)
self.context = context
self._builtin_context = builtin_context
self.value = value
self._builtin_value = builtin_value
"""
This context is what will be used to introspect the name, where as the
other context will be used to execute the function.
This value is what will be used to introspect the name, where as the
other value will be used to execute the function.
We distinguish, because we have to.
"""
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):
@@ -321,9 +321,9 @@ class _OverwriteMeta(type):
class _AttributeOverwriteMixin(object):
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
@@ -346,7 +346,7 @@ def publish_method(method_name, python_version_match=None):
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.
@@ -364,8 +364,8 @@ def get_global_filters(infer_state, context, until_position, origin_scope):
>>> scope = next(module_node.iter_funcdefs())
>>> scope
<Function: func@3-5>
>>> context = script._get_module().create_context(scope)
>>> filters = list(get_global_filters(context.infer_state, context, (4, 0), None))
>>> value = script._get_module().create_value(scope)
>>> filters = list(get_global_filters(value.infer_state, value, (4, 0), None))
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
[...]
"""
from jedi.inference.context.function import FunctionExecutionContext
while context is not None:
from jedi.inference.value.function import FunctionExecutionContext
while value is not None:
# Names in methods cannot be resolved within the class.
for filter in context.get_filters(
for filter in value.get_filters(
search_global=True,
until_position=until_position,
origin_scope=origin_scope):
yield filter
if isinstance(context, FunctionExecutionContext):
if isinstance(value, FunctionExecutionContext):
# The position should be reset if the current scope is a function.
until_position = None
context = context.parent_context
value = value.parent_value
# Add builtins to the global scope.
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.arguments import TreeArguments
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.names import TreeNameDefinition
from jedi.inference.base_value import ContextSet, NO_CONTEXTS
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):
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):
self._infer_state = infer_state
# Make sure that it's not just a syntax tree node.
self._context = context
self._name_context = name_context
self._value = value
self._name_value = name_value
self._name = name_or_str
if isinstance(name_or_str, tree.Name):
self._string_name = name_or_str.value
@@ -56,8 +56,8 @@ class NameFinder(object):
names = self.filter_name(filters)
if self._found_predefined_types is not None and names:
check = flow_analysis.reachability_check(
context=self._context,
context_scope=self._context.tree_node,
value=self._value,
value_scope=self._value.tree_node,
node=self._name,
)
if check is flow_analysis.UNREACHABLE:
@@ -72,11 +72,11 @@ class NameFinder(object):
if isinstance(self._name, tree.Name):
if attribute_lookup:
analysis.add_attribute_error(
self._name_context, self._context, self._name)
self._name_value, self._value, self._name)
else:
message = ("NameError: name '%s' is not defined."
% 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
@@ -98,7 +98,7 @@ class NameFinder(object):
position = self._position
# 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.
if origin_scope is not None:
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:
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:
return self._get_context_filters(origin_scope)
return self._get_value_filters(origin_scope)
def _get_context_filters(self, origin_scope):
for f in self._context.get_filters(False, self._position, origin_scope=origin_scope):
def _get_value_filters(self, origin_scope):
for f in self._value.get_filters(False, self._position, origin_scope=origin_scope):
yield f
# This covers the case where a stub files are incomplete.
if self._context.is_stub():
for c in convert_contexts(ContextSet({self._context})):
if self._value.is_stub():
for c in convert_values(ContextSet({self._value})):
for f in c.get_filters():
yield f
@@ -135,13 +135,13 @@ class NameFinder(object):
names = []
# This paragraph is currently needed for proper branch type inference
# (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
while node is not None and not is_scope(node):
node = node.parent
if node.type in ("if_stmt", "for_stmt", "comp_for", 'sync_comp_for'):
try:
name_dict = self._context.predefined_names[node]
name_dict = self._value.predefined_names[node]
types = name_dict[self._string_name]
except KeyError:
continue
@@ -167,7 +167,7 @@ class NameFinder(object):
break
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)
def _check_getattr(self, inst):
@@ -187,33 +187,33 @@ class NameFinder(object):
return inst.execute_function_slots(names, name)
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)
if not names and self._context.is_instance() and not self._context.is_compiled():
debug.dbg('finder._names_to_types: %s -> %s', names, values)
if not names and self._value.is_instance() and not self._value.is_compiled():
# handling __getattr__ / __getattribute__
return self._check_getattr(self._context)
return self._check_getattr(self._value)
# Add isinstance and other if/assert knowledge.
if not contexts and isinstance(self._name, tree.Name) and \
not self._name_context.is_instance() and not self._context.is_compiled():
if not values and isinstance(self._name, tree.Name) and \
not self._name_value.is_instance() and not self._value.is_compiled():
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):
return contexts
return values
while 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)
if n is not None:
return n
if flow_scope in base_nodes:
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
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:
ass = search_ancestor(name, 'assert_stmt')
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:
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 != ':']
for if_test in reversed(potential_ifs):
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
def _check_isinstance_type(context, element, search_name):
def _check_isinstance_type(value, element, search_name):
try:
assert element.type in ('power', 'atom_expr')
# this might be removed if we analyze and, etc
@@ -265,26 +265,26 @@ def _check_isinstance_type(context, element, search_name):
# arglist stuff
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())
# Disallow keyword arguments
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
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,
# 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)
except AssertionError:
return None
context_set = NO_CONTEXTS
for cls_or_tup in lazy_context_cls.infer():
value_set = NO_CONTEXTS
for cls_or_tup in lazy_value_cls.infer():
if isinstance(cls_or_tup, iterable.Sequence) and cls_or_tup.array_type == 'tuple':
for lazy_context in cls_or_tup.py__iter__():
context_set |= lazy_context.infer().execute_with_values()
for lazy_value in cls_or_tup.py__iter__():
value_set |= lazy_value.infer().execute_with_values()
else:
context_set |= cls_or_tup.execute_with_values()
return context_set
value_set |= cls_or_tup.execute_with_values()
return value_set
+10 -10
View File
@@ -41,7 +41,7 @@ def _get_flow_scopes(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)
if origin_scope is not None:
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
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
if flow_scope.type == 'if_stmt':
if flow_scope.is_node_after_else(node):
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):
break
reachable = reachable.invert()
else:
flow_node = flow_scope.get_corresponding_test_node(node)
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'):
return UNSURE
@@ -98,19 +98,19 @@ def _break_check(context, context_scope, flow_scope, node):
if reachable in (UNREACHABLE, UNSURE):
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)
return reachable & _break_check(context, context_scope, flow_scope, node)
return reachable & _break_check(value, value_scope, flow_scope, node)
else:
return reachable
def _check_if(context, node):
with execution_allowed(context.infer_state, node) as allowed:
def _check_if(value, node):
with execution_allowed(value.infer_state, node) as allowed:
if not allowed:
return UNSURE
types = context.infer_node(node)
types = value.infer_node(node)
values = set(x.py__bool__() for x in types)
if len(values) == 1:
return Status.lookup_table[values.pop()]
+88 -88
View File
@@ -21,7 +21,7 @@ from jedi import debug
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
`int` here:
@@ -30,37 +30,37 @@ def infer_annotation(context, annotation):
Also checks for forward references (strings)
"""
context_set = context.infer_node(annotation)
if len(context_set) != 1:
value_set = value.infer_node(annotation)
if len(value_set) != 1:
debug.warning("Inferred typing index %s should lead to 1 object, "
" not %s" % (annotation, context_set))
return context_set
" not %s" % (annotation, value_set))
return value_set
inferred_context = list(context_set)[0]
if is_string(inferred_context):
result = _get_forward_reference_node(context, inferred_context.get_safe_value())
inferred_value = list(value_set)[0]
if is_string(inferred_value):
result = _get_forward_reference_node(value, inferred_value.get_safe_value())
if result is not None:
return context.infer_node(result)
return context_set
return value.infer_node(result)
return value_set
def _infer_annotation_string(context, string, index=None):
node = _get_forward_reference_node(context, string)
def _infer_annotation_string(value, string, index=None):
node = _get_forward_reference_node(value, string)
if node is None:
return NO_CONTEXTS
context_set = context.infer_node(node)
value_set = value.infer_node(node)
if index is not None:
context_set = context_set.filter(
lambda context: context.array_type == u'tuple' # noqa
and len(list(context.py__iter__())) >= index
value_set = value_set.filter(
lambda value: value.array_type == u'tuple' # noqa
and len(list(value.py__iter__())) >= 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:
new_node = context.infer_state.grammar.parse(
new_node = value.infer_state.grammar.parse(
force_unicode(string),
start_symbol='eval_input',
error_recovery=False
@@ -69,9 +69,9 @@ def _get_forward_reference_node(context, string):
debug.warning('Annotation not parsed: %s' % string)
return None
else:
module = context.tree_node.get_root_node()
module = value.tree_node.get_root_node()
parser_utils.move(new_node, module.end_pos[0])
new_node.parent = context.tree_node
new_node.parent = value.tree_node
return new_node
@@ -107,26 +107,26 @@ def _split_comment_param_declaration(decl_text):
@infer_state_method_cache()
def infer_param(execution_context, param):
contexts = _infer_param(execution_context, param)
infer_state = execution_context.infer_state
def infer_param(execution_value, param):
values = _infer_param(execution_value, param)
infer_state = execution_value.infer_state
if param.star_count == 1:
tuple_ = builtin_from_name(infer_state, 'tuple')
return ContextSet([GenericClass(
tuple_,
generics=(contexts,),
) for c in contexts])
generics=(values,),
) for c in values])
elif param.star_count == 2:
dct = builtin_from_name(infer_state, 'dict')
return ContextSet([GenericClass(
dct,
generics=(ContextSet([builtin_from_name(infer_state, 'str')]), contexts),
) for c in contexts])
generics=(ContextSet([builtin_from_name(infer_state, 'str')]), values),
) for c in values])
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.
"""
@@ -158,8 +158,8 @@ def _infer_param(execution_context, param):
"Comments length != Params length %s %s",
params_comments, all_params
)
from jedi.inference.context.instance import InstanceArguments
if isinstance(execution_context.var_args, InstanceArguments):
from jedi.inference.value.instance import InstanceArguments
if isinstance(execution_value.var_args, InstanceArguments):
if index == 0:
# Assume it's self, which is already handled
return NO_CONTEXTS
@@ -169,12 +169,12 @@ def _infer_param(execution_context, param):
param_comment = params_comments[index]
return _infer_annotation_string(
execution_context.function_context.get_default_param_context(),
execution_value.function_value.get_default_param_value(),
param_comment
)
# Annotations are like default params and resolve in the same way.
context = execution_context.function_context.get_default_param_context()
return infer_annotation(context, annotation)
value = execution_value.function_value.get_default_param_value()
return infer_annotation(value, annotation)
def py__annotations__(funcdef):
@@ -191,16 +191,16 @@ def py__annotations__(funcdef):
@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,
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)
if annotation is None:
# 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)
if comment is None:
return NO_CONTEXTS
@@ -210,28 +210,28 @@ def infer_return_types(function_execution_context):
return NO_CONTEXTS
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()
).execute_annotation()
if annotation is None:
return NO_CONTEXTS
context = function_execution_context.function_context.get_default_param_context()
unknown_type_vars = list(find_unknown_type_vars(context, annotation))
annotation_contexts = infer_annotation(context, annotation)
value = function_execution_value.function_value.get_default_param_value()
unknown_type_vars = list(find_unknown_type_vars(value, annotation))
annotation_values = infer_annotation(value, annotation)
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(
ann.define_generics(type_var_dict)
if isinstance(ann, (AbstractAnnotatedClass, TypeVar)) else ContextSet({ann})
for ann in annotation_contexts
for ann in annotation_values
).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
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.
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 = {}
executed_params, _ = execution_context.get_executed_params_and_issues()
executed_params, _ = execution_value.get_executed_params_and_issues()
for executed_param in executed_params:
try:
annotation_node = annotation_dict[executed_param.string_name]
except KeyError:
continue
annotation_variables = find_unknown_type_vars(context, annotation_node)
annotation_variables = find_unknown_type_vars(value, annotation_node)
if annotation_variables:
# 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
actual_context_set = executed_param.infer(use_hints=False)
actual_value_set = executed_param.infer(use_hints=False)
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:
# TODO _dict_values is not public.
actual_context_set = actual_context_set.try_merge('_dict_values')
for ann in annotation_context_set:
actual_value_set = actual_value_set.try_merge('_dict_values')
for ann in annotation_value_set:
_merge_type_var_dicts(
annotation_variable_results,
_infer_type_vars(ann, actual_context_set),
_infer_type_vars(ann, actual_value_set),
)
return annotation_variable_results
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:
base_dict[type_var_name] |= contexts
base_dict[type_var_name] |= values
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
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.
According to typeshed, `iter` returns an `Iterator[_T]`:
@@ -293,66 +293,66 @@ def _infer_type_vars(annotation_context, context_set):
unpacks the `Iterable`.
"""
type_var_dict = {}
if isinstance(annotation_context, TypeVar):
return {annotation_context.py__name__(): context_set.py__class__()}
elif isinstance(annotation_context, LazyGenericClass):
name = annotation_context.py__name__()
if isinstance(annotation_value, TypeVar):
return {annotation_value.py__name__(): value_set.py__class__()}
elif isinstance(annotation_value, LazyGenericClass):
name = annotation_value.py__name__()
if name == 'Iterable':
given = annotation_context.get_generics()
given = annotation_value.get_generics()
if given:
for nested_annotation_context in given[0]:
for nested_annotation_value in given[0]:
_merge_type_var_dicts(
type_var_dict,
_infer_type_vars(
nested_annotation_context,
context_set.merge_types_of_iterate()
nested_annotation_value,
value_set.merge_types_of_iterate()
)
)
elif name == 'Mapping':
given = annotation_context.get_generics()
given = annotation_value.get_generics()
if len(given) == 2:
for context in context_set:
for value in value_set:
try:
method = context.get_mapping_item_contexts
method = value.get_mapping_item_values
except AttributeError:
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(
type_var_dict,
_infer_type_vars(
nested_annotation_context,
key_contexts,
nested_annotation_value,
key_values,
)
)
for nested_annotation_context in given[1]:
for nested_annotation_value in given[1]:
_merge_type_var_dicts(
type_var_dict,
_infer_type_vars(
nested_annotation_context,
value_contexts,
nested_annotation_value,
value_values,
)
)
return type_var_dict
def find_type_from_comment_hint_for(context, node, name):
return _find_type_from_comment_hint(context, node, node.children[1], name)
def find_type_from_comment_hint_for(value, node, 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, \
"Can only be here when children[1] is 'foo() as f'"
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):
return _find_type_from_comment_hint(context, node, node.children[0], name)
def find_type_from_comment_hint_assign(value, node, 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
if varlist.type in ("testlist_star_expr", "exprlist", "testlist"):
# something like "a, b = 1, 2"
@@ -373,11 +373,11 @@ def _find_type_from_comment_hint(context, node, varlist, name):
if match is None:
return []
return _infer_annotation_string(
context, match.group(1).strip(), index
value, match.group(1).strip(), index
).execute_annotation()
def find_unknown_type_vars(context, node):
def find_unknown_type_vars(value, node):
def check_node(node):
if node.type in ('atom_expr', 'power'):
trailer = node.children[-1]
@@ -385,7 +385,7 @@ def find_unknown_type_vars(context, node):
for subscript_node in _unpack_subscriptlist(trailer.children[1]):
check_node(subscript_node)
else:
type_var_set = context.infer_node(node)
type_var_set = value.infer_node(node)
for type_var in type_var_set:
if isinstance(type_var, TypeVar) and type_var not in found:
found.append(type_var)
+46 -46
View File
@@ -2,47 +2,47 @@ from jedi import debug
from jedi.inference.base_value import ContextSet, \
NO_CONTEXTS
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):
stub_module = stub_context.get_root_context()
def _stub_to_python_value_set(stub_value, ignore_compiled=False):
stub_module = stub_value.get_root_value()
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:
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:
return NO_CONTEXTS
was_bound_method = stub_context.is_bound_method()
was_bound_method = stub_value.is_bound_method()
if was_bound_method:
# Infer the object first. We can infer the method later.
method_name = qualified_names[-1]
qualified_names = qualified_names[:-1]
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:
contexts = ContextSet.from_sets(
values = ContextSet.from_sets(
c.execute_with_values()
for c in contexts
for c in values
if c.is_class()
)
if was_bound_method:
# Now that the instance has been properly created, we can simply get
# the method.
contexts = contexts.py__getattribute__(method_name)
return contexts
values = values.py__getattribute__(method_name)
return values
def _infer_from_stub(stub_module, qualified_names, ignore_compiled):
from jedi.inference.compiled.mixed import MixedObject
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:
non_stubs = non_stubs.filter(lambda c: not c.is_compiled())
for name in qualified_names:
@@ -53,28 +53,28 @@ def _infer_from_stub(stub_module, qualified_names, ignore_compiled):
@to_list
def _try_stub_to_python_names(names, prefer_stub_to_compiled=False):
for name in names:
module = name.get_root_context()
module = name.get_root_value()
if not module.is_stub():
yield name
continue
name_list = name.get_qualified_names()
if name_list is None:
contexts = NO_CONTEXTS
values = NO_CONTEXTS
else:
contexts = _infer_from_stub(
values = _infer_from_stub(
module,
name_list[:-1],
ignore_compiled=prefer_stub_to_compiled,
)
if contexts and name_list:
new_names = contexts.py__getattribute__(name_list[-1], is_goto=True)
if values and name_list:
new_names = values.py__getattribute__(name_list[-1], is_goto=True)
for new_name in new_names:
yield new_name
if new_names:
continue
elif contexts:
for c in contexts:
elif values:
for c in values:
yield c.name
continue
# 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(
module.infer_state,
import_names=module.string_names,
python_context_set=ContextSet([module]),
parent_module_context=None,
python_value_set=ContextSet([module]),
parent_module_value=None,
sys_path=module.infer_state.get_sys_path(),
)
@@ -98,7 +98,7 @@ def _load_stub_module(module):
@to_list
def _python_to_stub_names(names, fallback_to_python=False):
for name in names:
module = name.get_root_context()
module = name.get_root_value()
if module.is_stub():
yield name
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)
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)
with debug.increase_indent_cm('convert contexts'):
with debug.increase_indent_cm('convert values'):
if only_stubs or prefer_stubs:
return ContextSet.from_sets(
to_stub(context)
or (ContextSet({context}) if prefer_stubs else NO_CONTEXTS)
for context in contexts
to_stub(value)
or (ContextSet({value}) if prefer_stubs else NO_CONTEXTS)
for value in values
)
else:
return ContextSet.from_sets(
_stub_to_python_context_set(stub_context, ignore_compiled=ignore_compiled)
or ContextSet({stub_context})
for stub_context in contexts
_stub_to_python_value_set(stub_value, ignore_compiled=ignore_compiled)
or ContextSet({stub_value})
for stub_value in values
)
# TODO merge with _python_to_stub_names?
def to_stub(context):
if context.is_stub():
return ContextSet([context])
def to_stub(value):
if value.is_stub():
return ContextSet([value])
was_instance = context.is_instance()
was_instance = value.is_instance()
if was_instance:
context = context.py__class__()
value = value.py__class__()
qualified_names = context.get_qualified_names()
stub_module = _load_stub_module(context.get_root_context())
qualified_names = value.get_qualified_names()
stub_module = _load_stub_module(value.get_root_value())
if stub_module is None or qualified_names is None:
return NO_CONTEXTS
was_bound_method = context.is_bound_method()
was_bound_method = value.is_bound_method()
if was_bound_method:
# Infer the object first. We can infer the method later.
method_name = qualified_names[-1]
qualified_names = qualified_names[:-1]
was_instance = True
stub_contexts = ContextSet([stub_module])
stub_values = ContextSet([stub_module])
for name in qualified_names:
stub_contexts = stub_contexts.py__getattribute__(name)
stub_values = stub_values.py__getattribute__(name)
if was_instance:
stub_contexts = ContextSet.from_sets(
stub_values = ContextSet.from_sets(
c.execute_with_values()
for c in stub_contexts
for c in stub_values
if c.is_class()
)
if was_bound_method:
# Now that the instance has been properly created, we can simply get
# the method.
stub_contexts = stub_contexts.py__getattribute__(method_name)
return stub_contexts
stub_values = stub_values.py__getattribute__(method_name)
return stub_values
@@ -1,14 +1,14 @@
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, \
TreeNameDefinition
from jedi.inference.gradual.typing import TypingModuleFilterWrapper
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)
self.non_stub_context_set = non_stub_context_set
self.non_stub_value_set = non_stub_value_set
def is_stub(self):
return True
@@ -20,9 +20,9 @@ class StubModuleContext(ModuleContext):
there are for example no stubs for `json.tool`.
"""
names = {}
for context in self.non_stub_context_set:
for value in self.non_stub_value_set:
try:
method = context.sub_modules_dict
method = value.sub_modules_dict
except AttributeError:
pass
else:
@@ -31,13 +31,13 @@ class StubModuleContext(ModuleContext):
return names
def _get_first_non_stub_filters(self):
for context in self.non_stub_context_set:
yield next(context.get_filters(search_global=False))
for value in self.non_stub_value_set:
yield next(value.get_filters(search_global=False))
def _get_stub_filters(self, search_global, **filter_kwargs):
return [StubFilter(
self.infer_state,
context=self,
value=self,
search_global=search_global,
**filter_kwargs
)] + list(self.iter_star_filters(search_global=search_global))
@@ -72,7 +72,7 @@ class TypingModuleWrapper(StubModuleContext):
class _StubName(TreeNameDefinition):
def infer(self):
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 inferred
+40 -40
View File
@@ -6,7 +6,7 @@ from jedi.file_io import FileIO
from jedi._compatibility import FileNotFoundError, cast_path
from jedi.parser_utils import get_cached_code_lines
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__))))
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):
@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:
python_context_set = infer_state.module_cache.get(import_names)
python_value_set = infer_state.module_cache.get(import_names)
except KeyError:
if parent_module_context is not None and parent_module_context.is_stub():
parent_module_contexts = parent_module_context.non_stub_context_set
if parent_module_value is not None and parent_module_value.is_stub():
parent_module_values = parent_module_value.non_stub_value_set
else:
parent_module_contexts = [parent_module_context]
parent_module_values = [parent_module_value]
if import_names == ('os', 'path'):
# This is a huge exception, we follow a nested import
# ``os.path``, because it's a very important one in Python
# that is being achieved by messing with ``sys.modules`` in
# ``os``.
python_parent = next(iter(parent_module_contexts))
python_parent = next(iter(parent_module_values))
if python_parent is None:
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:
python_context_set = ContextSet.from_sets(
python_value_set = ContextSet.from_sets(
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:
return python_context_set
return python_value_set
stub = _try_to_load_stub_cached(infer_state, import_names, python_context_set,
parent_module_context, sys_path)
stub = _try_to_load_stub_cached(infer_state, import_names, python_value_set,
parent_module_value, sys_path)
if stub is not None:
return ContextSet([stub])
return python_context_set
return python_value_set
return wrapper
@@ -139,19 +139,19 @@ def _try_to_load_stub_cached(infer_state, import_names, *args, **kwargs):
return result
def _try_to_load_stub(infer_state, import_names, python_context_set,
parent_module_context, sys_path):
def _try_to_load_stub(infer_state, import_names, python_value_set,
parent_module_value, sys_path):
"""
Trying to load a stub for a set of import_names.
This is modelled to work like "PEP 561 -- Distributing and Packaging Type
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:
parent_module_context = _try_to_load_stub_cached(
parent_module_value = _try_to_load_stub_cached(
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:
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'
m = _try_to_load_stub_from_file(
infer_state,
python_context_set,
python_value_set,
file_io=FileIO(init),
import_names=import_names,
)
@@ -170,7 +170,7 @@ def _try_to_load_stub(infer_state, import_names, python_context_set,
return m
# 2. Try to load pyi files next to py files.
for c in python_context_set:
for c in python_value_set:
try:
method = c.py__file__
except AttributeError:
@@ -186,7 +186,7 @@ def _try_to_load_stub(infer_state, import_names, python_context_set,
for file_path in file_paths:
m = _try_to_load_stub_from_file(
infer_state,
python_context_set,
python_value_set,
# The file path should end with .pyi
file_io=FileIO(file_path),
import_names=import_names,
@@ -195,15 +195,15 @@ def _try_to_load_stub(infer_state, import_names, python_context_set,
return m
# 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:
return m
# 4. Try to load pyi file somewhere if python_context_set was not defined.
if not python_context_set:
if parent_module_context is not None:
# 4. Try to load pyi file somewhere if python_value_set was not defined.
if not python_value_set:
if parent_module_value is not None:
try:
method = parent_module_context.py__path__
method = parent_module_value.py__path__
except AttributeError:
check_path = []
else:
@@ -217,7 +217,7 @@ def _try_to_load_stub(infer_state, import_names, python_context_set,
for p in check_path:
m = _try_to_load_stub_from_file(
infer_state,
python_context_set,
python_value_set,
file_io=FileIO(os.path.join(p, *names_for_path) + '.pyi'),
import_names=import_names,
)
@@ -229,18 +229,18 @@ def _try_to_load_stub(infer_state, import_names, python_context_set,
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]
map_ = None
if len(import_names) == 1:
map_ = _cache_stub_file_map(infer_state.grammar.version_info)
import_name = _IMPORT_MAP.get(import_name, import_name)
elif isinstance(parent_module_context, StubModuleContext):
if not parent_module_context.is_package:
elif isinstance(parent_module_value, StubModuleContext):
if not parent_module_value.is_package:
# Only if it's a package (= a folder) something can be
# imported.
return None
path = parent_module_context.py__path__()
path = parent_module_value.py__path__()
map_ = _merge_create_stub_map(path)
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:
return _try_to_load_stub_from_file(
infer_state,
python_context_set,
python_value_set,
file_io=FileIO(path),
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:
stub_module_node = infer_state.parse(
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
else:
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
)
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',):
module_cls = TypingModuleWrapper
else:
module_cls = StubModuleContext
file_name = os.path.basename(file_io.path)
stub_module_context = module_cls(
python_context_set, infer_state, stub_module_node,
stub_module_value = module_cls(
python_value_set, infer_state, stub_module_node,
file_io=file_io,
string_names=import_names,
# 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),
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
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.
"""
@@ -10,16 +10,16 @@ from jedi import debug
from jedi.inference.cache import infer_state_method_cache
from jedi.inference.compiled import builtin_from_name
from jedi.inference.base_value import ContextSet, NO_CONTEXTS, Context, \
iterator_to_context_set, ContextWrapper, LazyContextWrapper
from jedi.inference.lazy_context import LazyKnownContexts
from jedi.inference.context.iterable import SequenceLiteralContext
iterator_to_value_set, ContextWrapper, LazyContextWrapper
from jedi.inference.lazy_value import LazyKnownContexts
from jedi.inference.value.iterable import SequenceLiteralContext
from jedi.inference.arguments import repack_with_argument_clinic
from jedi.inference.utils import to_list
from jedi.inference.filters import FilterWrapper
from jedi.inference.names import NameWrapper, AbstractTreeName, \
AbstractNameDefinition, ContextName
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()
_TYPE_ALIAS_TYPES = {
@@ -36,17 +36,17 @@ _PROXY_TYPES = 'Optional Union ClassVar'.split()
class TypingName(AbstractTreeName):
def __init__(self, context, other_name):
super(TypingName, self).__init__(context.parent_context, other_name.tree_name)
self._context = context
def __init__(self, value, other_name):
super(TypingName, self).__init__(value.parent_value, other_name.tree_name)
self._value = value
def infer(self):
return ContextSet([self._context])
return ContextSet([self._value])
class _BaseTypingContext(Context):
def __init__(self, infer_state, parent_context, tree_name):
super(_BaseTypingContext, self).__init__(infer_state, parent_context)
def __init__(self, infer_state, parent_value, tree_name):
super(_BaseTypingContext, self).__init__(infer_state, parent_value)
self._tree_name = tree_name
@property
@@ -87,39 +87,39 @@ class TypingModuleName(NameWrapper):
def _remap(self):
name = self.string_name
infer_state = self.parent_context.infer_state
infer_state = self.parent_value.infer_state
try:
actual = _TYPE_ALIAS_TYPES[name]
except KeyError:
pass
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
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:
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':
# 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
# have any effects there (because it's never executed).
return
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':
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':
# 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.
yield builtin_from_name(infer_state, u'True')
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':
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':
# 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':
# TODO doesn't even exist in typeshed/typing.py, yet. But will be
# added soon.
@@ -139,16 +139,16 @@ class TypingModuleFilterWrapper(FilterWrapper):
class _WithIndexBase(_BaseTypingContext):
def __init__(self, infer_state, parent_context, name, index_context, context_of_index):
super(_WithIndexBase, self).__init__(infer_state, parent_context, name)
self._index_context = index_context
self._context_of_index = context_of_index
def __init__(self, infer_state, parent_value, name, index_value, value_of_index):
super(_WithIndexBase, self).__init__(infer_state, parent_value, name)
self._index_value = index_value
self._value_of_index = value_of_index
def __repr__(self):
return '<%s: %s[%s]>' % (
self.__class__.__name__,
self._tree_name.value,
self._index_context,
self._index_value,
)
@@ -166,24 +166,24 @@ class TypingContextWithIndex(_WithIndexBase):
return self.gather_annotation_classes().execute_annotation() \
| ContextSet([builtin_from_name(self.infer_state, u'None')])
elif string_name == 'Type':
# The type is actually already given in the index_context
return ContextSet([self._index_context])
# The type is actually already given in the index_value
return ContextSet([self._index_value])
elif string_name == 'ClassVar':
# 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]
return ContextSet([cls(
self.infer_state,
self.parent_context,
self.parent_value,
self._tree_name,
self._index_context,
self._context_of_index
self._index_value,
self._value_of_index
)])
def gather_annotation_classes(self):
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
py__simple_getitem__ = None
def py__getitem__(self, index_context_set, contextualized_node):
def py__getitem__(self, index_value_set, valueualized_node):
return ContextSet(
self.index_class.create_cached(
self.infer_state,
self.parent_context,
self.parent_value,
self._tree_name,
index_context,
context_of_index=contextualized_node.context)
for index_context in index_context_set
index_value,
value_of_index=valueualized_node.value)
for index_value in index_value_set
)
@@ -221,33 +221,33 @@ class TypingClassContext(_TypingClassMixin, TypingContext, ClassMixin):
index_class = TypingClassContextWithIndex
def _iter_over_arguments(maybe_tuple_context, defining_context):
def _iter_over_arguments(maybe_tuple_value, defining_value):
def iterate():
if isinstance(maybe_tuple_context, SequenceLiteralContext):
for lazy_context in maybe_tuple_context.py__iter__(contextualized_node=None):
yield lazy_context.infer()
if isinstance(maybe_tuple_value, SequenceLiteralContext):
for lazy_value in maybe_tuple_value.py__iter__(valueualized_node=None):
yield lazy_value.infer()
else:
yield ContextSet([maybe_tuple_context])
yield ContextSet([maybe_tuple_value])
def resolve_forward_references(context_set):
for context in context_set:
if is_string(context):
def resolve_forward_references(value_set):
for value in value_set:
if is_string(value):
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:
for c in defining_context.infer_node(node):
for c in defining_value.infer_node(node):
yield c
else:
yield context
yield value
for context_set in iterate():
yield ContextSet(resolve_forward_references(context_set))
for value_set in iterate():
yield ContextSet(resolve_forward_references(value_set))
class TypeAlias(LazyContextWrapper):
def __init__(self, parent_context, origin_tree_name, actual):
self.infer_state = parent_context.infer_state
self.parent_context = parent_context
def __init__(self, parent_value, origin_tree_name, actual):
self.infer_state = parent_value.infer_state
self.parent_value = parent_value
self._origin_tree_name = origin_tree_name
self._actual = actual # e.g. builtins.list
@@ -261,7 +261,7 @@ class TypeAlias(LazyContextWrapper):
def __repr__(self):
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('.')
if self.infer_state.environment.version_info.major == 2 and module_name == 'builtins':
module_name = '__builtin__'
@@ -279,56 +279,56 @@ class TypeAlias(LazyContextWrapper):
class _ContainerBase(_WithIndexBase):
def _get_getitem_contexts(self, index):
args = _iter_over_arguments(self._index_context, self._context_of_index)
for i, contexts in enumerate(args):
def _get_getitem_values(self, index):
args = _iter_over_arguments(self._index_value, self._value_of_index)
for i, values in enumerate(args):
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
class Callable(_ContainerBase):
def py__call__(self, 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):
def _is_homogenous(self):
# To specify a variable-length tuple of homogeneous type, Tuple[T, ...]
# is used.
if isinstance(self._index_context, SequenceLiteralContext):
entries = self._index_context.get_tree_entries()
if isinstance(self._index_value, SequenceLiteralContext):
entries = self._index_value.get_tree_entries()
if len(entries) == 2 and entries[1] == '...':
return True
return False
def py__simple_getitem__(self, index):
if self._is_homogenous():
return self._get_getitem_contexts(0).execute_annotation()
return self._get_getitem_values(0).execute_annotation()
else:
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)
return NO_CONTEXTS
def py__iter__(self, contextualized_node=None):
def py__iter__(self, valueualized_node=None):
if self._is_homogenous():
yield LazyKnownContexts(self._get_getitem_contexts(0).execute_annotation())
yield LazyKnownContexts(self._get_getitem_values(0).execute_annotation())
else:
if isinstance(self._index_context, SequenceLiteralContext):
for i in range(self._index_context.py__len__()):
yield LazyKnownContexts(self._get_getitem_contexts(i).execute_annotation())
if isinstance(self._index_value, SequenceLiteralContext):
for i in range(self._index_value.py__len__()):
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():
return self._get_getitem_contexts(0).execute_annotation()
return self._get_getitem_values(0).execute_annotation()
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()
@@ -350,8 +350,8 @@ class TypeVarClass(_BaseTypingContext):
def py__call__(self, arguments):
unpacked = arguments.unpack()
key, lazy_context = next(unpacked, (None, None))
var_name = self._find_string_name(lazy_context)
key, lazy_value = next(unpacked, (None, None))
var_name = self._find_string_name(lazy_value)
# The name must be given, otherwise it's useless.
if var_name is None or key is not None:
debug.warning('Found a variable without a name %s', arguments)
@@ -359,25 +359,25 @@ class TypeVarClass(_BaseTypingContext):
return ContextSet([TypeVar.create_cached(
self.infer_state,
self.parent_context,
self.parent_value,
self._tree_name,
var_name,
unpacked
)])
def _find_string_name(self, lazy_context):
if lazy_context is None:
def _find_string_name(self, lazy_value):
if lazy_value is None:
return None
context_set = lazy_context.infer()
if not context_set:
value_set = lazy_value.infer()
if not value_set:
return None
if len(context_set) > 1:
debug.warning('Found multiple contexts for a type variable: %s', context_set)
if len(value_set) > 1:
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:
method = name_context.get_safe_value
method = name_value.get_safe_value
except AttributeError:
return None
else:
@@ -391,24 +391,24 @@ class TypeVarClass(_BaseTypingContext):
class TypeVar(_BaseTypingContext):
def __init__(self, infer_state, parent_context, tree_name, var_name, unpacked_args):
super(TypeVar, self).__init__(infer_state, parent_context, tree_name)
def __init__(self, infer_state, parent_value, tree_name, var_name, unpacked_args):
super(TypeVar, self).__init__(infer_state, parent_value, tree_name)
self._var_name = var_name
self._constraints_lazy_contexts = []
self._bound_lazy_context = None
self._covariant_lazy_context = None
self._contravariant_lazy_context = None
for key, lazy_context in unpacked_args:
self._constraints_lazy_values = []
self._bound_lazy_value = None
self._covariant_lazy_value = None
self._contravariant_lazy_value = None
for key, lazy_value in unpacked_args:
if key is None:
self._constraints_lazy_contexts.append(lazy_context)
self._constraints_lazy_values.append(lazy_value)
else:
if key == 'bound':
self._bound_lazy_context = lazy_context
self._bound_lazy_value = lazy_value
elif key == 'covariant':
self._covariant_lazy_context = lazy_context
self._covariant_lazy_value = lazy_value
elif key == 'contravariant':
self._contra_variant_lazy_context = lazy_context
self._contra_variant_lazy_value = lazy_value
else:
debug.warning('Invalid TypeVar param name %s', key)
@@ -419,9 +419,9 @@ class TypeVar(_BaseTypingContext):
return iter([])
def _get_classes(self):
if self._bound_lazy_context is not None:
return self._bound_lazy_context.infer()
if self._constraints_lazy_contexts:
if self._bound_lazy_value is not None:
return self._bound_lazy_value.infer()
if self._constraints_lazy_values:
return self.constraints
debug.warning('Tried to infer the TypeVar %s without a given type', self._var_name)
return NO_CONTEXTS
@@ -433,7 +433,7 @@ class TypeVar(_BaseTypingContext):
@property
def constraints(self):
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):
@@ -455,9 +455,9 @@ class TypeVar(_BaseTypingContext):
class OverloadFunction(_BaseTypingContext):
@repack_with_argument_clinic('func, /')
def py__call__(self, func_context_set):
def py__call__(self, func_value_set):
# Just pass arguments through.
return func_context_set
return func_value_set
class NewTypeFunction(_BaseTypingContext):
@@ -470,53 +470,53 @@ class NewTypeFunction(_BaseTypingContext):
return ContextSet(
NewType(
self.infer_state,
contextualized_node.context,
contextualized_node.node,
valueualized_node.value,
valueualized_node.node,
second_arg.infer(),
) for contextualized_node in arguments.get_calling_nodes())
) for valueualized_node in arguments.get_calling_nodes())
class NewType(Context):
def __init__(self, infer_state, parent_context, tree_node, type_context_set):
super(NewType, self).__init__(infer_state, parent_context)
self._type_context_set = type_context_set
def __init__(self, infer_state, parent_value, tree_node, type_value_set):
super(NewType, self).__init__(infer_state, parent_value)
self._type_value_set = type_value_set
self.tree_node = tree_node
def py__call__(self, arguments):
return self._type_context_set.execute_annotation()
return self._type_value_set.execute_annotation()
class CastFunction(_BaseTypingContext):
@repack_with_argument_clinic('type, object, /')
def py__call__(self, type_context_set, object_context_set):
return type_context_set.execute_annotation()
def py__call__(self, type_value_set, object_value_set):
return type_value_set.execute_annotation()
class BoundTypeVarName(AbstractNameDefinition):
"""
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.parent_context = type_var.parent_context
self._context_set = context_set
self.parent_value = type_var.parent_value
self._value_set = value_set
def infer(self):
def iter_():
for context in self._context_set:
for value in self._value_set:
# Replace any with the constraints if they are there.
if isinstance(context, Any):
if isinstance(value, Any):
for constraint in self._type_var.constraints:
yield constraint
else:
yield context
yield value
return ContextSet(iter_())
def py__name__(self):
return self._type_var.py__name__()
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):
@@ -602,16 +602,16 @@ class AbstractAnnotatedClass(ClassMixin, ContextWrapper):
changed = False
new_generics = []
for generic_set in self.get_generics():
contexts = NO_CONTEXTS
values = NO_CONTEXTS
for generic in generic_set:
if isinstance(generic, (AbstractAnnotatedClass, TypeVar)):
result = generic.define_generics(type_var_dict)
contexts |= result
values |= result
if result != ContextSet({generic}):
changed = True
else:
contexts |= ContextSet([generic])
new_generics.append(contexts)
values |= ContextSet([generic])
new_generics.append(values)
if not changed:
# 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([GenericClass(
self._wrapped_context,
self._wrapped_value,
generics=tuple(new_generics)
)])
def __repr__(self):
return '<%s: %s%s>' % (
self.__class__.__name__,
self._wrapped_context,
self._wrapped_value,
list(self.get_generics()),
)
@to_list
def py__bases__(self):
for base in self._wrapped_context.py__bases__():
for base in self._wrapped_value.py__bases__():
yield LazyAnnotatedBaseClass(self, base)
class LazyGenericClass(AbstractAnnotatedClass):
def __init__(self, class_context, index_context, context_of_index):
super(LazyGenericClass, self).__init__(class_context)
self._index_context = index_context
self._context_of_index = context_of_index
def __init__(self, class_value, index_value, value_of_index):
super(LazyGenericClass, self).__init__(class_value)
self._index_value = index_value
self._value_of_index = value_of_index
@infer_state_method_cache()
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):
def __init__(self, class_context, generics):
super(GenericClass, self).__init__(class_context)
def __init__(self, class_value, generics):
super(GenericClass, self).__init__(class_value)
self._generics = generics
def get_generics(self):
@@ -658,25 +658,25 @@ class GenericClass(AbstractAnnotatedClass):
class LazyAnnotatedBaseClass(object):
def __init__(self, class_context, lazy_base_class):
self._class_context = class_context
def __init__(self, class_value, lazy_base_class):
self._class_value = class_value
self._lazy_base_class = lazy_base_class
@iterator_to_context_set
@iterator_to_value_set
def infer(self):
for base in self._lazy_base_class.infer():
if isinstance(base, AbstractAnnotatedClass):
# Here we have to recalculate the given types.
yield GenericClass.create_cached(
base.infer_state,
base._wrapped_context,
base._wrapped_value,
tuple(self._remap_type_vars(base)),
)
else:
yield 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():
new = NO_CONTEXTS
for type_var in type_var_set:
@@ -688,14 +688,14 @@ class LazyAnnotatedBaseClass(object):
else:
# Mostly will be type vars, except if in some cases
# 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])
yield new
class InstanceWrapper(ContextWrapper):
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':
generics = cls.get_generics()
try:
@@ -704,4 +704,4 @@ class InstanceWrapper(ContextWrapper):
pass
elif cls.py__name__() == 'Iterator':
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]
if import_names is not None:
actual_context_set = infer_state.import_module(import_names, prefer_stubs=False)
if not actual_context_set:
actual_value_set = infer_state.import_module(import_names, prefer_stubs=False)
if not actual_value_set:
return None
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
return stub
+22 -22
View File
@@ -44,7 +44,7 @@ def deep_ast_copy(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``
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
if trailer.type == 'fstring':
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
# different trailers: `( x )`, `[ x ]` and `.x`. In the first two examples
# 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 == 'atom':
return context.infer_node(trailer)
return context.infer_node(leaf)
return value.infer_node(trailer)
return value.infer_node(leaf)
power = trailer.parent
index = power.children.index(trailer)
@@ -99,10 +99,10 @@ def infer_call_of_leaf(context, leaf, cut_own_trailer=False):
base = trailers[0]
trailers = trailers[1:]
values = context.infer_node(base)
values = value.infer_node(base)
from jedi.inference.syntax_tree import infer_trailer
for trailer in trailers:
values = infer_trailer(context, values, trailer)
values = infer_trailer(value, values, trailer)
return values
@@ -185,8 +185,8 @@ def get_module_names(module, all_scopes):
@contextmanager
def predefine_names(context, flow_scope, dct):
predefined = context.predefined_names
def predefine_names(value, flow_scope, dct):
predefined = value.predefined_names
predefined[flow_scope] = dct
try:
yield
@@ -194,34 +194,34 @@ def predefine_names(context, flow_scope, dct):
del predefined[flow_scope]
def is_string(context):
if context.infer_state.environment.version_info.major == 2:
def is_string(value):
if value.infer_state.environment.version_info.major == 2:
str_classes = (unicode, bytes)
else:
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):
return is_number(context) or is_string(context)
def is_literal(value):
return is_number(value) or is_string(value)
def _get_safe_value_or_none(context, accept):
value = context.get_safe_value(default=None)
def _get_safe_value_or_none(value, accept):
value = value.get_safe_value(default=None)
if isinstance(value, accept):
return value
def get_int_or_none(context):
return _get_safe_value_or_none(context, int)
def get_int_or_none(value):
return _get_safe_value_or_none(value, int)
def get_str_or_none(context):
return _get_safe_value_or_none(context, (bytes, unicode))
def get_str_or_none(value):
return _get_safe_value_or_none(value, (bytes, unicode))
def is_number(context):
return _get_safe_value_or_none(context, (int, float)) is not None
def is_number(value):
return _get_safe_value_or_none(value, (int, float)) is not None
class SimpleGetItemNotFound(Exception):
@@ -265,5 +265,5 @@ def parse_dotted_names(nodes, is_import_from, until_node=None):
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])
+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.base_value import ContextSet, NO_CONTEXTS
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
@@ -41,11 +41,11 @@ class ModuleCache(object):
self._path_cache = {}
self._name_cache = {}
def add(self, string_names, context_set):
def add(self, string_names, value_set):
#path = module.py__file__()
#self._path_cache[path] = context_set
#self._path_cache[path] = value_set
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):
return self._name_cache[string_names]
@@ -57,12 +57,12 @@ class ModuleCache(object):
# This memoization is needed, because otherwise we will infinitely loop on
# certain imports.
@infer_state_method_cache(default=NO_CONTEXTS)
def infer_import(context, tree_name, is_goto=False):
module_context = context.get_root_context()
def infer_import(value, tree_name, is_goto=False):
module_value = value.get_root_value()
import_node = search_ancestor(tree_name, 'import_name', 'import_from')
import_path = import_node.get_path_for_name(tree_name)
from_import_name = None
infer_state = context.infer_state
infer_state = value.infer_state
try:
from_names = import_node.get_from_names()
except AttributeError:
@@ -76,7 +76,7 @@ def infer_import(context, tree_name, is_goto=False):
import_path = from_names
importer = Importer(infer_state, tuple(import_path),
module_context, import_node.level)
module_value, import_node.level)
types = importer.follow()
@@ -90,7 +90,7 @@ def infer_import(context, tree_name, is_goto=False):
types = unite(
t.py__getattribute__(
from_import_name,
name_context=context,
name_value=value,
is_goto=is_goto,
analysis_errors=False
)
@@ -102,7 +102,7 @@ def infer_import(context, tree_name, is_goto=False):
if not types:
path = import_path + [from_import_name]
importer = Importer(infer_state, tuple(path),
module_context, import_node.level)
module_value, import_node.level)
types = importer.follow()
# goto only accepts `Name`
if is_goto:
@@ -148,9 +148,9 @@ class NestedImportModule(tree.Module):
self._nested_import)
def _add_error(context, name, message):
if hasattr(name, 'parent') and context is not None:
analysis.add(context, 'import-error', name, message)
def _add_error(value, name, message):
if hasattr(name, 'parent') and value is not None:
analysis.add(value, 'import-error', name, message)
else:
debug.warning('ImportError without origin: ' + message)
@@ -183,7 +183,7 @@ def _level_to_base_import_path(project_path, directory, level):
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`
to actually follow the imports.
@@ -196,15 +196,15 @@ class Importer(object):
: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.level = level
self.module_context = module_context
self.module_value = module_value
self._fixed_sys_path = None
self._infer_possible = True
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
# Python import. This import has a properly defined module name
# chain like `foo.bar.baz` and an import in baz is made for
@@ -221,7 +221,7 @@ class Importer(object):
base = base[:-level + 1]
import_path = base + tuple(import_path)
else:
path = module_context.py__file__()
path = module_value.py__file__()
import_path = list(import_path)
if path is None:
# 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 import_path:
_add_error(
module_context, import_path[0],
module_value, import_path[0],
message='Attempted relative import beyond top-level package.'
)
else:
@@ -266,11 +266,11 @@ class Importer(object):
sys_path_mod = (
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:
file_path = self.module_context.py__file__()
file_path = self.module_value.py__file__()
if file_path is not None:
# Python2 uses an old strange way of importing relative imports.
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()
context_set = [None]
value_set = [None]
for i, name in enumerate(self.import_path):
context_set = ContextSet.from_sets([
value_set = ContextSet.from_sets([
self._infer_state.import_module(
import_names[:i+1],
parent_module_context,
parent_module_value,
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)
_add_error(self.module_context, name, message)
_add_error(self.module_value, name, message)
return NO_CONTEXTS
return context_set
return value_set
def _get_module_names(self, search_path=None, in_module=None):
"""
@@ -310,7 +310,7 @@ class Importer(object):
names = []
# add builtin module names
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()]
if search_path is None:
@@ -318,7 +318,7 @@ class Importer(object):
for name in iter_module_names(self._infer_state, search_path):
if in_module is None:
n = ImportName(self.module_context, name)
n = ImportName(self.module_value, name)
else:
n = SubModuleName(in_module, name)
names.append(n)
@@ -341,25 +341,25 @@ class Importer(object):
modname = mod.string_name
if modname.startswith('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``
for dir in self._sys_path_with_modifications():
flaskext = os.path.join(dir, 'flaskext')
if os.path.isdir(flaskext):
names += self._get_module_names([flaskext])
contexts = self.follow()
for context in contexts:
values = self.follow()
for value in values:
# Non-modules are not completable.
if context.api_type != 'module': # not a module
if value.api_type != 'module': # not a module
continue
names += context.sub_modules_dict().values()
names += value.sub_modules_dict().values()
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)
for c in both_contexts:
both_values = values | convert_values(values)
for c in both_values:
for filter in c.get_filters(search_global=False):
names += filter.values()
else:
@@ -374,7 +374,7 @@ class Importer(object):
@plugin_manager.decorate()
@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`.
"""
@@ -385,7 +385,7 @@ def import_module(infer_state, import_names, parent_module_context, sys_path):
return ContextSet([module])
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.
# Injecting the path directly into `find_module` did not work.
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
else:
try:
method = parent_module_context.py__path__
method = parent_module_value.py__path__
except AttributeError:
# The module is not a package.
return NO_CONTEXTS
@@ -421,7 +421,7 @@ def import_module(infer_state, import_names, parent_module_context, sys_path):
return NO_CONTEXTS
if isinstance(file_io_or_ns, ImplicitNSInfo):
from jedi.inference.context.namespace import ImplicitNamespaceContext
from jedi.inference.value.namespace import ImplicitNamespaceContext
module = ImplicitNamespaceContext(
infer_state,
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,
)
if parent_module_context is None:
if parent_module_value is None:
debug.dbg('global search_module %s: %s', import_names[-1], module)
else:
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
)
from jedi.inference.context import ModuleContext
from jedi.inference.value import ModuleContext
return ModuleContext(
infer_state, module_node,
file_io=file_io,
@@ -14,7 +14,7 @@ class AbstractLazyContext(object):
class LazyKnownContext(AbstractLazyContext):
"""data is a context."""
"""data is a value."""
def infer(self):
return ContextSet([self.data])
@@ -34,26 +34,26 @@ class LazyUnknownContext(AbstractLazyContext):
class LazyTreeContext(AbstractLazyContext):
def __init__(self, context, node):
def __init__(self, value, 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
# 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):
with monkeypatch(self.context, 'predefined_names', self._predefined_names):
return self.context.infer_node(self.data)
with monkeypatch(self.value, 'predefined_names', self._predefined_names):
return self.value.infer_node(self.data)
def get_merged_lazy_context(lazy_contexts):
if len(lazy_contexts) > 1:
return MergedLazyContexts(lazy_contexts)
def get_merged_lazy_value(lazy_values):
if len(lazy_values) > 1:
return MergedLazyContexts(lazy_values)
else:
return lazy_contexts[0]
return lazy_values[0]
class MergedLazyContexts(AbstractLazyContext):
"""data is a list of lazy contexts."""
"""data is a list of lazy values."""
def infer(self):
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):
start_pos = None
string_name = None
parent_context = None
parent_value = 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.
"""
@@ -32,7 +32,7 @@ class AbstractNameDefinition(object):
if qualified_names is None or not include_module_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:
return None
return module_names + qualified_names
@@ -41,8 +41,8 @@ class AbstractNameDefinition(object):
# By default, a name has no qualified names.
return None
def get_root_context(self):
return self.parent_context.get_root_context()
def get_root_value(self):
return self.parent_value.get_root_value()
def __repr__(self):
if self.start_pos is None:
@@ -55,7 +55,7 @@ class AbstractNameDefinition(object):
@property
def api_type(self):
return self.parent_context.api_type
return self.parent_value.api_type
class AbstractArbitraryName(AbstractNameDefinition):
@@ -64,20 +64,20 @@ class AbstractArbitraryName(AbstractNameDefinition):
string literals, which is not really a name, but for Jedi we use this
concept of Name for completions as well.
"""
is_context_name = False
is_value_name = False
def __init__(self, infer_state, string):
self.infer_state = infer_state
self.string_name = string
self.parent_context = infer_state.builtins_module
self.parent_value = infer_state.builtins_module
def infer(self):
return NO_CONTEXTS
class AbstractTreeName(AbstractNameDefinition):
def __init__(self, parent_context, tree_name):
self.parent_context = parent_context
def __init__(self, parent_value, tree_name):
self.parent_value = parent_value
self.tree_name = tree_name
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
# lookup.
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.
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))
@@ -97,13 +97,13 @@ class AbstractTreeName(AbstractNameDefinition):
return super(AbstractTreeName, self).get_qualified_names(include_module_names)
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:
return None
return parent_names + (self.tree_name.value,)
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):
imp = search_ancestor(self.tree_name, 'import_from', 'import_name')
@@ -120,28 +120,28 @@ class AbstractTreeName(AbstractNameDefinition):
class ContextNameMixin(object):
def infer(self):
return ContextSet([self._context])
return ContextSet([self._value])
def _get_qualified_names(self):
return self._context.get_qualified_names()
return self._value.get_qualified_names()
def get_root_context(self):
if self.parent_context is None: # A module
return self._context
return super(ContextNameMixin, self).get_root_context()
def get_root_value(self):
if self.parent_value is None: # A module
return self._value
return super(ContextNameMixin, self).get_root_value()
@property
def api_type(self):
return self._context.api_type
return self._value.api_type
class ContextName(ContextNameMixin, AbstractTreeName):
def __init__(self, context, tree_name):
super(ContextName, self).__init__(context.parent_context, tree_name)
self._context = context
def __init__(self, value, tree_name):
super(ContextName, self).__init__(value.parent_value, tree_name)
self._value = value
def goto(self):
return ContextSet([self._context.name])
return ContextSet([self._value.name])
class TreeNameDefinition(AbstractTreeName):
@@ -155,9 +155,9 @@ class TreeNameDefinition(AbstractTreeName):
def infer(self):
# Refactor this, should probably be here.
from jedi.inference.syntax_tree import tree_name_to_contexts
parent = self.parent_context
return tree_name_to_contexts(parent.infer_state, parent, self.tree_name)
from jedi.inference.syntax_tree import tree_name_to_values
parent = self.parent_value
return tree_name_to_values(parent.infer_state, parent, self.tree_name)
@property
def api_type(self):
@@ -241,16 +241,16 @@ class ParamName(BaseTreeParamName):
node = self.annotation_node
if node is None:
return NO_CONTEXTS
contexts = self.parent_context.parent_context.infer_node(node)
values = self.parent_value.parent_value.infer_node(node)
if execute_annotation:
contexts = contexts.execute_annotation()
return contexts
values = values.execute_annotation()
return values
def infer_default(self):
node = self.default_node
if node is None:
return NO_CONTEXTS
return self.parent_context.parent_context.infer_node(node)
return self.parent_value.parent_value.infer_node(node)
@property
def default_node(self):
@@ -297,7 +297,7 @@ class ParamName(BaseTreeParamName):
return self.get_param().infer()
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')
return params[param_node.position_index]
@@ -317,15 +317,15 @@ class ImportName(AbstractNameDefinition):
start_pos = (1, 0)
_level = 0
def __init__(self, parent_context, string_name):
self._from_module_context = parent_context
def __init__(self, parent_value, string_name):
self._from_module_value = parent_value
self.string_name = string_name
def get_qualified_names(self, include_module_names=False):
if include_module_names:
if self._level:
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:
return module_names
return module_names + (self.string_name,)
@@ -333,19 +333,19 @@ class ImportName(AbstractNameDefinition):
return ()
@property
def parent_context(self):
m = self._from_module_context
import_contexts = self.infer()
if not import_contexts:
def parent_value(self):
m = self._from_module_value
import_values = self.infer()
if not import_values:
return m
# It's almost always possible to find the import or to not find it. The
# importing returns only one context, pretty much always.
return next(iter(import_contexts))
# importing returns only one value, pretty much always.
return next(iter(import_values))
@memoize_method
def infer(self):
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()
def goto(self):
+48 -48
View File
@@ -3,46 +3,46 @@ from collections import defaultdict
from jedi import debug
from jedi.inference.utils import PushBackIterator
from jedi.inference import analysis
from jedi.inference.lazy_context import LazyKnownContext, \
from jedi.inference.lazy_value import LazyKnownContext, \
LazyTreeContext, LazyUnknownContext
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):
if isinstance(lazy_context, LazyTreeContext):
node = lazy_context.data
def _add_argument_issue(error_name, lazy_value, message):
if isinstance(lazy_value, LazyTreeContext):
node = lazy_value.data
if node.parent.type == 'argument':
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):
"""Fake a param and give it values."""
def __init__(self, execution_context, param_node, lazy_context, is_default=False):
self._execution_context = execution_context
def __init__(self, execution_value, param_node, lazy_value, is_default=False):
self._execution_value = execution_value
self._param_node = param_node
self._lazy_context = lazy_context
self._lazy_value = lazy_value
self.string_name = param_node.name.value
self._is_default = is_default
def infer_annotations(self):
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):
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()
if ann or doc_params:
return ann | doc_params
return self._lazy_context.infer()
return self._lazy_value.infer()
def matches_signature(self):
if self._is_default:
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:
return True
annotations = self.infer_annotations()
@@ -51,21 +51,21 @@ class ExecutedParam(object):
# that the signature matches.
return True
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())
debug.dbg("signature compare %s: %s <=> %s",
matches, argument_contexts, annotations, color='BLUE')
matches, argument_values, annotations, color='BLUE')
return matches
@property
def var_args(self):
return self._execution_context.var_args
return self._execution_value.var_args
def __repr__(self):
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):
m = _error_argument_count(funcdef, len(unpacked_va))
# 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]]
result_params = []
param_dict = {}
funcdef = execution_context.tree_node
# Default params are part of the context where the function was defined.
funcdef = execution_value.tree_node
# Default params are part of the value where the function was defined.
# This means that they might have access on class variables that the
# 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():
param_dict[param.name.value] = param
@@ -118,14 +118,14 @@ def get_executed_params_and_issues(execution_context, arguments):
had_multiple_value_error = True
m = ("TypeError: %s() got multiple values for keyword argument '%s'."
% (funcdef.name, key))
for contextualized_node in arguments.get_calling_nodes():
for valueualized_node in arguments.get_calling_nodes():
issues.append(
analysis.add(contextualized_node.context,
analysis.add(valueualized_node.value,
'type-error-multiple-values',
contextualized_node.node, message=m)
valueualized_node.node, message=m)
)
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))
try:
@@ -136,22 +136,22 @@ def get_executed_params_and_issues(execution_context, arguments):
if param.star_count == 1:
# *args param
lazy_context_list = []
lazy_value_list = []
if argument is not None:
lazy_context_list.append(argument)
lazy_value_list.append(argument)
for key, argument in var_arg_iterator:
# Iterate until a key argument is found.
if key:
var_arg_iterator.push_back((key, argument))
break
lazy_context_list.append(argument)
seq = iterable.FakeSequence(execution_context.infer_state, u'tuple', lazy_context_list)
lazy_value_list.append(argument)
seq = iterable.FakeSequence(execution_value.infer_state, u'tuple', lazy_value_list)
result_arg = LazyKnownContext(seq)
elif param.star_count == 2:
if argument is not None:
too_many_args(argument)
# **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)
non_matching_keys = {}
else:
@@ -161,24 +161,24 @@ def get_executed_params_and_issues(execution_context, arguments):
if param.default is None:
result_arg = LazyUnknownContext()
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))
issues.append(
analysis.add(
contextualized_node.context,
valueualized_node.value,
'type-error-too-few-arguments',
contextualized_node.node,
valueualized_node.node,
message=m,
)
)
else:
result_arg = LazyTreeContext(default_param_context, param.default)
result_arg = LazyTreeContext(default_param_value, param.default)
is_default = True
else:
result_arg = argument
result_params.append(ExecutedParam(
execution_context, param, result_arg,
execution_value, param, result_arg,
is_default=is_default
))
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
param.star_count or param.default):
# 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))
issues.append(
analysis.add(contextualized_node.context,
analysis.add(valueualized_node.value,
'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'." \
% (funcdef.name, key)
issues.append(
_add_argument_issue(
'type-error-keyword-argument',
lazy_context,
lazy_value,
message=m
)
)
remaining_arguments = list(var_arg_iterator)
if remaining_arguments:
first_key, lazy_context = remaining_arguments[0]
too_many_args(lazy_context)
first_key, lazy_value = remaining_arguments[0]
too_many_args(lazy_value)
return result_params, issues
@@ -232,22 +232,22 @@ def _error_argument_count(funcdef, 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:
result_arg = LazyKnownContext(
iterable.FakeSequence(execution_context.infer_state, u'tuple', [])
iterable.FakeSequence(execution_value.infer_state, u'tuple', [])
)
elif param.star_count == 2:
result_arg = LazyKnownContext(
iterable.FakeDict(execution_context.infer_state, {})
iterable.FakeDict(execution_value.infer_state, {})
)
elif param.default is None:
result_arg = LazyUnknownContext()
else:
result_arg = LazyTreeContext(execution_context.parent_context, param.default)
return ExecutedParam(execution_context, param, result_arg)
result_arg = LazyTreeContext(execution_value.parent_value, param.default)
return ExecutedParam(execution_value, param, result_arg)
def create_default_params(execution_context, funcdef):
return [_create_default_param(execution_context, p)
def create_default_params(execution_value, funcdef):
return [_create_default_param(execution_value, p)
for p in funcdef.get_params()]
+1 -1
View File
@@ -115,7 +115,7 @@ class ExecutionRecursionDetector(object):
self._recursion_level += 1
self._parent_execution_funcs.append(funcdef)
module = execution.get_root_context()
module = execution.get_root_value()
if module == self._infer_state.builtins_module:
# 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):
def __init__(self, context, is_bound=False):
self.context = context
def __init__(self, value, is_bound=False):
self.value = value
self.is_bound = is_bound
@property
def name(self):
return self.context.name
return self.value.name
@property
def annotation_string(self):
return ''
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:
return param_names[1:]
return param_names
def bind(self, context):
def bind(self, value):
raise NotImplementedError
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):
def __init__(self, context, function_context=None, is_bound=False):
super(TreeSignature, self).__init__(context, is_bound)
self._function_context = function_context or context
def __init__(self, value, function_value=None, is_bound=False):
super(TreeSignature, self).__init__(value, is_bound)
self._function_value = function_value or value
def bind(self, context):
return TreeSignature(context, self._function_context, is_bound=True)
def bind(self, value):
return TreeSignature(value, self._function_value, is_bound=True)
@property
def _annotation(self):
# Classes don't need annotations, even if __init__ has one. They always
# return themselves.
if self.context.is_class():
if self.value.is_class():
return None
return self._function_context.tree_node.annotation
return self._function_value.tree_node.annotation
@property
def annotation_string(self):
@@ -91,8 +91,8 @@ class TreeSignature(AbstractSignature):
class BuiltinSignature(AbstractSignature):
def __init__(self, context, return_string, is_bound=False):
super(BuiltinSignature, self).__init__(context, is_bound)
def __init__(self, value, return_string, is_bound=False):
super(BuiltinSignature, self).__init__(value, is_bound)
self._return_string = return_string
@property
@@ -100,12 +100,12 @@ class BuiltinSignature(AbstractSignature):
return self._return_string
@property
def _function_context(self):
return self.context
def _function_value(self):
return self.value
def bind(self, context):
def bind(self, value):
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):
+15 -15
View File
@@ -20,8 +20,8 @@ def _iter_nodes_for_param(param_name):
from parso.python.tree import search_ancestor
from jedi.inference.arguments import TreeArguments
execution_context = param_name.parent_context
function_node = execution_context.tree_node
execution_value = param_name.parent_value
function_node = execution_value.tree_node
module_node = function_node.get_root_node()
start = function_node.children[-1].start_pos
end = function_node.children[-1].end_pos
@@ -35,44 +35,44 @@ def _iter_nodes_for_param(param_name):
# anyway
trailer = search_ancestor(argument, 'trailer')
if trailer is not None: # Make sure we're in a function
context = execution_context.create_context(trailer)
if _goes_to_param_name(param_name, context, name):
contexts = _to_callables(context, trailer)
value = execution_value.create_value(trailer)
if _goes_to_param_name(param_name, value, name):
values = _to_callables(value, trailer)
args = TreeArguments.create_cached(
execution_context.infer_state,
context=context,
execution_value.infer_state,
value=value,
argument_node=trailer.children[1],
trailer=trailer,
)
for c in contexts:
for c in values:
yield c, args
else:
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':
return False
from jedi.inference.names import TreeNameDefinition
found = TreeNameDefinition(context, potential_name).goto()
return any(param_name.parent_context == p.parent_context
found = TreeNameDefinition(value, potential_name).goto()
return any(param_name.parent_value == p.parent_value
and param_name.start_pos == p.start_pos
for p in found)
def _to_callables(context, trailer):
def _to_callables(value, trailer):
from jedi.inference.syntax_tree import infer_trailer
atom_expr = trailer.parent
index = atom_expr.children[0] == 'await'
# 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:]:
if trailer == trailer2:
break
contexts = infer_trailer(context, contexts, trailer2)
return contexts
values = infer_trailer(value, values, trailer2)
return values
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 parser_utils
from jedi.inference.base_value import ContextSet, NO_CONTEXTS, ContextualizedNode, \
ContextualizedName, iterator_to_context_set, iterate_contexts
from jedi.inference.lazy_context import LazyTreeContext
ContextualizedName, iterator_to_value_set, iterate_values
from jedi.inference.lazy_value import LazyTreeContext
from jedi.inference import compiled
from jedi.inference import recursion
from jedi.inference import helpers
from jedi.inference import analysis
from jedi.inference import imports
from jedi.inference import arguments
from jedi.inference.context import ClassContext, FunctionContext
from jedi.inference.context import iterable
from jedi.inference.context import TreeInstance
from jedi.inference.value import ClassContext, FunctionContext
from jedi.inference.value import iterable
from jedi.inference.value import TreeInstance
from jedi.inference.finder import NameFinder
from jedi.inference.helpers import is_string, is_literal, is_number
from jedi.inference.compiled.access import COMPARISON_OPERATORS
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.context.decorator import Decoratee
from jedi.inference.value.decorator import Decoratee
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
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
can still go anther way in the future. Tests are there. ~ dave
"""
def wrapper(context, *args, **kwargs):
n = context.tree_node
infer_state = context.infer_state
def wrapper(value, *args, **kwargs):
n = value.tree_node
infer_state = value.infer_state
try:
infer_state.inferred_element_counts[n] += 1
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
except KeyError:
infer_state.inferred_element_counts[n] = 1
return func(context, *args, **kwargs)
return func(value, *args, **kwargs)
return wrapper
@@ -67,17 +67,17 @@ def _py__stop_iteration_returns(generators):
@debug.increase_indent
@_limit_context_infers
def infer_node(context, element):
debug.dbg('infer_node %s@%s in %s', element, element.start_pos, context)
infer_state = context.infer_state
@_limit_value_infers
def infer_node(value, element):
debug.dbg('infer_node %s@%s in %s', element, element.start_pos, value)
infer_state = value.infer_state
typ = element.type
if typ in ('name', 'number', 'string', 'atom', 'strings', 'keyword', 'fstring'):
return infer_atom(context, element)
return infer_atom(value, element)
elif typ == 'lambdef':
return ContextSet([FunctionContext.from_context(context, element)])
return ContextSet([FunctionContext.from_value(value, element)])
elif typ == 'expr_stmt':
return infer_expr_stmt(context, element)
return infer_expr_stmt(value, element)
elif typ in ('power', 'atom_expr'):
first_child = element.children[0]
children = element.children[1:]
@@ -86,35 +86,35 @@ def infer_node(context, element):
had_await = True
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):
if trailer == '**': # has a power operation.
right = context.infer_node(children[i + 1])
context_set = _infer_comparison(
right = value.infer_node(children[i + 1])
value_set = _infer_comparison(
infer_state,
context,
context_set,
value,
value_set,
trailer,
right
)
break
context_set = infer_trailer(context, context_set, trailer)
value_set = infer_trailer(value, value_set, trailer)
if had_await:
return context_set.py__await__().py__stop_iteration_returns()
return context_set
return value_set.py__await__().py__stop_iteration_returns()
return value_set
elif typ in ('testlist_star_expr', 'testlist',):
# 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'):
context_set = context.infer_node(element.children[-1])
value_set = value.infer_node(element.children[-1])
for operator in element.children[:-1]:
context_set = infer_factor(context_set, operator)
return context_set
value_set = infer_factor(value_set, operator)
return value_set
elif typ == 'test':
# `x if foo else y` case.
return (context.infer_node(element.children[0]) |
context.infer_node(element.children[-1]))
return (value.infer_node(element.children[0]) |
value.infer_node(element.children[-1]))
elif typ == 'operator':
# Must be an ellipsis, other operators are not inferred.
# 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))
return ContextSet([compiled.builtin_from_name(infer_state, u'Ellipsis')])
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]:
# TODO add search_global=True?
context_set = context_set.py__getattribute__(next_name, name_context=context)
return context_set
value_set = value_set.py__getattribute__(next_name, name_value=value)
return value_set
elif typ == 'eval_input':
return infer_node(context, element.children[0])
return infer_node(value, element.children[0])
elif typ == 'annassign':
return annotation.infer_annotation(context, element.children[1]) \
return annotation.infer_annotation(value, element.children[1]) \
.execute_annotation()
elif typ == 'yield_expr':
if len(element.children) and element.children[1].type == 'yield_arg':
# Implies that it's a yield from.
element = element.children[1].children[1]
generators = context.infer_node(element) \
generators = value.infer_node(element) \
.py__getattribute__('__iter__').execute_with_values()
return generators.py__stop_iteration_returns()
# Generator.send() is not implemented.
return NO_CONTEXTS
elif typ == 'namedexpr_test':
return infer_node(context, element.children[2])
return infer_node(value, element.children[2])
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]
if node == ')': # `arglist` is optional.
node = None
if trailer_op == '[':
trailer_op, node, _ = trailer.children
return atom_contexts.get_item(
infer_subscript_list(context.infer_state, context, node),
ContextualizedNode(context, trailer)
return atom_values.get_item(
infer_subscript_list(value.infer_state, value, node),
ContextualizedNode(value, trailer)
)
else:
debug.dbg('infer_trailer: %s in %s', trailer, atom_contexts)
debug.dbg('infer_trailer: %s in %s', trailer, atom_values)
if trailer_op == '.':
return atom_contexts.py__getattribute__(
name_context=context,
return atom_values.py__getattribute__(
name_value=value,
name_or_str=node
)
else:
assert trailer_op == '(', 'trailer_op is actually %s' % trailer_op
args = arguments.TreeArguments(context.infer_state, context, node, trailer)
return atom_contexts.execute(args)
args = arguments.TreeArguments(value.infer_state, value, node, trailer)
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
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.value in ('True', 'False', 'None'):
# 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.
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 in the module.
position = None
return context.py__getattribute__(
return value.py__getattribute__(
name_or_str=atom,
position=position,
search_global=True
@@ -207,7 +207,7 @@ def infer_atom(context, atom):
elif atom.type == 'keyword':
# For 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':
# print e.g. could be inferred like this in Python 2.7
return NO_CONTEXTS
@@ -218,24 +218,24 @@ def infer_atom(context, atom):
assert False, 'Cannot infer the keyword %s' % atom
elif isinstance(atom, tree.Literal):
string = context.infer_state.compiled_subprocess.safe_literal_eval(atom.value)
return ContextSet([compiled.create_simple_object(context.infer_state, string)])
string = value.infer_state.compiled_subprocess.safe_literal_eval(atom.value)
return ContextSet([compiled.create_simple_object(value.infer_state, string)])
elif atom.type == 'strings':
# 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:]:
right = infer_atom(context, string)
context_set = _infer_comparison(context.infer_state, context, context_set, u'+', right)
return context_set
right = infer_atom(value, string)
value_set = _infer_comparison(value.infer_state, value, value_set, u'+', right)
return value_set
elif atom.type == 'fstring':
return compiled.get_string_context_set(context.infer_state)
return compiled.get_string_value_set(value.infer_state)
else:
c = atom.children
# Parentheses without commas are not tuples.
if c[0] == '(' and not len(c) == 2 \
and not(c[1].type == 'testlist_comp' and
len(c[1].children) > 1):
return context.infer_node(c[1])
return value.infer_node(c[1])
try:
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'):
return ContextSet([iterable.comprehension_from_atom(
context.infer_state, context, atom
value.infer_state, value, atom
)])
# It's a dict/list/tuple literal.
@@ -262,36 +262,36 @@ def infer_atom(context, atom):
array_node_c = []
if c[0] == '{' and (array_node == '}' or ':' in array_node_c or
'**' in array_node_c):
context = iterable.DictLiteralContext(context.infer_state, context, atom)
new_value = iterable.DictLiteralContext(value.infer_state, value, atom)
else:
context = iterable.SequenceLiteralContext(context.infer_state, context, atom)
return ContextSet([context])
new_value = iterable.SequenceLiteralContext(value.infer_state, value, atom)
return ContextSet([new_value])
@_limit_context_infers
def infer_expr_stmt(context, stmt, seek_name=None):
with recursion.execution_allowed(context.infer_state, stmt) as allowed:
@_limit_value_infers
def infer_expr_stmt(value, stmt, seek_name=None):
with recursion.execution_allowed(value.infer_state, stmt) as allowed:
# Here we allow list/set to recurse under certain conditions. To make
# it possible to resolve stuff like list(set(list(x))), this is
# 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:
instance = context.var_args.instance
instance = value.var_args.instance
except AttributeError:
pass
else:
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:
allowed = True
if allowed:
return _infer_expr_stmt(context, stmt, seek_name)
return _infer_expr_stmt(value, stmt, seek_name)
return NO_CONTEXTS
@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
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)
rhs = stmt.get_rhs()
context_set = context.infer_node(rhs)
value_set = value.infer_node(rhs)
if seek_name:
c_node = ContextualizedName(context, seek_name)
context_set = check_tuple_assignments(context.infer_state, c_node, context_set)
c_node = ContextualizedName(value, seek_name)
value_set = check_tuple_assignments(value.infer_state, c_node, value_set)
first_operator = next(stmt.yield_operators(), None)
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.value = operator.value[:-1]
name = stmt.get_defined_names()[0].value
left = context.py__getattribute__(
left = value.py__getattribute__(
name, position=stmt.start_pos, search_global=True)
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):
# Iterate through result and add the values, that's possible
# only in for loops without clutter, because they are
# predictable. Also only do it, if the variable is not a tuple.
node = for_stmt.get_testlist()
cn = ContextualizedNode(context, node)
cn = ContextualizedNode(value, node)
ordered = list(cn.infer().iterate(cn))
for lazy_context in ordered:
dct = {for_stmt.children[1].value: lazy_context.infer()}
with helpers.predefine_names(context, for_stmt, dct):
t = context.infer_node(rhs)
left = _infer_comparison(context.infer_state, context, left, operator, t)
context_set = left
for lazy_value in ordered:
dct = {for_stmt.children[1].value: lazy_value.infer()}
with helpers.predefine_names(value, for_stmt, dct):
t = value.infer_node(rhs)
left = _infer_comparison(value.infer_state, value, left, operator, t)
value_set = left
else:
context_set = _infer_comparison(context.infer_state, context, left, operator, context_set)
debug.dbg('infer_expr_stmt result %s', context_set)
return context_set
value_set = _infer_comparison(value.infer_state, value, left, operator, value_set)
debug.dbg('infer_expr_stmt result %s', value_set)
return value_set
def infer_or_test(context, or_test):
def infer_or_test(value, or_test):
iterator = iter(or_test.children)
types = context.infer_node(next(iterator))
types = value.infer_node(next(iterator))
for operator in iterator:
right = next(iterator)
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)
if left_bools == {True}:
if operator == 'and':
types = context.infer_node(right)
types = value.infer_node(right)
elif left_bools == {False}:
if operator != 'and':
types = context.infer_node(right)
types = value.infer_node(right)
# Otherwise continue, because of uncertainty.
else:
types = _infer_comparison(context.infer_state, context, types, operator,
context.infer_node(right))
types = _infer_comparison(value.infer_state, value, types, operator,
value.infer_node(right))
debug.dbg('infer_or_test types %s', types)
return types
@iterator_to_context_set
def infer_factor(context_set, operator):
@iterator_to_value_set
def infer_factor(value_set, operator):
"""
Calculates `+`, `-`, `~` and `not` prefixes.
"""
for context in context_set:
for value in value_set:
if operator == '-':
if is_number(context):
yield context.negate()
if is_number(value):
yield value.negate()
elif operator == 'not':
value = context.py__bool__()
if value is None: # Uncertainty.
b = value.py__bool__()
if b is None: # Uncertainty.
return
yield compiled.create_simple_object(context.infer_state, not value)
yield compiled.create_simple_object(value.infer_state, not b)
else:
yield context
yield value
def _literals_to_types(infer_state, result):
@@ -397,22 +397,22 @@ def _literals_to_types(infer_state, result):
return new_result
def _infer_comparison(infer_state, context, left_contexts, operator, right_contexts):
if not left_contexts or not right_contexts:
def _infer_comparison(infer_state, value, left_values, operator, right_values):
if not left_values or not right_values:
# 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)
else:
# I don't think there's a reasonable chance that a string
# operation is still correct, once we pass something like six
# objects.
if len(left_contexts) * len(right_contexts) > 6:
return _literals_to_types(infer_state, left_contexts | right_contexts)
if len(left_values) * len(right_values) > 6:
return _literals_to_types(infer_state, left_values | right_values)
else:
return ContextSet.from_sets(
_infer_comparison_part(infer_state, context, left, operator, right)
for left in left_contexts
for right in right_contexts
_infer_comparison_part(infer_state, value, left, operator, right)
for left in left_values
for right in right_values
)
@@ -432,26 +432,26 @@ def _is_annotation_name(name):
return False
def _is_tuple(context):
return isinstance(context, iterable.Sequence) and context.array_type == 'tuple'
def _is_tuple(value):
return isinstance(value, iterable.Sequence) and value.array_type == 'tuple'
def _is_list(context):
return isinstance(context, iterable.Sequence) and context.array_type == 'list'
def _is_list(value):
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_)))
def _get_tuple_ints(context):
if not isinstance(context, iterable.SequenceLiteralContext):
def _get_tuple_ints(value):
if not isinstance(value, iterable.SequenceLiteralContext):
return None
numbers = []
for lazy_context in context.py__iter__():
if not isinstance(lazy_context, LazyTreeContext):
for lazy_value in value.py__iter__():
if not isinstance(lazy_value, LazyTreeContext):
return None
node = lazy_context.data
node = lazy_value.data
if node.type != 'number':
return None
try:
@@ -461,7 +461,7 @@ def _get_tuple_ints(context):
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)
r_is_num = is_number(right)
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'):
operation = COMPARISON_OPERATORS[str_operator]
bool_ = operation(left, right)
return ContextSet([_bool_to_context(infer_state, bool_)])
return ContextSet([_bool_to_value(infer_state, bool_)])
if isinstance(left, VersionInfo):
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,
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':
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 \
and not (check(left) or check(right)):
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))
result = ContextSet([left, right])
@@ -531,25 +531,25 @@ def _infer_comparison_part(infer_state, context, left, operator, right):
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.
Due to lazy type inference, statements like a = func; b = a; b() have to be
inferred.
"""
pep0484_contexts = \
annotation.find_type_from_comment_hint_assign(context, stmt, name)
if pep0484_contexts:
return pep0484_contexts
pep0484_values = \
annotation.find_type_from_comment_hint_assign(value, stmt, name)
if pep0484_values:
return pep0484_values
return infer_expr_stmt(context, stmt, seek_name=name)
return infer_expr_stmt(value, stmt, seek_name=name)
@plugin_manager.decorate()
def tree_name_to_contexts(infer_state, context, tree_name):
context_set = NO_CONTEXTS
module_node = context.get_root_context().tree_node
def tree_name_to_values(infer_state, value, tree_name):
value_set = NO_CONTEXTS
module_node = value.get_root_value().tree_node
# First check for annotations, like: `foo: int = 3`
if module_node is not None:
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
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:
context_set |= annotation.infer_annotation(
context, expr_stmt.children[1].children[1]
value_set |= annotation.infer_annotation(
value, expr_stmt.children[1].children[1]
).execute_annotation()
if context_set:
return context_set
if value_set:
return value_set
types = []
node = tree_name.get_definition(import_name_always=True)
if node is None:
node = tree_name.parent
if node.type == 'global_stmt':
context = infer_state.create_context(context, tree_name)
finder = NameFinder(infer_state, context, context, tree_name.value)
value = infer_state.create_value(value, tree_name)
finder = NameFinder(infer_state, value, value, tree_name.value)
filters = finder.get_filters(search_global=True)
# For global_stmt lookups, we only need the first possible scope,
# which means the function itself.
filters = [next(filters)]
return finder.find(filters, attribute_lookup=False)
elif node.type not in ('import_from', 'import_name'):
context = infer_state.create_context(context, tree_name)
return infer_atom(context, tree_name)
value = infer_state.create_value(value, tree_name)
return infer_atom(value, tree_name)
typ = node.type
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:
return types
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:
return types
if typ in ('for_stmt', 'comp_for', 'sync_comp_for'):
try:
types = context.predefined_names[node][tree_name.value]
types = value.predefined_names[node][tree_name.value]
except KeyError:
cn = ContextualizedNode(context, node.children[3])
for_types = iterate_contexts(
cn = ContextualizedNode(value, node.children[3])
for_types = iterate_values(
cn.infer(),
contextualized_node=cn,
valueualized_node=cn,
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)
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':
context_managers = context.infer_node(node.get_test_node_from_name(tree_name))
enter_methods = context_managers.py__getattribute__(u'__enter__')
value_managers = value.infer_node(node.get_test_node_from_name(tree_name))
enter_methods = value_managers.py__getattribute__(u'__enter__')
return enter_methods.execute_with_values()
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'):
types = _apply_decorators(context, node)
types = _apply_decorators(value, node)
elif typ == 'try_stmt':
# TODO an exception can also be a tuple. Check for those.
# TODO check for types that are not classes and add it to
# 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()
elif node.type == 'param':
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
# tree_node.
@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.
This is also the places where the decorators are processed.
"""
if node.type == 'classdef':
decoratee_context = ClassContext(
context.infer_state,
parent_context=context,
decoratee_value = ClassContext(
value.infer_state,
parent_value=value,
tree_node=node
)
else:
decoratee_context = FunctionContext.from_context(context, node)
initial = values = ContextSet([decoratee_context])
decoratee_value = FunctionContext.from_value(value, node)
initial = values = ContextSet([decoratee_value])
for dec in reversed(node.get_decorators()):
debug.dbg('decorator: %s %s', dec, values, color="MAGENTA")
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]
if trailer_nodes:
# Create a trailer and infer it.
trailer = tree.PythonNode('trailer', trailer_nodes)
trailer.parent = dec
dec_values = infer_trailer(context, dec_values, trailer)
dec_values = infer_trailer(value, dec_values, trailer)
if not len(dec_values):
code = dec.get_code(include_prefix=False)
@@ -670,41 +670,41 @@ def _apply_decorators(context, node):
debug.dbg('decorator end %s', values, color="MAGENTA")
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
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.
"""
lazy_context = None
for index, node in contextualized_name.assignment_indexes():
cn = ContextualizedNode(contextualized_name.context, node)
iterated = context_set.iterate(cn)
lazy_value = None
for index, node in valueualized_name.assignment_indexes():
cn = ContextualizedNode(valueualized_name.value, node)
iterated = value_set.iterate(cn)
if isinstance(index, slice):
# For no star unpacking is not possible.
return NO_CONTEXTS
for _ in range(index + 1):
try:
lazy_context = next(iterated)
lazy_value = next(iterated)
except StopIteration:
# 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
# index number is high. Therefore break if the loop is
# finished.
return NO_CONTEXTS
context_set = lazy_context.infer()
return context_set
value_set = lazy_value.infer()
return value_set
def infer_subscript_list(infer_state, context, index):
def infer_subscript_list(infer_state, value, index):
"""
Handles slices in subscript nodes.
"""
if index == ':':
# 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] == '.':
# 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 += [None] * (3 - len(result))
return ContextSet([iterable.Slice(context, *result)])
return ContextSet([iterable.Slice(value, *result)])
elif index.type == 'subscriptlist':
return ContextSet([iterable.SequenceLiteralContext(infer_state, context, index)])
return ContextSet([iterable.SequenceLiteralContext(infer_state, value, index)])
# 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
def _abs_path(module_context, path):
def _abs_path(module_value, path):
if os.path.isabs(path):
return path
module_path = module_context.py__file__()
module_path = module_value.py__file__()
if module_path is None:
# In this case we have no idea where we actually are in the file
# system.
@@ -26,7 +26,7 @@ def _abs_path(module_context, 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::
@@ -60,16 +60,16 @@ def _paths_from_assignment(module_context, expr_stmt):
except AssertionError:
continue
cn = ContextualizedNode(module_context.create_context(expr_stmt), expr_stmt)
for lazy_context in cn.infer().iterate(cn):
for context in lazy_context.infer():
if is_string(context):
abs_path = _abs_path(module_context, context.get_safe_value())
cn = ContextualizedNode(module_value.create_value(expr_stmt), expr_stmt)
for lazy_value in cn.infer().iterate(cn):
for value in lazy_value.infer():
if is_string(value):
abs_path = _abs_path(module_value, value.get_safe_value())
if abs_path is not None:
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" """
# Guarantee that both are trailers, the first one a name and the second one
# 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.
arg = arg.children[2]
for context in module_context.create_context(arg).infer_node(arg):
if is_string(context):
abs_path = _abs_path(module_context, context.get_safe_value())
for value in module_value.create_value(arg).infer_node(arg):
if is_string(value):
abs_path = _abs_path(module_value, value.get_safe_value())
if abs_path is not None:
yield abs_path
@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.
"""
@@ -108,12 +108,12 @@ def check_sys_path_modifications(module_context):
if n.type == 'name' and n.value == 'path':
yield name, power
if module_context.tree_node is None:
if module_value.tree_node is None:
return []
added = []
try:
possible_names = module_context.tree_node.get_used_names()['path']
possible_names = module_value.tree_node.get_used_names()['path']
except KeyError:
pass
else:
@@ -122,11 +122,11 @@ def check_sys_path_modifications(module_context):
if len(power.children) >= 4:
added.extend(
_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':
added.extend(_paths_from_assignment(module_context, expr_stmt))
added.extend(_paths_from_assignment(module_value, expr_stmt))
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)
return
from jedi.inference.context import ModuleContext
from jedi.inference.value import ModuleContext
module = ModuleContext(
infer_state, module_node, file_io,
string_names=None,
+7 -7
View File
@@ -26,22 +26,22 @@ def _dictionarize(names):
)
def _find_names(module_context, tree_name):
context = module_context.create_context(tree_name)
name = TreeNameDefinition(context, tree_name)
def _find_names(module_value, tree_name):
value = module_value.create_value(tree_name)
name = TreeNameDefinition(value, tree_name)
found_names = set(name.goto())
found_names.add(name)
return _dictionarize(_resolve_names(found_names))
def usages(module_context, tree_name):
def usages(module_value, tree_name):
search_name = tree_name.value
found_names = _find_names(module_context, tree_name)
modules = set(d.get_root_context() for d in found_names.values())
found_names = _find_names(module_value, tree_name)
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())
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, []):
new = _find_names(m, name_leaf)
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.base_value import ContextualizedNode, NO_CONTEXTS, \
ContextSet, TreeContext, ContextWrapper
from jedi.inference.lazy_context import LazyKnownContexts, LazyKnownContext, \
from jedi.inference.lazy_value import LazyKnownContexts, LazyKnownContext, \
LazyTreeContext
from jedi.inference.context import iterable
from jedi.inference.value import iterable
from jedi import parser_utils
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):
string_name = '<lambda>'
api_type = u'function'
def __init__(self, lambda_context):
self._lambda_context = lambda_context
self.parent_context = lambda_context.parent_context
def __init__(self, lambda_value):
self._lambda_value = lambda_value
self.parent_value = lambda_value.parent_value
@property
def start_pos(self):
return self._lambda_context.tree_node.start_pos
return self._lambda_value.tree_node.start_pos
def infer(self):
return ContextSet([self._lambda_context])
return ContextSet([self._lambda_value])
class FunctionAndClassBase(TreeContext):
def get_qualified_names(self):
if self.parent_context.is_class():
n = self.parent_context.get_qualified_names()
if self.parent_value.is_class():
n = self.parent_value.get_qualified_names()
if n is None:
# This means that the parent class lives within a function.
return None
return n + (self.py__name__(),)
elif self.parent_context.is_module():
elif self.parent_value.is_module():
return (self.py__name__(),)
else:
return None
@@ -59,7 +59,7 @@ class FunctionMixin(object):
if search_global:
yield ParserTreeFilter(
self.infer_state,
context=self,
value=self,
until_position=until_position,
origin_scope=origin_scope
)
@@ -69,8 +69,8 @@ class FunctionMixin(object):
for filter in instance.get_filters(search_global=False, origin_scope=origin_scope):
yield filter
def py__get__(self, instance, class_context):
from jedi.inference.context.instance import BoundMethod
def py__get__(self, instance, class_value):
from jedi.inference.value.instance import BoundMethod
if instance is None:
# Calling the Foo.bar results in the original bar function.
return ContextSet([self])
@@ -98,7 +98,7 @@ class FunctionMixin(object):
if arguments is None:
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):
return [TreeSignature(f) for f in self.get_signature_functions()]
@@ -109,27 +109,27 @@ class FunctionContext(use_metaclass(CachedMetaClass, FunctionMixin, FunctionAndC
return True
@classmethod
def from_context(cls, context, tree_node):
def from_value(cls, value, tree_node):
def create(tree_node):
if context.is_class():
if value.is_class():
return MethodContext(
context.infer_state,
context,
parent_context=parent_context,
value.infer_state,
value,
parent_value=parent_value,
tree_node=tree_node
)
else:
return cls(
context.infer_state,
parent_context=parent_context,
value.infer_state,
parent_value=parent_value,
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
while parent_context.is_class() or parent_context.is_instance():
parent_context = parent_context.parent_context
parent_value = value
while parent_value.is_class() or parent_value.is_instance():
parent_value = parent_value.parent_value
function = create(tree_node)
@@ -141,28 +141,28 @@ class FunctionContext(use_metaclass(CachedMetaClass, FunctionMixin, FunctionAndC
return function
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
def get_default_param_context(self):
return self.parent_context
def get_default_param_value(self):
return self.parent_value
def get_signature_functions(self):
return [self]
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)
self.class_context = class_context
self.class_value = class_value
def get_default_param_context(self):
return self.class_context
def get_default_param_value(self):
return self.class_value
def get_qualified_names(self):
# Need to implement this, because the parent context of a method
# context is not the class context but the module.
names = self.class_context.get_qualified_names()
# Need to implement this, because the parent value of a method
# value is not the class value but the module.
names = self.class_value.get_qualified_names()
if names is None:
return None
return names + (self.py__name__(),)
@@ -171,13 +171,13 @@ class MethodContext(FunctionContext):
class FunctionExecutionContext(TreeContext):
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__(
infer_state,
parent_context,
function_context.tree_node,
parent_value,
function_value.tree_node,
)
self.function_context = function_context
self.function_value = function_value
self.var_args = var_args
@infer_state_method_cache(default=NO_CONTEXTS)
@@ -188,17 +188,17 @@ class FunctionExecutionContext(TreeContext):
return self.infer_node(funcdef.children[-1])
if check_yields:
context_set = NO_CONTEXTS
value_set = NO_CONTEXTS
returns = get_yield_exprs(self.infer_state, funcdef)
else:
returns = funcdef.iter_return_stmts()
from jedi.inference.gradual.annotation import infer_return_types
context_set = infer_return_types(self)
if context_set:
value_set = infer_return_types(self)
if value_set:
# If there are annotations, prefer them over anything else.
# This will make it faster.
return context_set
context_set |= docstrings.infer_return_types(self.function_context)
return value_set
value_set |= docstrings.infer_return_types(self.function_value)
for r in returns:
check = flow_analysis.reachability_check(self, funcdef, r)
@@ -206,24 +206,24 @@ class FunctionExecutionContext(TreeContext):
debug.dbg('Return unreachable: %s', r)
else:
if check_yields:
context_set |= ContextSet.from_sets(
lazy_context.infer()
for lazy_context in self._get_yield_lazy_context(r)
value_set |= ContextSet.from_sets(
lazy_value.infer()
for lazy_value in self._get_yield_lazy_value(r)
)
else:
try:
children = r.children
except AttributeError:
ctx = compiled.builtin_from_name(self.infer_state, u'None')
context_set |= ContextSet([ctx])
value_set |= ContextSet([ctx])
else:
context_set |= self.infer_node(children[1])
value_set |= self.infer_node(children[1])
if check is flow_analysis.REACHABLE:
debug.dbg('Return reachable: %s', r)
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':
# `yield` just yields None.
ctx = compiled.builtin_from_name(self.infer_state, u'None')
@@ -233,13 +233,13 @@ class FunctionExecutionContext(TreeContext):
node = yield_expr.children[1]
if node.type == 'yield_arg': # It must be a yield from.
cn = ContextualizedNode(self, node.children[1])
for lazy_context in cn.infer().iterate(cn):
yield lazy_context
for lazy_value in cn.infer().iterate(cn):
yield lazy_value
else:
yield LazyTreeContext(self, node)
@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
for_parents = [(y, tree.search_ancestor(y, 'for_stmt', 'funcdef',
'while_stmt', 'if_stmt'))
@@ -273,24 +273,24 @@ class FunctionExecutionContext(TreeContext):
if for_stmt is None:
# No for_stmt, just normal 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
else:
input_node = for_stmt.get_testlist()
cn = ContextualizedNode(self, input_node)
ordered = cn.infer().iterate(cn)
ordered = list(ordered)
for lazy_context in ordered:
dct = {str(for_stmt.children[1].value): lazy_context.infer()}
for lazy_value in ordered:
dct = {str(for_stmt.children[1].value): lazy_value.infer()}
with helpers.predefine_names(self, for_stmt, dct):
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
def merge_yield_contexts(self, is_async=False):
def merge_yield_values(self, is_async=False):
return ContextSet.from_sets(
lazy_context.infer()
for lazy_context in self.get_yield_lazy_contexts()
lazy_value.infer()
for lazy_value in self.get_yield_lazy_values()
)
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 \
.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.
generics = (yield_contexts.py__class__(), NO_CONTEXTS)
generics = (yield_values.py__class__(), NO_CONTEXTS)
return ContextSet(
# In Python 3.6 AsyncGenerator is still a class.
GenericClass(c, generics)
@@ -347,9 +347,9 @@ class FunctionExecutionContext(TreeContext):
if infer_state.environment.version_info < (3, 5):
return NO_CONTEXTS
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.
generics = (return_contexts.py__class__(), NO_CONTEXTS, NO_CONTEXTS)
generics = (return_values.py__class__(), NO_CONTEXTS, NO_CONTEXTS)
return ContextSet(
GenericClass(c, generics) for c in async_classes
).execute_annotation()
@@ -366,9 +366,9 @@ class OverloadedFunctionContext(FunctionMixin, ContextWrapper):
self._overloaded_functions = overloaded_functions
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 = []
context_set = NO_CONTEXTS
value_set = NO_CONTEXTS
matched = False
for f in self._overloaded_functions:
function_execution = f.get_function_execution(arguments)
@@ -378,7 +378,7 @@ class OverloadedFunctionContext(FunctionMixin, ContextWrapper):
return function_execution.infer()
if matched:
return context_set
return value_set
if self.infer_state.is_analysis:
# In this case we want precision.
@@ -389,7 +389,7 @@ class OverloadedFunctionContext(FunctionMixin, ContextWrapper):
return self._overloaded_functions
def _find_overload_functions(context, tree_node):
def _find_overload_functions(value, tree_node):
def _is_overload_decorated(funcdef):
if funcdef.parent.type == 'decorated':
decorators = funcdef.parent.children[0]
@@ -400,7 +400,7 @@ def _find_overload_functions(context, tree_node):
for decorator in decorators:
dotted_name = decorator.children[1]
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 False
@@ -412,8 +412,8 @@ def _find_overload_functions(context, tree_node):
while True:
filter = ParserTreeFilter(
context.infer_state,
context,
value.infer_state,
value,
until_position=tree_node.start_pos
)
names = filter.get(tree_node.name.value)
@@ -3,21 +3,21 @@ from abc import abstractproperty
from jedi import debug
from jedi import settings
from jedi.inference import compiled
from jedi.inference.compiled.context import CompiledObjectFilter
from jedi.inference.helpers import contexts_from_qualified_names
from jedi.inference.compiled.value import CompiledObjectFilter
from jedi.inference.helpers import values_from_qualified_names
from jedi.inference.filters import AbstractFilter
from jedi.inference.names import ContextName, TreeNameDefinition
from jedi.inference.base_value import Context, NO_CONTEXTS, ContextSet, \
iterator_to_context_set, ContextWrapper
from jedi.inference.lazy_context import LazyKnownContext, LazyKnownContexts
iterator_to_value_set, ContextWrapper
from jedi.inference.lazy_value import LazyKnownContext, LazyKnownContexts
from jedi.inference.cache import infer_state_method_cache
from jedi.inference.arguments import AnonymousArguments, \
ValuesArguments, TreeArgumentsWrapper
from jedi.inference.context.function import \
from jedi.inference.value.function import \
FunctionContext, FunctionMixin, OverloadedFunctionContext
from jedi.inference.context.klass import ClassContext, apply_py__get__, \
from jedi.inference.value.klass import ClassContext, apply_py__get__, \
ClassFilter
from jedi.inference.context import iterable
from jedi.inference.value import iterable
from jedi.parser_utils import get_parent_scope
@@ -38,9 +38,9 @@ class AnonymousInstanceArguments(AnonymousArguments):
def __init__(self, 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
tree_params = execution_context.tree_node.get_params()
tree_params = execution_value.tree_node.get_params()
if not tree_params:
return [], []
@@ -50,9 +50,9 @@ class AnonymousInstanceArguments(AnonymousArguments):
# executions of this function, we have all the params already.
return [self_param], []
executed_params = list(search_params(
execution_context.infer_state,
execution_context,
execution_context.tree_node
execution_value.infer_state,
execution_value,
execution_value.tree_node
))
executed_params[0] = self_param
return executed_params, []
@@ -61,21 +61,21 @@ class AnonymousInstanceArguments(AnonymousArguments):
class AbstractInstanceContext(Context):
api_type = u'instance'
def __init__(self, infer_state, parent_context, class_context, var_args):
super(AbstractInstanceContext, self).__init__(infer_state, parent_context)
def __init__(self, infer_state, parent_value, class_value, var_args):
super(AbstractInstanceContext, self).__init__(infer_state, parent_value)
# Generated instances are classes that are just generated by self
# (No var_args) used.
self.class_context = class_context
self.class_value = class_value
self.var_args = var_args
def is_instance(self):
return True
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):
return self.class_context # This is the default.
return self.class_value # This is the default.
def py__call__(self, arguments):
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)
def py__class__(self):
return self.class_context
return self.class_value
def py__bool__(self):
# Signalize that we don't know about the bool type.
@@ -108,7 +108,7 @@ class AbstractInstanceContext(Context):
for name in names
)
def py__get__(self, obj, class_context):
def py__get__(self, obj, class_value):
"""
obj may be None.
"""
@@ -118,15 +118,15 @@ class AbstractInstanceContext(Context):
if names:
if obj is 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:
return ContextSet([self])
def get_filters(self, search_global=None, until_position=None,
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:
for cls in class_context.py__mro__():
for cls in class_value.py__mro__():
if not isinstance(cls, compiled.CompiledObject) \
or cls.tree_node is not None:
# In this case we're excluding compiled objects that are
@@ -134,7 +134,7 @@ class AbstractInstanceContext(Context):
# compiled objects to search for self variables.
yield SelfAttributeFilter(self.infer_state, self, cls, origin_scope)
class_filters = class_context.get_filters(
class_filters = class_value.get_filters(
search_global=False,
origin_scope=origin_scope,
is_instance=True,
@@ -148,21 +148,21 @@ class AbstractInstanceContext(Context):
# Propably from the metaclass.
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__')
if not names:
return super(AbstractInstanceContext, self).py__getitem__(
index_context_set,
contextualized_node,
index_value_set,
valueualized_node,
)
args = ValuesArguments([index_context_set])
args = ValuesArguments([index_value_set])
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__')
if not iter_slot_names:
return super(AbstractInstanceContext, self).py__iter__(contextualized_node)
return super(AbstractInstanceContext, self).py__iter__(valueualized_node)
def iterate():
for generator in self.execute_function_slots(iter_slot_names):
@@ -180,8 +180,8 @@ class AbstractInstanceContext(Context):
else:
debug.warning('Instance has no __next__ function in %s.', generator)
else:
for lazy_context in generator.py__iter__():
yield lazy_context
for lazy_value in generator.py__iter__():
yield lazy_value
return iterate()
@abstractproperty
@@ -192,88 +192,88 @@ class AbstractInstanceContext(Context):
for name in self.get_function_slot_names(u'__init__'):
# TODO is this correct? I think we need to check for functions.
if isinstance(name, LazyInstanceClassName):
function = FunctionContext.from_context(
self.parent_context,
function = FunctionContext.from_value(
self.parent_value,
name.tree_name.parent
)
bound_method = BoundMethod(self, function)
yield bound_method.get_function_execution(self.var_args)
@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'):
node = node.parent
scope = get_parent_scope(node)
if scope == class_context.tree_node:
return class_context
if scope == class_value.tree_node:
return class_value
else:
parent_context = self.create_instance_context(class_context, scope)
parent_value = self.create_instance_value(class_value, scope)
if scope.type == 'funcdef':
func = FunctionContext.from_context(
parent_context,
func = FunctionContext.from_value(
parent_value,
scope,
)
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)
else:
return bound_method.get_function_execution()
elif scope.type == 'classdef':
class_context = ClassContext(self.infer_state, parent_context, scope)
return class_context
class_value = ClassContext(self.infer_state, parent_value, scope)
return class_value
elif scope.type in ('comp_for', 'sync_comp_for'):
# 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:
raise NotImplementedError
return class_context
return class_value
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()]
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)
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
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
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):
key, lazy_context = next(self._original_var_args.unpack(), ('', None))
def get_first_non_keyword_argument_values(self):
key, lazy_value = next(self._original_var_args.unpack(), ('', None))
if key is not None:
return NO_CONTEXTS
return lazy_context.infer()
return lazy_value.infer()
def is_stub(self):
return False
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
# sounds more like something that should go to py__iter__.
if class_context.py__name__() in ['list', 'set'] \
and parent_context.get_root_context() == infer_state.builtins_module:
if class_value.py__name__() in ['list', 'set'] \
and parent_value.get_root_value() == infer_state.builtins_module:
# compare the module path with the builtin name.
if settings.dynamic_array_additions:
var_args = iterable.get_dynamic_array_instance(self, var_args)
super(TreeInstance, self).__init__(infer_state, parent_context,
class_context, var_args)
self.tree_node = class_context.tree_node
super(TreeInstance, self).__init__(infer_state, parent_value,
class_value, var_args)
self.tree_node = class_value.tree_node
@property
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
# to itself.
@@ -293,36 +293,36 @@ class TreeInstance(AbstractInstanceContext):
continue
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),
)
debug.dbg('Inferred instance context as %s', defined, color='BLUE')
debug.dbg('Inferred instance value as %s', defined, color='BLUE')
return defined
return None
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):
filter = next(self.class_context.get_filters())
filter = next(self.class_value.get_filters())
for init_name in filter.get('__init__'):
for init in init_name.infer():
if init.is_function():
for signature in init.get_signatures():
yield signature.context
yield signature.value
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__(
infer_state,
parent_context,
class_context,
parent_value,
class_value,
var_args=AnonymousInstanceArguments(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):
@@ -330,19 +330,19 @@ class CompiledInstanceName(compiled.CompiledName):
def __init__(self, infer_state, instance, klass, name):
super(CompiledInstanceName, self).__init__(
infer_state,
klass.parent_context,
klass.parent_value,
name.string_name
)
self._instance = instance
self._class_member_name = name
@iterator_to_context_set
@iterator_to_value_set
def infer(self):
for result_context in self._class_member_name.infer():
if result_context.api_type == 'function':
yield CompiledBoundMethod(result_context)
for result_value in self._class_member_name.infer():
if result_value.api_type == 'function':
yield CompiledBoundMethod(result_value)
else:
yield result_context
yield result_value
class CompiledInstanceClassFilter(AbstractFilter):
@@ -376,7 +376,7 @@ class BoundMethod(FunctionMixin, ContextWrapper):
return True
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
def _get_arguments(self, arguments):
@@ -390,8 +390,8 @@ class BoundMethod(FunctionMixin, ContextWrapper):
return super(BoundMethod, self).get_function_execution(arguments)
def py__call__(self, arguments):
if isinstance(self._wrapped_context, OverloadedFunctionContext):
return self._wrapped_context.py__call__(self._get_arguments(arguments))
if isinstance(self._wrapped_value, OverloadedFunctionContext):
return self._wrapped_value.py__call__(self._get_arguments(arguments))
function_execution = self.get_function_execution(arguments)
return function_execution.infer()
@@ -399,14 +399,14 @@ class BoundMethod(FunctionMixin, ContextWrapper):
def get_signature_functions(self):
return [
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):
return [sig.bind(self) for sig in super(BoundMethod, self).get_signatures()]
def __repr__(self):
return '<%s: %s>' % (self.__class__.__name__, self._wrapped_context)
return '<%s: %s>' % (self.__class__.__name__, self._wrapped_value)
class CompiledBoundMethod(ContextWrapper):
@@ -414,33 +414,33 @@ class CompiledBoundMethod(ContextWrapper):
return True
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):
"""
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.class_context = class_context
self.class_value = class_value
self.tree_name = tree_name
@property
def parent_context(self):
return self._instance.create_instance_context(self.class_context, self.tree_name)
def parent_value(self):
return self._instance.create_instance_value(self.class_value, self.tree_name)
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.class_context = class_context
self.class_value = class_value
self._class_member_name = class_member_name
@iterator_to_context_set
@iterator_to_value_set
def infer(self):
for result_context in self._class_member_name.infer():
for c in apply_py__get__(result_context, self._instance, self.class_context):
for result_value in self._class_member_name.infer():
for c in apply_py__get__(result_value, self._instance, self.class_value):
yield c
def __getattr__(self, name):
@@ -467,10 +467,10 @@ class InstanceClassFilter(AbstractFilter):
return self._convert(self._class_filter.values(from_instance=True))
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):
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):
@@ -479,15 +479,15 @@ class SelfAttributeFilter(ClassFilter):
"""
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__(
infer_state=infer_state,
context=context,
node_context=class_context,
value=value,
node_value=class_value,
origin_scope=origin_scope,
is_instance=True,
)
self._class_context = class_context
self._class_value = class_value
def _filter(self, names):
names = self._filter_self_names(names)
@@ -505,7 +505,7 @@ class SelfAttributeFilter(ClassFilter):
yield name
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):
return names
@@ -521,8 +521,8 @@ class InstanceArguments(TreeArgumentsWrapper):
for values in self._wrapped_arguments.unpack(func):
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):
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 analysis
from jedi.inference import recursion
from jedi.inference.lazy_context import LazyKnownContext, LazyKnownContexts, \
from jedi.inference.lazy_value import LazyKnownContext, LazyKnownContexts, \
LazyTreeContext
from jedi.inference.helpers import get_int_or_none, is_string, \
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, \
publish_method
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
@@ -48,7 +48,7 @@ class IterableMixin(object):
# 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
# 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.
# This mostly speeds up patterns like `sys.version_info >= (3, 0)` in
# typeshed.
@@ -56,7 +56,7 @@ class IterableMixin(object):
# Python 2...........
def get_safe_value(self, default=_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
else:
get_safe_value = Context.get_safe_value
@@ -65,7 +65,7 @@ class IterableMixin(object):
class GeneratorBase(LazyAttributeOverwrite, IterableMixin):
array_type = None
def _get_wrapped_context(self):
def _get_wrapped_value(self):
generator, = self.infer_state.typing_module \
.py__getattribute__('Generator') \
.execute_annotation()
@@ -78,14 +78,14 @@ class GeneratorBase(LazyAttributeOverwrite, IterableMixin):
return True
@publish_method('__iter__')
def py__iter__(self, contextualized_node=None):
def py__iter__(self, valueualized_node=None):
return ContextSet([self])
@publish_method('send')
@publish_method('next', python_version_match=2)
@publish_method('__next__', python_version_match=3)
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):
return ContextSet([compiled.builtin_from_name(self.infer_state, u'None')])
@@ -97,30 +97,30 @@ class GeneratorBase(LazyAttributeOverwrite, IterableMixin):
class Generator(GeneratorBase):
"""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)
self._func_execution_context = func_execution_context
self._func_execution_value = func_execution_value
def py__iter__(self, contextualized_node=None):
return self._func_execution_context.get_yield_lazy_contexts()
def py__iter__(self, valueualized_node=None):
return self._func_execution_value.get_yield_lazy_values()
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):
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):
@classmethod
def from_comp_for(cls, parent_context, comp_for):
return cls(parent_context.infer_state, parent_context, comp_for)
def from_comp_for(cls, parent_value, 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):
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]
test_list_comp = atom.children[1]
@@ -132,7 +132,7 @@ def comprehension_from_atom(infer_state, context, atom):
return DictComprehension(
infer_state,
context,
value,
sync_comp_for_node=sync_comp_for,
key_node=test_list_comp.children[0],
value_node=test_list_comp.children[2],
@@ -150,7 +150,7 @@ def comprehension_from_atom(infer_state, context, atom):
return cls(
infer_state,
defining_context=context,
defining_value=value,
sync_comp_for_node=sync_comp_for,
entry_node=test_list_comp.children[0],
)
@@ -158,37 +158,37 @@ def comprehension_from_atom(infer_state, context, atom):
class ComprehensionMixin(object):
@infer_state_method_cache()
def _get_comp_for_context(self, parent_context, comp_for):
return CompForContext.from_comp_for(parent_context, comp_for)
def _get_comp_for_value(self, parent_value, 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]
is_async = comp_for.parent.type == 'comp_for'
input_node = comp_for.children[3]
parent_context = parent_context or self._defining_context
input_types = parent_context.infer_node(input_node)
parent_value = parent_value or self._defining_value
input_types = parent_value.infer_node(input_node)
# 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)
exprlist = comp_for.children[1]
for i, lazy_context in enumerate(iterated):
types = lazy_context.infer()
dct = unpack_tuple_to_dict(parent_context, types, exprlist)
context_ = self._get_comp_for_context(
parent_context,
for i, lazy_value in enumerate(iterated):
types = lazy_value.infer()
dct = unpack_tuple_to_dict(parent_value, types, exprlist)
value_ = self._get_comp_for_value(
parent_value,
comp_for,
)
with predefine_names(context_, comp_for, dct):
with predefine_names(value_, comp_for, dct):
try:
for result in self._nested(comp_fors[1:], context_):
for result in self._nested(comp_fors[1:], value_):
yield result
except IndexError:
iterated = context_.infer_node(self._entry_node)
iterated = value_.infer_node(self._entry_node)
if self.array_type == 'dict':
yield iterated, context_.infer_node(self._value_node)
yield iterated, value_.infer_node(self._value_node)
else:
yield iterated
@@ -199,7 +199,7 @@ class ComprehensionMixin(object):
for result in self._nested(comp_fors):
yield result
def py__iter__(self, contextualized_node=None):
def py__iter__(self, valueualized_node=None):
for set_ in self._iterate():
yield LazyKnownContexts(set_)
@@ -209,7 +209,7 @@ class ComprehensionMixin(object):
class _DictMixin(object):
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):
@@ -222,7 +222,7 @@ class Sequence(LazyAttributeOverwrite, IterableMixin):
def _get_generics(self):
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
klass = compiled.builtin_from_name(self.infer_state, self.array_type)
c, = GenericClass(klass, self._get_generics()).execute_annotation()
@@ -238,17 +238,17 @@ class Sequence(LazyAttributeOverwrite, IterableMixin):
def parent(self):
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':
return self._dict_values()
return iterate_contexts(ContextSet([self]))
return iterate_values(ContextSet([self]))
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'
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._entry_node = entry_node
@@ -262,8 +262,8 @@ class ListComprehension(_BaseComprehension, Sequence):
all_types = list(self.py__iter__())
with reraise_getitem_errors(IndexError, TypeError):
lazy_context = all_types[index]
return lazy_context.infer()
lazy_value = all_types[index]
return lazy_value.infer()
class SetComprehension(_BaseComprehension, Sequence):
@@ -277,15 +277,15 @@ class GeneratorComprehension(_BaseComprehension, GeneratorBase):
class DictComprehension(ComprehensionMixin, Sequence):
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'
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._entry_node = key_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():
yield LazyKnownContexts(keys)
@@ -307,12 +307,12 @@ class DictComprehension(ComprehensionMixin, Sequence):
@publish_method('values')
def _imitate_values(self):
lazy_context = LazyKnownContexts(self._dict_values())
return ContextSet([FakeSequence(self.infer_state, u'list', [lazy_context])])
lazy_value = LazyKnownContexts(self._dict_values())
return ContextSet([FakeSequence(self.infer_state, u'list', [lazy_value])])
@publish_method('items')
def _imitate_items(self):
lazy_contexts = [
lazy_values = [
LazyKnownContext(
FakeSequence(
self.infer_state,
@@ -324,9 +324,9 @@ class DictComprehension(ComprehensionMixin, Sequence):
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()
def exact_key_items(self):
@@ -341,10 +341,10 @@ class SequenceLiteralContext(Sequence):
'[': u'list',
'{': u'set'}
def __init__(self, infer_state, defining_context, atom):
def __init__(self, infer_state, defining_value, atom):
super(SequenceLiteralContext, self).__init__(infer_state)
self.atom = atom
self._defining_context = defining_context
self._defining_value = defining_value
if self.atom.type in self._TUPLE_LIKE:
self.array_type = u'tuple'
@@ -357,14 +357,14 @@ class SequenceLiteralContext(Sequence):
if self.array_type == u'dict':
compiled_obj_index = compiled.create_simple_object(self.infer_state, index)
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:
method = k.execute_operation
except AttributeError:
pass
else:
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)
if isinstance(index, slice):
@@ -372,9 +372,9 @@ class SequenceLiteralContext(Sequence):
else:
with reraise_getitem_errors(TypeError, KeyError, IndexError):
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
function returns the value for a certain index.
@@ -383,7 +383,7 @@ class SequenceLiteralContext(Sequence):
# Get keys.
types = NO_CONTEXTS
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
# yield all the types.
for _ in types:
@@ -393,10 +393,10 @@ class SequenceLiteralContext(Sequence):
if node == ':' or node.type == 'subscript':
# TODO this should probably use at least part of the code
# of infer_subscript_list.
yield LazyKnownContext(Slice(self._defining_context, None, None, None))
yield LazyKnownContext(Slice(self._defining_value, None, None, None))
else:
yield LazyTreeContext(self._defining_context, node)
for addition in check_array_additions(self._defining_context, self):
yield LazyTreeContext(self._defining_value, node)
for addition in check_array_additions(self._defining_value, self):
yield addition
def py__len__(self):
@@ -405,7 +405,7 @@ class SequenceLiteralContext(Sequence):
def _dict_values(self):
return ContextSet.from_sets(
self._defining_context.infer_node(v)
self._defining_value.infer_node(v)
for k, v in self.get_tree_entries()
)
@@ -457,12 +457,12 @@ class SequenceLiteralContext(Sequence):
def exact_key_items(self):
"""
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 in self._defining_context.infer_node(key_node):
for key in self._defining_value.infer_node(key_node):
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):
return "<%s of %s>" % (self.__class__.__name__, self.atom)
@@ -471,35 +471,35 @@ class SequenceLiteralContext(Sequence):
class DictLiteralContext(_DictMixin, SequenceLiteralContext):
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)
self._defining_context = defining_context
self._defining_value = defining_value
self.atom = atom
@publish_method('values')
def _imitate_values(self):
lazy_context = LazyKnownContexts(self._dict_values())
return ContextSet([FakeSequence(self.infer_state, u'list', [lazy_context])])
lazy_value = LazyKnownContexts(self._dict_values())
return ContextSet([FakeSequence(self.infer_state, u'list', [lazy_value])])
@publish_method('items')
def _imitate_items(self):
lazy_contexts = [
lazy_values = [
LazyKnownContext(FakeSequence(
self.infer_state, u'tuple',
(LazyTreeContext(self._defining_context, key_node),
LazyTreeContext(self._defining_context, value_node))
(LazyTreeContext(self._defining_value, key_node),
LazyTreeContext(self._defining_value, value_node))
)) 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):
return ContextSet.from_sets(
self._defining_context.infer_node(k)
self._defining_value.infer_node(k)
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()
@@ -512,29 +512,29 @@ class _FakeArray(SequenceLiteralContext):
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"
"""
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):
if isinstance(index, slice):
return ContextSet([self])
with reraise_getitem_errors(IndexError, TypeError):
lazy_context = self._lazy_context_list[index]
return lazy_context.infer()
lazy_value = self._lazy_value_list[index]
return lazy_value.infer()
def py__iter__(self, contextualized_node=None):
return self._lazy_context_list
def py__iter__(self, valueualized_node=None):
return self._lazy_value_list
def py__bool__(self):
return bool(len(self._lazy_context_list))
return bool(len(self._lazy_value_list))
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):
@@ -542,7 +542,7 @@ class FakeDict(_DictMixin, _FakeArray):
super(FakeDict, self).__init__(infer_state, dct, u'dict')
self._dct = dct
def py__iter__(self, contextualized_node=None):
def py__iter__(self, valueualized_node=None):
for key in self._dct:
yield LazyKnownContext(compiled.create_simple_object(self.infer_state, key))
@@ -563,8 +563,8 @@ class FakeDict(_DictMixin, _FakeArray):
pass
with reraise_getitem_errors(KeyError, TypeError):
lazy_context = self._dct[index]
return lazy_context.infer()
lazy_value = self._dct[index]
return lazy_value.infer()
@publish_method('values')
def _values(self):
@@ -574,12 +574,12 @@ class FakeDict(_DictMixin, _FakeArray):
)])
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):
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()
def exact_key_items(self):
@@ -591,13 +591,13 @@ class MergedArray(_FakeArray):
super(MergedArray, self).__init__(infer_state, arrays, arrays[-1].array_type)
self._arrays = arrays
def py__iter__(self, contextualized_node=None):
def py__iter__(self, valueualized_node=None):
for array in self._arrays:
for lazy_context in array.py__iter__():
yield lazy_context
for lazy_value in array.py__iter__():
yield lazy_value
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):
for array in self._arrays:
@@ -608,33 +608,33 @@ class MergedArray(_FakeArray):
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.
"""
if exprlist.type == 'name':
return {exprlist.value: types}
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',
'testlist_star_expr'):
dct = {}
parts = iter(exprlist.children[::2])
n = 0
for lazy_context in types.iterate(exprlist):
for lazy_value in types.iterate(exprlist):
n += 1
try:
part = next(parts)
except StopIteration:
# TODO this context is probably not right.
analysis.add(context, 'value-error-too-many-values', part,
# TODO this value is probably not right.
analysis.add(value, 'value-error-too-many-values', part,
message="ValueError: too many values to unpack (expected %s)" % n)
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)
if types and has_parts is not None:
# TODO this context is probably not right.
analysis.add(context, 'value-error-too-few-values', has_parts,
# TODO this value is probably not right.
analysis.add(value, 'value-error-too-few-values', has_parts,
message="ValueError: need more than %s values to unpack" % n)
return dct
elif exprlist.type == 'power' or exprlist.type == 'atom_expr':
@@ -648,18 +648,18 @@ def unpack_tuple_to_dict(context, types, exprlist):
raise NotImplementedError
def check_array_additions(context, sequence):
def check_array_additions(value, sequence):
""" Just a mapper function for the internal _check_array_additions """
if sequence.array_type not in ('list', 'set'):
# TODO also check for dict updates
return NO_CONTEXTS
return _check_array_additions(context, sequence)
return _check_array_additions(value, sequence)
@infer_state_method_cache(default=NO_CONTEXTS)
@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:
@@ -669,22 +669,22 @@ def _check_array_additions(context, sequence):
from jedi.inference import arguments
debug.dbg('Dynamic array search for %s' % sequence, color='MAGENTA')
module_context = context.get_root_context()
if not settings.dynamic_array_additions or isinstance(module_context, compiled.CompiledObject):
module_value = value.get_root_value()
if not settings.dynamic_array_additions or isinstance(module_value, compiled.CompiledObject):
debug.dbg('Dynamic array search aborted.', color='MAGENTA')
return NO_CONTEXTS
def find_additions(context, arglist, add_name):
params = list(arguments.TreeArguments(context.infer_state, context, arglist).unpack())
def find_additions(value, arglist, add_name):
params = list(arguments.TreeArguments(value.infer_state, value, arglist).unpack())
result = set()
if add_name in ['insert']:
params = params[1:]
if add_name in ['append', 'add', 'insert']:
for key, lazy_context in params:
result.add(lazy_context)
for key, lazy_value in params:
result.add(lazy_value)
elif add_name in ['extend', 'update']:
for key, lazy_context in params:
result |= set(lazy_context.infer().iterate())
for key, lazy_value in params:
result |= set(lazy_value.infer().iterate())
return result
temp_param_add, settings.dynamic_params_for_other_modules = \
@@ -696,13 +696,13 @@ def _check_array_additions(context, sequence):
added_types = set()
for add_name in search_names:
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:
continue
else:
for name in possible_names:
context_node = context.tree_node
if not (context_node.start_pos < name.start_pos < context_node.end_pos):
value_node = value.tree_node
if not (value_node.start_pos < name.start_pos < value_node.end_pos):
continue
trailer = name.parent
power = trailer.parent
@@ -717,19 +717,19 @@ def _check_array_additions(context, sequence):
or execution_trailer.children[1] == ')':
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:
found = infer_call_of_leaf(
random_context,
random_value,
name,
cut_own_trailer=True
)
if sequence in found:
# The arrays match. Now add the results
added_types |= find_additions(
random_context,
random_value,
execution_trailer.children[1],
add_name
)
@@ -761,29 +761,29 @@ class _ArrayInstance(HelperContextMixin):
tuple_, = self.instance.infer_state.builtins_module.py__getattribute__('tuple')
return tuple_
def py__iter__(self, contextualized_node=None):
def py__iter__(self, valueualized_node=None):
var_args = self.var_args
try:
_, lazy_context = next(var_args.unpack())
_, lazy_value = next(var_args.unpack())
except StopIteration:
pass
else:
for lazy in lazy_context.infer().iterate():
for lazy in lazy_value.infer().iterate():
yield lazy
from jedi.inference import arguments
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:
yield addition
def iterate(self, contextualized_node=None, is_async=False):
return self.py__iter__(contextualized_node)
def iterate(self, valueualized_node=None, is_async=False):
return self.py__iter__(valueualized_node)
class Slice(object):
def __init__(self, context, start, stop, step):
self._context = context
def __init__(self, value, start, stop, step):
self._value = value
self._slice_object = None
# All of them are either a Precedence or None.
self._start = start
@@ -792,8 +792,8 @@ class Slice(object):
def __getattr__(self, name):
if self._slice_object is None:
context = compiled.builtin_from_name(self._context.infer_state, 'slice')
self._slice_object, = context.execute_with_values()
value = compiled.builtin_from_name(self._value.infer_state, 'slice')
self._slice_object, = value.execute_with_values()
return getattr(self._slice_object, name)
@property
@@ -806,14 +806,14 @@ class Slice(object):
if element is None:
return None
result = self._context.infer_node(element)
result = self._value.infer_node(element)
if len(result) != 1:
# For simplicity, we want slices to be clear defined with just
# one type. Otherwise we will return an empty slice object.
raise IndexError
context, = result
return get_int_or_none(context)
value, = result
return get_int_or_none(value)
try:
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__get__(call_object) Only on instances. Simulates
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, \
infer_state_method_generator_cache
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.names import TreeNameDefinition, ContextName
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
from jedi.inference.context.function import FunctionAndClassBase
from jedi.inference.value.function import FunctionAndClassBase
from jedi.plugins import plugin_manager
def apply_py__get__(context, instance, class_context):
def apply_py__get__(value, instance, class_value):
try:
method = context.py__get__
method = value.py__get__
except AttributeError:
yield context
yield value
else:
for descriptor_context in method(instance, class_context):
yield descriptor_context
for descriptor_value in method(instance, class_value):
yield descriptor_value
class ClassName(TreeNameDefinition):
def __init__(self, parent_context, tree_name, name_context, apply_decorators):
super(ClassName, self).__init__(parent_context, tree_name)
self._name_context = name_context
def __init__(self, parent_value, tree_name, name_value, apply_decorators):
super(ClassName, self).__init__(parent_value, tree_name)
self._name_value = name_value
self._apply_decorators = apply_decorators
@iterator_to_context_set
@iterator_to_value_set
def infer(self):
# We're using a different context to infer, so we cannot call super().
from jedi.inference.syntax_tree import tree_name_to_contexts
inferred = tree_name_to_contexts(
self.parent_context.infer_state, self._name_context, self.tree_name)
# We're using a different value to infer, so we cannot call super().
from jedi.inference.syntax_tree import tree_name_to_values
inferred = tree_name_to_values(
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:
for c in apply_py__get__(result_context,
for c in apply_py__get__(result_value,
instance=None,
class_context=self.parent_context):
class_value=self.parent_value):
yield c
else:
yield result_context
yield result_value
class ClassFilter(ParserTreeFilter):
@@ -95,9 +95,9 @@ class ClassFilter(ParserTreeFilter):
def _convert_names(self, names):
return [
self.name_class(
parent_context=self.context,
parent_value=self.value,
tree_name=name,
name_context=self._node_context,
name_value=self._node_value,
apply_decorators=not self._is_instance,
) for name in names
]
@@ -105,7 +105,7 @@ class ClassFilter(ParserTreeFilter):
def _equals_origin_scope(self):
node = self._origin_scope
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
node = get_cached_parent_scope(self._used_names, node)
return False
@@ -138,10 +138,10 @@ class ClassMixin(object):
return True
def py__call__(self, arguments=None):
from jedi.inference.context import TreeInstance
from jedi.inference.value import TreeInstance
if arguments is None:
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):
return compiled.builtin_from_name(self.infer_state, u'type')
@@ -154,9 +154,9 @@ class ClassMixin(object):
return self.name.string_name
def get_param_names(self):
for context_ in self.py__getattribute__(u'__init__'):
if context_.is_function():
return list(context_.get_param_names())[1:]
for value_ in self.py__getattribute__(u'__init__'):
if value_.is_function():
return list(value_.get_param_names())[1:]
return []
@infer_state_method_generator_cache()
@@ -208,7 +208,7 @@ class ClassMixin(object):
yield filter
else:
yield ClassFilter(
self.infer_state, self, node_context=cls,
self.infer_state, self, node_value=cls,
origin_scope=origin_scope,
is_instance=is_instance
)
@@ -231,7 +231,7 @@ class ClassMixin(object):
def get_global_filter(self, until_position=None, origin_scope=None):
return ParserTreeFilter(
self.infer_state,
context=self,
value=self,
until_position=until_position,
origin_scope=origin_scope
)
@@ -252,7 +252,7 @@ class ClassContext(use_metaclass(CachedMetaClass, ClassMixin, FunctionAndClassBa
continue # These are not relevant for this search.
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:
# The order matters and it's therefore a list.
found.append(type_var)
@@ -262,7 +262,7 @@ class ClassContext(use_metaclass(CachedMetaClass, ClassMixin, FunctionAndClassBa
arglist = self.tree_node.get_super_arglist()
if arglist:
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
@infer_state_method_cache(default=())
@@ -274,23 +274,23 @@ class ClassContext(use_metaclass(CachedMetaClass, ClassMixin, FunctionAndClassBa
return lst
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 [LazyKnownContexts(
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
if not index_context_set:
if not index_value_set:
return ContextSet([self])
return ContextSet(
LazyGenericClass(
self,
index_context,
context_of_index=contextualized_node.context,
index_value,
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):
@@ -326,15 +326,15 @@ class ClassContext(use_metaclass(CachedMetaClass, ClassMixin, FunctionAndClassBa
args = self._get_bases_arguments()
if args is not None:
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())
if metaclasses:
return metaclasses
for lazy_base in self.py__bases__():
for context in lazy_base.infer():
if context.is_class():
contexts = context.get_metaclasses()
if contexts:
return contexts
for value in lazy_base.infer():
if value.is_class():
values = value.get_metaclasses()
if values:
return values
return NO_CONTEXTS
@@ -8,7 +8,7 @@ from jedi.inference.filters import GlobalNameFilter, ParserTreeFilter, DictFilte
from jedi.inference import compiled
from jedi.inference.base_value import TreeContext
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.base_value import ContextSet
@@ -20,27 +20,27 @@ class _ModuleAttributeName(AbstractNameDefinition):
api_type = u'instance'
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_value = string_value
def infer(self):
if self._string_value is not None:
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):
s = s.encode('utf-8')
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):
start_pos = 1, 0
def __init__(self, context, name):
self._context = context
def __init__(self, value, name):
self._value = value
self._name = name
@property
@@ -102,7 +102,7 @@ class ModuleMixin(SubModuleDictMixin):
yield MergedFilter(
ParserTreeFilter(
self.infer_state,
context=self,
value=self,
until_position=until_position,
origin_scope=origin_scope
),
@@ -114,7 +114,7 @@ class ModuleMixin(SubModuleDictMixin):
yield star_filter
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
def is_module(self):
@@ -168,7 +168,7 @@ class ModuleMixin(SubModuleDictMixin):
new = Importer(
self.infer_state,
import_path=i.get_paths()[-1],
module_context=self,
module_value=self,
level=i.level
).follow()
@@ -182,19 +182,19 @@ class ModuleMixin(SubModuleDictMixin):
"""
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
qualified names on top for all context children.
qualified names on top for all value children.
"""
return ()
class ModuleContext(ModuleMixin, TreeContext):
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):
super(ModuleContext, self).__init__(
infer_state,
parent_context=None,
parent_value=None,
tree_node=module_node
)
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.names import ContextNameMixin, AbstractNameDefinition
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):
@@ -10,8 +10,8 @@ class ImplicitNSName(ContextNameMixin, AbstractNameDefinition):
Accessing names for implicit namespace packages should infer to nothing.
This object will prevent Jedi from raising exceptions
"""
def __init__(self, implicit_ns_context, string_name):
self._context = implicit_ns_context
def __init__(self, implicit_ns_value, string_name):
self._value = implicit_ns_value
self.string_name = string_name
@@ -23,10 +23,10 @@ class ImplicitNamespaceContext(Context, SubModuleDictMixin):
# folder foobar it will be available as an object:
# <module 'foobar' (namespace)>.
api_type = u'module'
parent_context = None
parent_value = None
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._fullname = fullname
self._paths = paths
+7 -7
View File
@@ -3,19 +3,19 @@ def import_module(callback):
Handle "magic" Flask extension imports:
``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'):
# New style.
ipath = (u'flask_' + import_names[2]),
context_set = callback(infer_state, ipath, None, *args, **kwargs)
if context_set:
return context_set
context_set = callback(infer_state, (u'flaskext',), None, *args, **kwargs)
value_set = callback(infer_state, ipath, None, *args, **kwargs)
if value_set:
return value_set
value_set = callback(infer_state, (u'flaskext',), None, *args, **kwargs)
return callback(
infer_state,
(u'flaskext', import_names[2]),
next(iter(context_set)),
next(iter(value_set)),
*args, **kwargs
)
return callback(infer_state, import_names, module_context, *args, **kwargs)
return callback(infer_state, import_names, module_value, *args, **kwargs)
return wrapper
+114 -114
View File
@@ -20,15 +20,15 @@ from jedi.inference.arguments import ValuesArguments, \
repack_with_argument_clinic, AbstractArguments, TreeArgumentsWrapper
from jedi.inference import analysis
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, \
NO_CONTEXTS, ContextSet, ContextWrapper, LazyContextWrapper
from jedi.inference.context import ClassContext, ModuleContext, \
from jedi.inference.value import ClassContext, ModuleContext, \
FunctionExecutionContext
from jedi.inference.context.klass import ClassMixin
from jedi.inference.context.function import FunctionMixin
from jedi.inference.context import iterable
from jedi.inference.lazy_context import LazyTreeContext, LazyKnownContext, \
from jedi.inference.value.klass import ClassMixin
from jedi.inference.value.function import FunctionMixin
from jedi.inference.value import iterable
from jedi.inference.lazy_value import LazyTreeContext, LazyKnownContext, \
LazyKnownContexts
from jedi.inference.names import ContextName, BaseTreeParamName
from jedi.inference.syntax_tree import is_string
@@ -105,34 +105,34 @@ _NAMEDTUPLE_FIELD_TEMPLATE = '''\
def execute(callback):
def wrapper(context, arguments):
def wrapper(value, arguments):
def call():
return callback(context, arguments=arguments)
return callback(value, arguments=arguments)
try:
obj_name = context.name.string_name
obj_name = value.name.string_name
except AttributeError:
pass
else:
if context.parent_context == context.infer_state.builtins_module:
if value.parent_value == value.infer_state.builtins_module:
module_name = 'builtins'
elif context.parent_context is not None and context.parent_context.is_module():
module_name = context.parent_context.py__name__()
elif value.parent_value is not None and value.parent_value.is_module():
module_name = value.parent_value.py__name__()
else:
return call()
if isinstance(context, BoundMethod):
if isinstance(value, BoundMethod):
if module_name == 'builtins':
if context.py__name__() == '__get__':
if context.class_context.py__name__() == 'property':
if value.py__name__() == '__get__':
if value.class_value.py__name__() == 'property':
return builtins_property(
context,
value,
arguments=arguments,
callback=call,
)
elif context.py__name__() in ('deleter', 'getter', 'setter'):
if context.class_context.py__name__() == 'property':
return ContextSet([context.instance])
elif value.py__name__() in ('deleter', 'getter', 'setter'):
if value.class_value.py__name__() == 'property':
return ContextSet([value.instance])
return call()
@@ -142,7 +142,7 @@ def execute(callback):
except KeyError:
pass
else:
return func(context, arguments=arguments, callback=call)
return func(value, arguments=arguments, callback=call)
return call()
return wrapper
@@ -150,14 +150,14 @@ def execute(callback):
def _follow_param(infer_state, arguments, index):
try:
key, lazy_context = list(arguments.unpack())[index]
key, lazy_value = list(arguments.unpack())[index]
except IndexError:
return NO_CONTEXTS
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_callback=False):
"""
@@ -173,8 +173,8 @@ def argument_clinic(string, want_obj=False, want_context=False,
assert not kwargs # Python 2...
debug.dbg('builtin start %s' % obj, color='MAGENTA')
result = NO_CONTEXTS
if want_context:
kwargs['context'] = arguments.context
if want_value:
kwargs['value'] = arguments.value
if want_obj:
kwargs['obj'] = obj
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)
def builtins_property(objects, types, obj, arguments):
property_args = obj.instance.var_args.unpack()
key, lazy_context = next(property_args, (None, None))
if key is not None or lazy_context is None:
key, lazy_value = next(property_args, (None, None))
if key is not None or lazy_value is None:
debug.warning('property expected a first param, not %s', arguments)
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)
@@ -252,7 +252,7 @@ class SuperInstance(LazyContextWrapper):
def _get_bases(self):
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()
if not objs:
# This is just a fallback and will only be used, if it's not
@@ -267,11 +267,11 @@ class SuperInstance(LazyContextWrapper):
yield f
@argument_clinic('[type[, obj]], /', want_context=True)
def builtins_super(types, objects, context):
if isinstance(context, FunctionExecutionContext):
if isinstance(context.var_args, InstanceArguments):
instance = context.var_args.instance
@argument_clinic('[type[, obj]], /', want_value=True)
def builtins_super(types, objects, value):
if isinstance(value, FunctionExecutionContext):
if isinstance(value.var_args, InstanceArguments):
instance = value.var_args.instance
# TODO if a class is given it doesn't have to be the direct super
# class, it can be an anecestor from long ago.
return ContextSet({SuperInstance(instance.infer_state, instance)})
@@ -285,14 +285,14 @@ class ReversedObject(AttributeOverwrite):
self._iter_list = iter_list
@publish_method('__iter__')
def py__iter__(self, contextualized_node=None):
def py__iter__(self, valueualized_node=None):
return self._iter_list
@publish_method('next', python_version_match=2)
@publish_method('__next__', python_version_match=3)
def py__next__(self):
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
# want static analysis to work well. Therefore we need to generated the
# values again.
key, lazy_context = next(arguments.unpack())
key, lazy_value = next(arguments.unpack())
cn = None
if isinstance(lazy_context, LazyTreeContext):
if isinstance(lazy_value, LazyTreeContext):
# TODO access private
cn = ContextualizedNode(lazy_context.context, lazy_context.data)
cn = ContextualizedNode(lazy_value.value, lazy_value.data)
ordered = list(sequences.iterate(cn))
# 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():
bool_results.add(cls_or_tup in mro)
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.
classes = ContextSet.from_sets(
lazy_context.infer()
for lazy_context in cls_or_tup.iterate()
lazy_value.infer()
for lazy_value in cls_or_tup.iterate()
)
bool_results.add(any(cls in mro for cls in classes))
else:
_, lazy_context = list(arguments.unpack())[1]
if isinstance(lazy_context, LazyTreeContext):
node = lazy_context.data
_, lazy_value = list(arguments.unpack())[1]
if isinstance(lazy_value, LazyTreeContext):
node = lazy_value.data
message = 'TypeError: isinstance() arg 2 must be a ' \
'class, type, or tuple of classes and types, ' \
'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(
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):
def get_object(self):
return self._wrapped_context
return self._wrapped_value
def py__get__(self, instance, klass):
return ContextSet([self._wrapped_context])
return ContextSet([self._wrapped_value])
@argument_clinic('sequence, /')
@@ -377,12 +377,12 @@ class ClassMethodObject(AttributeOverwrite, ContextWrapper):
self._function = function
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([
ClassMethodGet(__get__, class_context, self._function)
for __get__ in self._wrapped_context.py__getattribute__('__get__')
ClassMethodGet(__get__, class_value, self._function)
for __get__ in self._wrapped_value.py__getattribute__('__get__')
])
@@ -396,7 +396,7 @@ class ClassMethodGet(AttributeOverwrite, ContextWrapper):
return self._function.get_signatures()
def get_object(self):
return self._wrapped_context
return self._wrapped_value
def py__call__(self, arguments):
return self._function.execute(ClassMethodArguments(self._class, arguments))
@@ -441,18 +441,18 @@ def collections_namedtuple(obj, arguments, callback):
break
# TODO here we only use one of the types, we should use all.
param_contexts = _follow_param(infer_state, arguments, 1)
if not param_contexts:
param_values = _follow_param(infer_state, arguments, 1)
if not param_values:
return NO_CONTEXTS
_fields = list(param_contexts)[0]
_fields = list(param_values)[0]
string = get_str_or_none(_fields)
if string is not None:
fields = force_unicode(string).replace(',', ' ').split()
elif isinstance(_fields, iterable.Sequence):
fields = [
force_unicode(get_str_or_none(v))
for lazy_context in _fields.py__iter__()
for v in lazy_context.infer()
for lazy_value in _fields.py__iter__()
for v in lazy_value.infer()
]
fields = [f for f in fields if f is not None]
else:
@@ -472,30 +472,30 @@ def collections_namedtuple(obj, arguments, callback):
# Parse source code
module = infer_state.grammar.parse(code)
generated_class = next(module.iter_classdefs())
parent_context = ModuleContext(
parent_value = ModuleContext(
infer_state, module,
file_io=None,
string_names=None,
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):
def __init__(self, actual_context, arguments):
self._actual_context = actual_context
def __init__(self, actual_value, arguments):
self._actual_value = actual_value
self._arguments = arguments
def __getattr__(self, name):
return getattr(self._actual_context, name)
return getattr(self._actual_value, name)
def _get_function(self, unpacked_arguments):
key, lazy_context = next(unpacked_arguments, (None, None))
if key is not None or lazy_context is None:
key, lazy_value = next(unpacked_arguments, (None, None))
if key is not None or lazy_value is None:
debug.warning("Partial should have a proper function %s", self._arguments)
return None
return lazy_context.infer()
return lazy_value.infer()
def get_signatures(self):
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
# there.
next(unpacked)
for key_lazy_context in unpacked:
yield key_lazy_context
for key_lazy_context in self._call_arguments.unpack(funcdef):
yield key_lazy_context
for key_lazy_value in unpacked:
yield key_lazy_value
for key_lazy_value in self._call_arguments.unpack(funcdef):
yield key_lazy_value
def functools_partial(obj, arguments, callback):
@@ -564,9 +564,9 @@ def _return_first_param(firsts):
@argument_clinic('seq')
def _random_choice(sequences):
return ContextSet.from_sets(
lazy_context.infer()
lazy_value.infer()
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:
default = annassign.children[3]
param_names.append(DataclassParamName(
parent_context=cls.parent_context,
parent_value=cls.parent_value,
tree_name=name.tree_name,
annotation_node=annassign.children[1],
default_node=default,
@@ -606,8 +606,8 @@ class DataclassWrapper(ContextWrapper, ClassMixin):
class DataclassSignature(AbstractSignature):
def __init__(self, context, param_names):
super(DataclassSignature, self).__init__(context)
def __init__(self, value, param_names):
super(DataclassSignature, self).__init__(value)
self._param_names = param_names
def get_param_names(self, resolve_stars=False):
@@ -615,8 +615,8 @@ class DataclassSignature(AbstractSignature):
class DataclassParamName(BaseTreeParamName):
def __init__(self, parent_context, tree_name, annotation_node, default_node):
super(DataclassParamName, self).__init__(parent_context, tree_name)
def __init__(self, parent_value, tree_name, annotation_node, default_node):
super(DataclassParamName, self).__init__(parent_value, tree_name)
self.annotation_node = annotation_node
self.default_node = default_node
@@ -627,32 +627,32 @@ class DataclassParamName(BaseTreeParamName):
if self.annotation_node is None:
return NO_CONTEXTS
else:
return self.parent_context.infer_node(self.annotation_node)
return self.parent_value.infer_node(self.annotation_node)
class ItemGetterCallable(ContextWrapper):
def __init__(self, instance, args_context_set):
def __init__(self, instance, args_value_set):
super(ItemGetterCallable, self).__init__(instance)
self._args_context_set = args_context_set
self._args_value_set = args_value_set
@repack_with_argument_clinic('item, /')
def py__call__(self, item_context_set):
context_set = NO_CONTEXTS
for args_context in self._args_context_set:
lazy_contexts = list(args_context.py__iter__())
if len(lazy_contexts) == 1:
# TODO we need to add the contextualized context.
context_set |= item_context_set.get_item(lazy_contexts[0].infer(), None)
def py__call__(self, item_value_set):
value_set = NO_CONTEXTS
for args_value in self._args_value_set:
lazy_values = list(args_value.py__iter__())
if len(lazy_values) == 1:
# TODO we need to add the valueualized value.
value_set |= item_value_set.get_item(lazy_values[0].infer(), None)
else:
context_set |= ContextSet([iterable.FakeSequence(
self._wrapped_context.infer_state,
value_set |= ContextSet([iterable.FakeSequence(
self._wrapped_value.infer_state,
'list',
[
LazyKnownContexts(item_context_set.get_item(lazy_context.infer(), None))
for lazy_context in lazy_contexts
LazyKnownContexts(item_value_set.get_item(lazy_value.infer(), None))
for lazy_value in lazy_values
],
)])
return context_set
return value_set
@argument_clinic('func, /')
@@ -661,12 +661,12 @@ def _functools_wraps(funcs):
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
# decorator anyway.
@repack_with_argument_clinic('func, /')
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):
@@ -683,9 +683,9 @@ class Wrapped(ContextWrapper, FunctionMixin):
@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([
ItemGetterCallable(instance, args_context_set)
ItemGetterCallable(instance, args_value_set)
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)
def wrapper(strings, obj, arguments):
def iterate():
for context in strings:
s = get_str_or_none(context)
for value in strings:
s = get_str_or_none(value)
if s is not None:
s = func(s)
yield compiled.create_simple_object(context.infer_state, s)
contexts = ContextSet(iterate())
if contexts:
return contexts
yield compiled.create_simple_object(value.infer_state, s)
values = ContextSet(iterate())
if values:
return values
return obj.py__call__(arguments)
return wrapper
@@ -712,11 +712,11 @@ def _os_path_join(args_set, callback):
string = u''
sequence, = args_set
is_first = True
for lazy_context in sequence.py__iter__():
string_contexts = lazy_context.infer()
if len(string_contexts) != 1:
for lazy_value in sequence.py__iter__():
string_values = lazy_value.infer()
if len(string_values) != 1:
break
s = get_str_or_none(next(iter(string_contexts)))
s = get_str_or_none(next(iter(string_values)))
if s is None:
break
if not is_first:
@@ -792,8 +792,8 @@ def get_metaclass_filters(func):
def wrapper(cls, metaclasses):
for metaclass in metaclasses:
if metaclass.py__name__() == 'EnumMeta' \
and metaclass.get_root_context().py__name__() == 'enum':
filter_ = ParserTreeFilter(cls.infer_state, context=cls)
and metaclass.get_root_value().py__name__() == 'enum':
filter_ = ParserTreeFilter(cls.infer_state, value=cls)
return [DictFilter({
name.string_name: EnumInstance(cls, name).name for name in filter_.values()
})]
@@ -812,7 +812,7 @@ class EnumInstance(LazyContextWrapper):
def name(self):
return ContextName(self, self._name.tree_name)
def _get_wrapped_context(self):
def _get_wrapped_value(self):
obj, = self._cls.execute_with_values()
return obj
@@ -821,15 +821,15 @@ class EnumInstance(LazyContextWrapper):
name=compiled.create_simple_object(self.infer_state, self._name.string_name).name,
value=self._name,
))
for f in self._get_wrapped_context().get_filters():
for f in self._get_wrapped_value().get_filters():
yield f
def tree_name_to_contexts(func):
def wrapper(infer_state, context, tree_name):
if tree_name.value == 'sep' and context.is_module() and context.py__name__() == 'os.path':
def tree_name_to_values(func):
def wrapper(infer_state, value, tree_name):
if tree_name.value == 'sep' and value.is_module() and value.py__name__() == 'os.path':
return ContextSet({
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
+1 -1
View File
@@ -1,6 +1,6 @@
"""
Special cases of completions (typically special positions that caused issues
with context parsing.
with value parsing.
"""
def pass_decorator(func):
+1 -1
View File
@@ -36,7 +36,7 @@ definition = 0
str(def
# It might be hard to determine the context
# It might be hard to determine the value
class Foo(object):
@property
#? ['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 import parser_utils
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
@@ -225,14 +225,14 @@ class IntegrationTestCase(object):
parser = grammar36.parse(string, start_symbol='eval_input', error_recovery=False)
parser_utils.move(parser.get_root_node(), self.line_nr)
element = parser.get_root_node()
module_context = script._get_module()
# The context shouldn't matter for the test results.
user_context = get_user_scope(module_context, (self.line_nr, 0))
if user_context.api_type == 'function':
user_context = user_context.get_function_execution()
element.parent = user_context.tree_node
results = convert_contexts(
infer_state.infer_element(user_context, element),
module_value = script._get_module()
# The value shouldn't matter for the test results.
user_value = get_user_scope(module_value, (self.line_nr, 0))
if user_value.api_type == 'function':
user_value = user_value.get_function_execution()
element.parent = user_value.tree_node
results = convert_values(
infer_state.infer_element(user_value, element),
)
if not results:
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]
assert n.name == 'json'
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].type == 'module'
@@ -407,7 +407,7 @@ def test_import_alias(names):
assert len(ass) == 1
assert ass[0].name == 'json'
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):
+4 -4
View File
@@ -34,7 +34,7 @@ def test_in_empty_space(Script):
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
complete.
@@ -44,7 +44,7 @@ def test_indent_context(Script):
assert comp.name == 'isinstance'
def test_keyword_context(Script):
def test_keyword_value(Script):
def get_names(*args, **kwargs):
return [d.name for d in Script(*args, **kwargs).completions()]
@@ -101,8 +101,8 @@ def test_fake_subnodes(Script):
for i in range(2):
completions = Script('').completions()
c = get_str_completion(completions)
str_context, = c._name.infer()
n = len(str_context.tree_node.children[-1].children)
str_value, = c._name.infer()
n = len(str_value.tree_node.children[-1].children)
if i == 0:
limit = n
else:
+3 -3
View File
@@ -7,7 +7,7 @@ import pytest
import jedi
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
if py_version > 30:
@@ -101,8 +101,8 @@ def test_side_effect_completion():
side_effect = get_completion('SideEffectContainer', _GlobalNameSpace.__dict__)
# It's a class that contains MixedObject.
context, = side_effect._name.infer()
assert isinstance(context, mixed.MixedObject)
value, = side_effect._name.infer()
assert isinstance(value, mixed.MixedObject)
foo = get_completion('SideEffectContainer.foo', _GlobalNameSpace.__dict__)
assert foo.name == 'foo'
@@ -10,8 +10,8 @@ from ..helpers import cwd_at
def check_module_test(Script, code):
module_context = Script(code)._get_module()
return check_sys_path_modifications(module_context)
module_value = Script(code)._get_module()
return check_sys_path_modifications(module_value)
@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.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):
@@ -34,7 +34,7 @@ def test_next_docstr(infer_state):
next_ = compiled.builtin_from_name(infer_state, u'next')
assert next_.tree_node is not None
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__
@@ -44,7 +44,7 @@ def test_parse_function_doc_illegal_docstr():
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):
@@ -122,7 +122,7 @@ def _return_int():
('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
class C:
@@ -140,11 +140,11 @@ def test_parent_context(same_process_infer_state, attribute, expected_name, expe
)
x, = o.py__getattribute__(attribute)
assert x.py__name__() == expected_name
module_name = x.parent_context.py__name__()
module_name = x.parent_value.py__name__()
if module_name == '__builtin__':
module_name = 'builtins' # Python 2
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")
+2 -2
View File
@@ -13,9 +13,9 @@ def test_module_attributes(Script):
def test_module__file__(Script, environment):
assert not Script('__file__').goto_definitions()
def_, = Script('__file__', path='example.py').goto_definitions()
value = force_unicode(def_._name._context.get_safe_value())
value = force_unicode(def_._name._value.get_safe_value())
assert value.endswith('example.py')
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')
@@ -3,8 +3,8 @@ import os
import pytest
from parso.utils import PythonVersionInfo
from jedi.inference.gradual import typeshed, stub_context
from jedi.inference.context import TreeInstance, BoundMethod, FunctionContext, \
from jedi.inference.gradual import typeshed, stub_value
from jedi.inference.value import TreeInstance, BoundMethod, FunctionContext, \
MethodContext, ClassContext
TYPESHED_PYTHON3 = os.path.join(typeshed.TYPESHED_PATH, 'stdlib', '3')
@@ -47,15 +47,15 @@ def test_get_stub_files():
def test_function(Script, environment):
code = 'import threading; threading.current_thread'
def_, = Script(code).goto_definitions()
context = def_._name._context
assert isinstance(context, FunctionContext), context
value = def_._name._value
assert isinstance(value, FunctionContext), value
def_, = Script(code + '()').goto_definitions()
context = def_._name._context
assert isinstance(context, TreeInstance)
value = def_._name._value
assert isinstance(value, TreeInstance)
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):
@@ -69,33 +69,33 @@ def test_keywords_variable(Script):
def test_class(Script):
def_, = Script('import threading; threading.Thread').goto_definitions()
context = def_._name._context
assert isinstance(context, ClassContext), context
value = def_._name._value
assert isinstance(value, ClassContext), value
def test_instance(Script):
def_, = Script('import threading; threading.Thread()').goto_definitions()
context = def_._name._context
assert isinstance(context, TreeInstance)
value = def_._name._value
assert isinstance(value, TreeInstance)
def test_class_function(Script):
def_, = Script('import threading; threading.Thread.getName').goto_definitions()
context = def_._name._context
assert isinstance(context, MethodContext), context
value = def_._name._value
assert isinstance(value, MethodContext), value
def test_method(Script):
code = 'import threading; threading.Thread().getName'
def_, = Script(code).goto_definitions()
context = def_._name._context
assert isinstance(context, BoundMethod), context
assert isinstance(context._wrapped_context, MethodContext), context
value = def_._name._value
assert isinstance(value, BoundMethod), value
assert isinstance(value._wrapped_value, MethodContext), value
def_, = Script(code + '()').goto_definitions()
context = def_._name._context
assert isinstance(context, TreeInstance)
assert context.class_context.py__name__() == 'str'
value = def_._name._value
assert isinstance(value, TreeInstance)
assert value.class_value.py__name__() == 'str'
def test_sys_exc_info(Script):
@@ -125,7 +125,7 @@ def test_sys_getwindowsversion(Script, environment):
def test_sys_hexversion(Script):
script = Script('import sys; sys.hexversion')
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
def_, = script.goto_definitions()
assert def_.name == 'int'
@@ -134,8 +134,8 @@ def test_sys_hexversion(Script):
def test_math(Script):
def_, = Script('import math; math.acos()').goto_definitions()
assert def_.name == 'float'
context = def_._name._context
assert context
value = def_._name._value
assert value
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 imports
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
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):
sys_path = environment.get_sys_path() + [pkg_zip_path]
pkg, = Script(code, sys_path=sys_path).goto_definitions()
context, = pkg._name.infer()
assert context.py__file__() == os.path.join(pkg_zip_path, 'pkg', file)
assert '.'.join(context.py__package__()) == package
assert context.is_package is (path is not None)
value, = pkg._name.infer()
assert value.py__file__() == os.path.join(pkg_zip_path, 'pkg', file)
assert '.'.join(value.py__package__()) == package
assert value.is_package is (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):
@@ -156,8 +156,8 @@ def test_not_importable_file(Script):
def test_import_unique(Script):
src = "import os; os.path"
defs = Script(src, path='example.py').goto_definitions()
parent_contexts = [d._name._context for d in defs]
assert len(parent_contexts) == len(set(parent_contexts))
parent_values = [d._name._value for d in defs]
assert len(parent_values) == len(set(parent_values))
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)
def_, = script.goto_definitions()
assert def_.type == 'module'
context, = def_._name.infer()
assert not _stub_to_python_context_set(context)
value, = def_._name.infer()
assert not _stub_to_python_value_set(value)
@pytest.mark.parametrize(
+3 -3
View File
@@ -1,15 +1,15 @@
import pytest
from jedi.inference.context import TreeInstance
from jedi.inference.value import TreeInstance
def _infer_literal(Script, code, is_fstring=False):
def_, = Script(code).goto_definitions()
if is_fstring:
assert def_.name == 'str'
assert isinstance(def_._name._context, TreeInstance)
assert isinstance(def_._name._value, TreeInstance)
return ''
else:
return def_._name._context.get_safe_value()
return def_._name._value.get_safe_value()
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):
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):
+3 -3
View File
@@ -4,7 +4,7 @@ import re
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(
@@ -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.
d, = Script(code).goto_definitions()
context, = d._name.infer()
compiled, = _stub_to_python_context_set(context)
value, = d._name.infer()
compiled, = _stub_to_python_value_set(value)
signature, = compiled.get_signatures()
assert signature.to_string() == sig
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):
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):
+2 -2
View File
@@ -14,8 +14,8 @@ def auto_import_json(monkeypatch):
def test_base_auto_import_modules(auto_import_json, Script):
loads, = Script('import json; json.loads').goto_definitions()
assert isinstance(loads._name, ContextName)
context, = loads._name.infer()
assert isinstance(context.parent_context, StubModuleContext)
value, = loads._name.infer()
assert isinstance(value.parent_value, StubModuleContext)
def test_auto_import_modules_imports(auto_import_json, Script):