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
+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