diff options
-rw-r--r-- | Lib/test/test_typing.py | 13 | ||||
-rw-r--r-- | Lib/typing.py | 68 | ||||
-rw-r--r-- | Misc/NEWS | 6 |
3 files changed, 61 insertions, 26 deletions
diff --git a/Lib/test/test_typing.py b/Lib/test/test_typing.py index a7f8dd5..72afe67 100644 --- a/Lib/test/test_typing.py +++ b/Lib/test/test_typing.py @@ -512,6 +512,10 @@ class CallableTests(BaseTestCase): self.assertEqual(get_type_hints(foo, globals(), locals()), {'a': Callable[..., T]}) + def test_ellipsis_in_generic(self): + # Shouldn't crash; see https://github.com/python/typing/issues/259 + typing.List[Callable[..., str]] + XK = TypeVar('XK', str, bytes) XV = TypeVar('XV') @@ -852,7 +856,7 @@ class VarianceTests(BaseTestCase): def test_covariance_sequence(self): # Check covariance for Sequence (which is just a generic class - # for this purpose, but using a covariant type variable). + # for this purpose, but using a type variable with covariant=True). self.assertIsSubclass(typing.Sequence[Manager], typing.Sequence[Employee]) self.assertNotIsSubclass(typing.Sequence[Employee], @@ -1185,6 +1189,13 @@ class CollectionsAbcTests(BaseTestCase): self.assertIsInstance([], typing.Container) self.assertNotIsInstance(42, typing.Container) + def test_collection(self): + if hasattr(typing, 'Collection'): + self.assertIsInstance(tuple(), typing.Collection) + self.assertIsInstance(frozenset(), typing.Collection) + self.assertIsSubclass(dict, typing.Collection) + self.assertNotIsInstance(42, typing.Collection) + def test_abstractset(self): self.assertIsInstance(set(), typing.AbstractSet) self.assertNotIsInstance(42, typing.AbstractSet) diff --git a/Lib/typing.py b/Lib/typing.py index 4cac66c..5573a1f 100644 --- a/Lib/typing.py +++ b/Lib/typing.py @@ -57,6 +57,7 @@ __all__ = [ 'DefaultDict', 'List', 'Set', + 'FrozenSet', 'NamedTuple', # Not really a type. 'Generator', @@ -160,12 +161,6 @@ class _ForwardRef(TypingMeta): return self def _eval_type(self, globalns, localns): - if not isinstance(localns, dict): - raise TypeError('ForwardRef localns must be a dict -- got %r' % - (localns,)) - if not isinstance(globalns, dict): - raise TypeError('ForwardRef globalns must be a dict -- got %r' % - (globalns,)) if not self.__forward_evaluated__: if globalns is None and localns is None: globalns = localns = {} @@ -388,9 +383,10 @@ class TypeVar(TypingMeta, metaclass=TypingMeta, _root=True): and issubclass(bytes, A) are true, and issubclass(int, A) is false. (TODO: Why is this needed? This may change. See #136.) - Type variables may be marked covariant or contravariant by passing - covariant=True or contravariant=True. See PEP 484 for more - details. By default type variables are invariant. + Type variables defined with covariant=True or contravariant=True + can be used do declare covariant or contravariant generic types. + See PEP 484 for more details. By default generic types are invariant + in all type variables. Type variables can be introspected. e.g.: @@ -405,7 +401,7 @@ class TypeVar(TypingMeta, metaclass=TypingMeta, _root=True): covariant=False, contravariant=False): self = super().__new__(cls, name, (Final,), {}, _root=True) if covariant and contravariant: - raise ValueError("Bivariant type variables are not supported.") + raise ValueError("Bivariant types are not supported.") self.__covariant__ = bool(covariant) self.__contravariant__ = bool(contravariant) if constraints and bound is not None: @@ -782,7 +778,7 @@ class CallableMeta(TypingMeta): return self def _get_type_vars(self, tvars): - if self.__args__: + if self.__args__ and self.__args__ is not Ellipsis: _get_type_vars(self.__args__, tvars) def _eval_type(self, globalns, localns): @@ -1044,7 +1040,7 @@ class GenericMeta(TypingMeta, abc.ABCMeta): if cls is Any: return True if isinstance(cls, GenericMeta): - # For a class C(Generic[T]) where T is co-variant, + # For a covariant class C(Generic[T]), # C[X] is a subclass of C[Y] iff X is a subclass of Y. origin = self.__origin__ if origin is not None and origin is cls.__origin__: @@ -1434,31 +1430,53 @@ class Container(Generic[T_co], extra=collections_abc.Container): __slots__ = () -# Callable was defined earlier. +if hasattr(collections_abc, 'Collection'): + class Collection(Sized, Iterable[T_co], Container[T_co], + extra=collections_abc.Collection): + __slots__ = () + __all__.append('Collection') -class AbstractSet(Sized, Iterable[T_co], Container[T_co], - extra=collections_abc.Set): - pass + +# Callable was defined earlier. + +if hasattr(collections_abc, 'Collection'): + class AbstractSet(Collection[T_co], + extra=collections_abc.Set): + pass +else: + class AbstractSet(Sized, Iterable[T_co], Container[T_co], + extra=collections_abc.Set): + pass class MutableSet(AbstractSet[T], extra=collections_abc.MutableSet): pass -# NOTE: Only the value type is covariant. -class Mapping(Sized, Iterable[KT], Container[KT], Generic[KT, VT_co], - extra=collections_abc.Mapping): - pass +# NOTE: It is only covariant in the value type. +if hasattr(collections_abc, 'Collection'): + class Mapping(Collection[KT], Generic[KT, VT_co], + extra=collections_abc.Mapping): + pass +else: + class Mapping(Sized, Iterable[KT], Container[KT], Generic[KT, VT_co], + extra=collections_abc.Mapping): + pass class MutableMapping(Mapping[KT, VT], extra=collections_abc.MutableMapping): pass if hasattr(collections_abc, 'Reversible'): - class Sequence(Sized, Reversible[T_co], Container[T_co], - extra=collections_abc.Sequence): - pass + if hasattr(collections_abc, 'Collection'): + class Sequence(Reversible[T_co], Collection[T_co], + extra=collections_abc.Sequence): + pass + else: + class Sequence(Sized, Reversible[T_co], Container[T_co], + extra=collections_abc.Sequence): + pass else: class Sequence(Sized, Iterable[T_co], Container[T_co], extra=collections_abc.Sequence): @@ -1583,11 +1601,11 @@ class Generator(Iterator[T_co], Generic[T_co, T_contra, V_co], # Internal type variable used for Type[]. -CT = TypeVar('CT', covariant=True, bound=type) +CT_co = TypeVar('CT_co', covariant=True, bound=type) # This is not a real generic class. Don't use outside annotations. -class Type(type, Generic[CT], extra=type): +class Type(type, Generic[CT_co], extra=type): """A special construct usable to annotate class objects. For example, suppose we have the following classes:: @@ -50,6 +50,12 @@ Core and Builtins Library ------- +- A new version of typing.py from https://github.com/python/typing: + - Collection (only for 3.6) (Issue #27598) + - Add FrozenSet to __all__ (upstream #261) + - fix crash in _get_type_vars() (upstream #259) + - Remove the dict constraint in ForwardRef._eval_type (upstream #252) + - Issue #27539: Fix unnormalised ``Fraction.__pow__`` result in the case of negative exponent and negative base. |