forked from VimPlug/jedi
context -> value
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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()
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user