1
0
forked from VimPlug/jedi

Merge pull request #1572 from davidhalter/classvar

Remove is_class_value from infer_type_vars
This commit is contained in:
Dave Halter
2020-05-12 23:56:03 +02:00
committed by GitHub
8 changed files with 104 additions and 122 deletions
+3 -11
View File
@@ -268,7 +268,7 @@ class Value(HelperValueMixin):
def get_type_hint(self, add_class_info=True): def get_type_hint(self, add_class_info=True):
return None return None
def infer_type_vars(self, value_set, is_class_value=False): def infer_type_vars(self, value_set):
""" """
When the current instance represents a type annotation, this method When the current instance represents a type annotation, this method
tries to find information about undefined type vars and returns a dict tries to find information about undefined type vars and returns a dict
@@ -294,14 +294,6 @@ class Value(HelperValueMixin):
we're inferrined for, or (for recursive calls) their types. In the we're inferrined for, or (for recursive calls) their types. In the
above example this would first be the representation of the list above example this would first be the representation of the list
`[1]` and then, when recursing, just of `1`. `[1]` and then, when recursing, just of `1`.
`is_class_value`: tells us whether or not to treat the `value_set` as
representing the instances or types being passed, which is neccesary
to correctly cope with `Type[T]` annotations. When it is True, this
means that we are being called with a nested portion of an
annotation and that the `value_set` represents the types of the
arguments, rather than their actual instances. Note: not all
recursive calls will neccesarily set this to True.
""" """
return {} return {}
@@ -538,7 +530,7 @@ class ValueSet(object):
s = 'Optional[%s]' % s s = 'Optional[%s]' % s
return s return s
def infer_type_vars(self, value_set, is_class_value=False): def infer_type_vars(self, value_set):
# Circular # Circular
from jedi.inference.gradual.annotation import merge_type_var_dicts from jedi.inference.gradual.annotation import merge_type_var_dicts
@@ -546,7 +538,7 @@ class ValueSet(object):
for value in self._set: for value in self._set:
merge_type_var_dicts( merge_type_var_dicts(
type_var_dict, type_var_dict,
value.infer_type_vars(value_set, is_class_value), value.infer_type_vars(value_set),
) )
return type_var_dict return type_var_dict
+7 -12
View File
@@ -12,7 +12,7 @@ from parso import ParserSyntaxError, parse
from jedi._compatibility import force_unicode, Parameter from jedi._compatibility import force_unicode, Parameter
from jedi.inference.cache import inference_state_method_cache from jedi.inference.cache import inference_state_method_cache
from jedi.inference.base_value import ValueSet, NO_VALUES from jedi.inference.base_value import ValueSet, NO_VALUES
from jedi.inference.gradual.base import DefineGenericBase, GenericClass from jedi.inference.gradual.base import DefineGenericBaseClass, GenericClass
from jedi.inference.gradual.generics import TupleGenericManager from jedi.inference.gradual.generics import TupleGenericManager
from jedi.inference.gradual.type_var import TypeVar from jedi.inference.gradual.type_var import TypeVar
from jedi.inference.helpers import is_string from jedi.inference.helpers import is_string
@@ -229,7 +229,7 @@ def infer_return_types(function, arguments):
return ValueSet.from_sets( return ValueSet.from_sets(
ann.define_generics(type_var_dict) ann.define_generics(type_var_dict)
if isinstance(ann, (DefineGenericBase, TypeVar)) else ValueSet({ann}) if isinstance(ann, (DefineGenericBaseClass, TypeVar)) else ValueSet({ann})
for ann in annotation_values for ann in annotation_values
).execute_annotation() ).execute_annotation()
@@ -276,17 +276,17 @@ def infer_return_for_callable(arguments, param_values, result_values):
all_type_vars = {} all_type_vars = {}
for pv in param_values: for pv in param_values:
if pv.array_type == 'list': if pv.array_type == 'list':
type_var_dict = infer_type_vars_for_callable(arguments, pv.py__iter__()) type_var_dict = _infer_type_vars_for_callable(arguments, pv.py__iter__())
all_type_vars.update(type_var_dict) all_type_vars.update(type_var_dict)
return ValueSet.from_sets( return ValueSet.from_sets(
v.define_generics(all_type_vars) v.define_generics(all_type_vars)
if isinstance(v, (DefineGenericBase, TypeVar)) else ValueSet({v}) if isinstance(v, (DefineGenericBaseClass, TypeVar)) else ValueSet({v})
for v in result_values for v in result_values
).execute_annotation() ).execute_annotation()
def infer_type_vars_for_callable(arguments, lazy_params): def _infer_type_vars_for_callable(arguments, lazy_params):
""" """
Infers type vars for the Calllable class: Infers type vars for the Calllable class:
@@ -350,7 +350,7 @@ def merge_pairwise_generics(annotation_value, annotated_argument_class):
type_var_dict = {} type_var_dict = {}
if not isinstance(annotated_argument_class, DefineGenericBase): if not isinstance(annotated_argument_class, DefineGenericBaseClass):
return type_var_dict return type_var_dict
annotation_generics = annotation_value.get_generics() annotation_generics = annotation_value.get_generics()
@@ -359,12 +359,7 @@ def merge_pairwise_generics(annotation_value, annotated_argument_class):
for annotation_generics_set, actual_generic_set in zip(annotation_generics, actual_generics): for annotation_generics_set, actual_generic_set in zip(annotation_generics, actual_generics):
merge_type_var_dicts( merge_type_var_dicts(
type_var_dict, type_var_dict,
annotation_generics_set.infer_type_vars( annotation_generics_set.infer_type_vars(actual_generic_set.execute_annotation()),
actual_generic_set,
# This is a note to ourselves that we have already
# converted the instance representation to its class.
is_class_value=True,
),
) )
return type_var_dict return type_var_dict
+43 -20
View File
@@ -23,8 +23,8 @@ class _BoundTypeVarName(AbstractNameDefinition):
def iter_(): def iter_():
for value in self._value_set: for value in self._value_set:
# Replace any with the constraints if they are there. # Replace any with the constraints if they are there.
from jedi.inference.gradual.typing import Any from jedi.inference.gradual.typing import AnyClass
if isinstance(value, Any): if isinstance(value, AnyClass):
for constraint in self._type_var.constraints: for constraint in self._type_var.constraints:
yield constraint yield constraint
else: else:
@@ -81,7 +81,7 @@ class _AnnotatedClassContext(ClassContext):
yield self._value.get_type_var_filter() yield self._value.get_type_var_filter()
class DefineGenericBase(LazyValueWrapper): class DefineGenericBaseClass(LazyValueWrapper):
def __init__(self, generics_manager): def __init__(self, generics_manager):
self._generics_manager = generics_manager self._generics_manager = generics_manager
@@ -99,7 +99,7 @@ class DefineGenericBase(LazyValueWrapper):
for generic_set in self.get_generics(): for generic_set in self.get_generics():
values = NO_VALUES values = NO_VALUES
for generic in generic_set: for generic in generic_set:
if isinstance(generic, (DefineGenericBase, TypeVar)): if isinstance(generic, (DefineGenericBaseClass, TypeVar)):
result = generic.define_generics(type_var_dict) result = generic.define_generics(type_var_dict)
values |= result values |= result
if result != ValueSet({generic}): if result != ValueSet({generic}):
@@ -119,7 +119,7 @@ class DefineGenericBase(LazyValueWrapper):
)]) )])
def is_same_class(self, other): def is_same_class(self, other):
if not isinstance(other, DefineGenericBase): if not isinstance(other, DefineGenericBaseClass):
return False return False
if self.tree_node != other.tree_node: if self.tree_node != other.tree_node:
@@ -151,7 +151,7 @@ class DefineGenericBase(LazyValueWrapper):
) )
class GenericClass(ClassMixin, DefineGenericBase): class GenericClass(ClassMixin, DefineGenericBaseClass):
""" """
A class that is defined with generics, might be something simple like: A class that is defined with generics, might be something simple like:
@@ -200,29 +200,27 @@ class GenericClass(ClassMixin, DefineGenericBase):
return True return True
return self._class_value.is_sub_class_of(class_value) return self._class_value.is_sub_class_of(class_value)
def infer_type_vars(self, value_set, is_class_value=False): def infer_type_vars(self, value_set):
# Circular # Circular
from jedi.inference.gradual.annotation import merge_pairwise_generics, merge_type_var_dicts from jedi.inference.gradual.annotation import merge_pairwise_generics, merge_type_var_dicts
annotation_name = self.py__name__() annotation_name = self.py__name__()
type_var_dict = {} type_var_dict = {}
if annotation_name == 'Iterable' and not is_class_value: if annotation_name == 'Iterable':
annotation_generics = self.get_generics() annotation_generics = self.get_generics()
if annotation_generics: if annotation_generics:
return annotation_generics[0].infer_type_vars( return annotation_generics[0].infer_type_vars(
value_set.merge_types_of_iterate(), value_set.merge_types_of_iterate(),
) )
else: else:
# Note: we need to handle the MRO _in order_, so we need to extract # Note: we need to handle the MRO _in order_, so we need to extract
# the elements from the set first, then handle them, even if we put # the elements from the set first, then handle them, even if we put
# them back in a set afterwards. # them back in a set afterwards.
for py_class in value_set: for py_class in value_set:
if not is_class_value: if py_class.is_instance() and not py_class.is_compiled():
if py_class.is_instance() and not py_class.is_compiled(): py_class = py_class.get_annotated_class_object()
py_class = py_class.get_annotated_class_object() else:
else: continue
continue
if py_class.api_type != u'class': if py_class.api_type != u'class':
# Functions & modules don't have an MRO and we're not # Functions & modules don't have an MRO and we're not
@@ -332,10 +330,9 @@ class _PseudoTreeNameClass(Value):
yield EmptyFilter() yield EmptyFilter()
def py__class__(self): def py__class__(self):
# TODO this is obviously not correct, but at least gives us a class if # This might not be 100% correct, but it is good enough. The details of
# we have none. Some of these objects don't really have a base class in # the typing library are not really an issue for Jedi.
# typeshed. return builtin_from_name(self.inference_state, u'type')
return builtin_from_name(self.inference_state, u'object')
@property @property
def name(self): def name(self):
@@ -365,9 +362,9 @@ class BaseTypingValue(LazyValueWrapper):
return '%s(%s)' % (self.__class__.__name__, self._tree_name.value) return '%s(%s)' % (self.__class__.__name__, self._tree_name.value)
class BaseTypingValueWithGenerics(DefineGenericBase): class BaseTypingClassWithGenerics(DefineGenericBaseClass):
def __init__(self, parent_context, tree_name, generics_manager): def __init__(self, parent_context, tree_name, generics_manager):
super(BaseTypingValueWithGenerics, self).__init__(generics_manager) super(BaseTypingClassWithGenerics, self).__init__(generics_manager)
self.inference_state = parent_context.inference_state self.inference_state = parent_context.inference_state
self.parent_context = parent_context self.parent_context = parent_context
self._tree_name = tree_name self._tree_name = tree_name
@@ -378,3 +375,29 @@ class BaseTypingValueWithGenerics(DefineGenericBase):
def __repr__(self): def __repr__(self):
return '%s(%s%s)' % (self.__class__.__name__, self._tree_name.value, return '%s(%s%s)' % (self.__class__.__name__, self._tree_name.value,
self._generics_manager) self._generics_manager)
class BaseTypingInstance(LazyValueWrapper):
def __init__(self, parent_context, class_value, tree_name, generics_manager):
self.inference_state = class_value.inference_state
self.parent_context = parent_context
self._class_value = class_value
self._tree_name = tree_name
self._generics_manager = generics_manager
def py__class__(self):
return self._class_value
def get_annotated_class_object(self):
return self._class_value
@property
def name(self):
return ValueName(self, self._tree_name)
def _get_wrapped_value(self):
object_, = builtin_from_name(self.inference_state, u'object').execute_annotation()
return object_
def __repr__(self):
return '<%s: %s>' % (self.__class__.__name__, self._generics_manager)
+2 -4
View File
@@ -107,11 +107,9 @@ class TypeVar(BaseTypingValue):
def execute_annotation(self): def execute_annotation(self):
return self._get_classes().execute_annotation() return self._get_classes().execute_annotation()
def infer_type_vars(self, value_set, is_class_value=False): def infer_type_vars(self, value_set):
annotation_name = self.py__name__() annotation_name = self.py__name__()
if not is_class_value: return {annotation_name: value_set.py__class__()}
return {annotation_name: value_set.py__class__()}
return {annotation_name: value_set}
def __repr__(self): def __repr__(self):
return '<%s: %s>' % (self.__class__.__name__, self.py__name__()) return '<%s: %s>' % (self.__class__.__name__, self.py__name__())
+41 -72
View File
@@ -17,7 +17,8 @@ from jedi.inference.arguments import repack_with_argument_clinic
from jedi.inference.filters import FilterWrapper from jedi.inference.filters import FilterWrapper
from jedi.inference.names import NameWrapper, ValueName from jedi.inference.names import NameWrapper, ValueName
from jedi.inference.value.klass import ClassMixin from jedi.inference.value.klass import ClassMixin
from jedi.inference.gradual.base import BaseTypingValue, BaseTypingValueWithGenerics from jedi.inference.gradual.base import BaseTypingValue, \
BaseTypingClassWithGenerics, BaseTypingInstance
from jedi.inference.gradual.type_var import TypeVarClass from jedi.inference.gradual.type_var import TypeVarClass
from jedi.inference.gradual.generics import LazyGenericManager, TupleGenericManager from jedi.inference.gradual.generics import LazyGenericManager, TupleGenericManager
@@ -66,7 +67,7 @@ class TypingModuleName(NameWrapper):
yield TypeVarClass.create_cached( yield TypeVarClass.create_cached(
inference_state, self.parent_context, self.tree_name) inference_state, self.parent_context, self.tree_name)
elif name == 'Any': elif name == 'Any':
yield Any.create_cached( yield AnyClass.create_cached(
inference_state, self.parent_context, self.tree_name) inference_state, self.parent_context, self.tree_name)
elif name == 'TYPE_CHECKING': elif name == 'TYPE_CHECKING':
# This is needed for e.g. imports that are only available for type # This is needed for e.g. imports that are only available for type
@@ -84,7 +85,7 @@ class TypingModuleName(NameWrapper):
elif name == 'TypedDict': elif name == 'TypedDict':
# TODO doesn't even exist in typeshed/typing.py, yet. But will be # TODO doesn't even exist in typeshed/typing.py, yet. But will be
# added soon. # added soon.
yield TypedDictBase.create_cached( yield TypedDictClass.create_cached(
inference_state, self.parent_context, self.tree_name) inference_state, self.parent_context, self.tree_name)
elif name in ('no_type_check', 'no_type_check_decorator'): elif name in ('no_type_check', 'no_type_check_decorator'):
# This is not necessary, as long as we are not doing type checking. # This is not necessary, as long as we are not doing type checking.
@@ -100,7 +101,7 @@ class TypingModuleFilterWrapper(FilterWrapper):
name_wrapper_class = TypingModuleName name_wrapper_class = TypingModuleName
class TypingValueWithIndex(BaseTypingValueWithGenerics): class TypingClassWithIndex(BaseTypingClassWithGenerics):
def execute_annotation(self): def execute_annotation(self):
string_name = self._tree_name.value string_name = self._tree_name.value
@@ -129,6 +130,7 @@ class TypingValueWithIndex(BaseTypingValueWithGenerics):
cls = mapped[string_name] cls = mapped[string_name]
return ValueSet([cls( return ValueSet([cls(
self.parent_context, self.parent_context,
self,
self._tree_name, self._tree_name,
generics_manager=self._generics_manager, generics_manager=self._generics_manager,
)]) )])
@@ -137,7 +139,7 @@ class TypingValueWithIndex(BaseTypingValueWithGenerics):
return ValueSet.from_sets(self._generics_manager.to_tuple()) return ValueSet.from_sets(self._generics_manager.to_tuple())
def _create_instance_with_generics(self, generics_manager): def _create_instance_with_generics(self, generics_manager):
return TypingValueWithIndex( return TypingClassWithIndex(
self.parent_context, self.parent_context,
self._tree_name, self._tree_name,
generics_manager generics_manager
@@ -145,7 +147,7 @@ class TypingValueWithIndex(BaseTypingValueWithGenerics):
class ProxyTypingValue(BaseTypingValue): class ProxyTypingValue(BaseTypingValue):
index_class = TypingValueWithIndex index_class = TypingClassWithIndex
def with_generics(self, generics_tuple): def with_generics(self, generics_tuple):
return self.index_class.create_cached( return self.index_class.create_cached(
@@ -183,11 +185,8 @@ class _TypingClassMixin(ClassMixin):
return ValueName(self, self._tree_name) return ValueName(self, self._tree_name)
class TypingClassValueWithIndex(_TypingClassMixin, TypingValueWithIndex): class TypingClassValueWithIndex(_TypingClassMixin, TypingClassWithIndex):
def infer_type_vars(self, value_set, is_class_value=False): def infer_type_vars(self, value_set):
# Circular
from jedi.inference.gradual.annotation import merge_pairwise_generics, merge_type_var_dicts
type_var_dict = {} type_var_dict = {}
annotation_generics = self.get_generics() annotation_generics = self.get_generics()
@@ -196,49 +195,22 @@ class TypingClassValueWithIndex(_TypingClassMixin, TypingValueWithIndex):
annotation_name = self.py__name__() annotation_name = self.py__name__()
if annotation_name == 'Type': if annotation_name == 'Type':
if is_class_value: return annotation_generics[0].infer_type_vars(
# This only applies if we are comparing something like # This is basically a trick to avoid extra code: We execute the
# List[Type[int]] with Iterable[Type[int]]. First, Jedi tries to # incoming classes to be able to use the normal code for type
# match List/Iterable. After that we will land here, because # var inference.
# is_class_value will be True at that point. Obviously we also value_set.execute_annotation(),
# compare below that both sides are `Type`. )
for element in value_set:
element_name = element.py__name__()
if element_name == 'Type':
merge_type_var_dicts(
type_var_dict,
merge_pairwise_generics(self, element),
)
else:
return annotation_generics[0].infer_type_vars(
value_set,
is_class_value=True,
)
elif annotation_name == 'Callable': elif annotation_name == 'Callable':
if len(annotation_generics) == 2: if len(annotation_generics) == 2:
if is_class_value: return annotation_generics[1].infer_type_vars(
# This only applies if we are comparing something like value_set.execute_annotation(),
# List[Callable[..., T]] with Iterable[Callable[..., T]]. )
# First, Jedi tries to match List/Iterable. After that we
# will land here, because is_class_value will be True at
# that point. Obviously we also compare below that both
# sides are `Callable`.
for element in value_set:
element_name = element.py__name__()
if element_name == 'Callable':
merge_type_var_dicts(
type_var_dict,
merge_pairwise_generics(self, element),
)
else:
return annotation_generics[1].infer_type_vars(
value_set.execute_annotation(),
)
elif annotation_name == 'Tuple': elif annotation_name == 'Tuple':
tuple_annotation, = self.execute_annotation() tuple_annotation, = self.execute_annotation()
return tuple_annotation.infer_type_vars(value_set, is_class_value) return tuple_annotation.infer_type_vars(value_set)
return type_var_dict return type_var_dict
@@ -284,7 +256,7 @@ class TypeAlias(LazyValueWrapper):
return ValueSet([self._get_wrapped_value()]) return ValueSet([self._get_wrapped_value()])
class Callable(BaseTypingValueWithGenerics): class Callable(BaseTypingInstance):
def py__call__(self, arguments): def py__call__(self, arguments):
""" """
def x() -> Callable[[Callable[..., _T]], _T]: ... def x() -> Callable[[Callable[..., _T]], _T]: ...
@@ -301,7 +273,7 @@ class Callable(BaseTypingValueWithGenerics):
return infer_return_for_callable(arguments, param_values, result_values) return infer_return_for_callable(arguments, param_values, result_values)
class Tuple(BaseTypingValueWithGenerics): class Tuple(BaseTypingInstance):
def _is_homogenous(self): def _is_homogenous(self):
# To specify a variable-length tuple of homogeneous type, Tuple[T, ...] # To specify a variable-length tuple of homogeneous type, Tuple[T, ...]
# is used. # is used.
@@ -337,28 +309,23 @@ class Tuple(BaseTypingValueWithGenerics):
.py__getattribute__('tuple').execute_annotation() .py__getattribute__('tuple').execute_annotation()
return tuple_ return tuple_
def infer_type_vars(self, value_set, is_class_value=False): @property
def name(self):
return self._wrapped_value.name
def infer_type_vars(self, value_set):
# Circular # Circular
from jedi.inference.gradual.annotation import merge_pairwise_generics, merge_type_var_dicts from jedi.inference.gradual.annotation import merge_pairwise_generics, merge_type_var_dicts
from jedi.inference.gradual.base import GenericClass
value_set = value_set.filter( value_set = value_set.filter(
lambda x: x.py__name__().lower() == 'tuple', lambda x: x.py__name__().lower() == 'tuple',
) )
# Somewhat unusually, this `infer_type_vars` method is on an instance
# representation of a type, rather than the annotation or class
# representation. This means that as a starting point, we need to
# convert the incoming values to their instance style if they're
# classes, rather than the reverse.
if is_class_value:
value_set = value_set.execute_annotation()
if self._is_homogenous(): if self._is_homogenous():
# The parameter annotation is of the form `Tuple[T, ...]`, # The parameter annotation is of the form `Tuple[T, ...]`,
# so we treat the incoming tuple like a iterable sequence # so we treat the incoming tuple like a iterable sequence
# rather than a positional container of elements. # rather than a positional container of elements.
return self.get_generics()[0].infer_type_vars( return self._class_value.get_generics()[0].infer_type_vars(
value_set.merge_types_of_iterate(), value_set.merge_types_of_iterate(),
) )
@@ -370,30 +337,32 @@ class Tuple(BaseTypingValueWithGenerics):
type_var_dict = {} type_var_dict = {}
for element in value_set: for element in value_set:
if not is_class_value: try:
py_class = element.get_annotated_class_object() method = element.get_annotated_class_object
if not isinstance(py_class, GenericClass): except AttributeError:
py_class = element # This might still happen, because the tuple name matching
else: # above is not 100% correct, so just catch the remaining
py_class = element # cases here.
continue
py_class = method()
merge_type_var_dicts( merge_type_var_dicts(
type_var_dict, type_var_dict,
merge_pairwise_generics(self, py_class), merge_pairwise_generics(self._class_value, py_class),
) )
return type_var_dict return type_var_dict
class Generic(BaseTypingValueWithGenerics): class Generic(BaseTypingInstance):
pass pass
class Protocol(BaseTypingValueWithGenerics): class Protocol(BaseTypingInstance):
pass pass
class Any(BaseTypingValue): class AnyClass(BaseTypingValue):
def execute_annotation(self): def execute_annotation(self):
debug.warning('Used Any - returned no results') debug.warning('Used Any - returned no results')
return NO_VALUES return NO_VALUES
@@ -447,7 +416,7 @@ class CastFunction(BaseTypingValue):
return type_value_set.execute_annotation() return type_value_set.execute_annotation()
class TypedDictBase(BaseTypingValue): class TypedDictClass(BaseTypingValue):
""" """
This class has no responsibilities and is just here to make sure that typed This class has no responsibilities and is just here to make sure that typed
dicts can be identified. dicts can be identified.
+2 -2
View File
@@ -241,7 +241,7 @@ class ClassMixin(object):
def is_typeddict(self): def is_typeddict(self):
# TODO Do a proper mro resolution. Currently we are just listing # TODO Do a proper mro resolution. Currently we are just listing
# classes. However, it's a complicated algorithm. # classes. However, it's a complicated algorithm.
from jedi.inference.gradual.typing import TypedDictBase from jedi.inference.gradual.typing import TypedDictClass
for lazy_cls in self.py__bases__(): for lazy_cls in self.py__bases__():
if not isinstance(lazy_cls, LazyTreeValue): if not isinstance(lazy_cls, LazyTreeValue):
return False return False
@@ -253,7 +253,7 @@ class ClassMixin(object):
return False return False
for cls in lazy_cls.infer(): for cls in lazy_cls.infer():
if isinstance(cls, TypedDictBase): if isinstance(cls, TypedDictClass):
return True return True
try: try:
method = cls.is_typeddict method = cls.is_typeddict
@@ -10,6 +10,7 @@ from typing import (
Type, Type,
TypeVar, TypeVar,
Union, Union,
Sequence,
) )
K = TypeVar('K') K = TypeVar('K')
@@ -165,6 +166,9 @@ some_str = NotImplemented # type: str
#? str() #? str()
first(some_str) first(some_str)
annotated = [len] # type: List[ Callable[[Sequence[float]], int] ]
#? int()
first(annotated)()
# Test that the right type is chosen when a partially realised mapping is expected # Test that the right type is chosen when a partially realised mapping is expected
def values(mapping: Mapping[int, T]) -> List[T]: def values(mapping: Mapping[int, T]) -> List[T]:
+2 -1
View File
@@ -656,7 +656,8 @@ def bar():
({'return': 'typing.Optional[str, int]'}, [], ''), # Takes only one arg ({'return': 'typing.Optional[str, int]'}, [], ''), # Takes only one arg
({'return': 'typing.Any'}, [], ''), ({'return': 'typing.Any'}, [], ''),
({'return': 'typing.Tuple[int, str]'}, ['tuple'], ''), ({'return': 'typing.Tuple[int, str]'},
['Tuple' if sys.version_info[:2] == (3, 6) else 'tuple'], ''),
({'return': 'typing.Tuple[int, str]'}, ['int'], 'x()[0]'), ({'return': 'typing.Tuple[int, str]'}, ['int'], 'x()[0]'),
({'return': 'typing.Tuple[int, str]'}, ['str'], 'x()[1]'), ({'return': 'typing.Tuple[int, str]'}, ['str'], 'x()[1]'),
({'return': 'typing.Tuple[int, str]'}, [], 'x()[2]'), ({'return': 'typing.Tuple[int, str]'}, [], 'x()[2]'),