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