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