cpython: fd889884fe08 (original) (raw)
Mercurial > cpython
changeset 106206:fd889884fe08 3.6
Issue #28556: merge 5 more typing changes from upstream (#340, #344, #348, #349, #350) (3.5->3.6) [#28556]
Guido van Rossum guido@python.org | |
---|---|
date | Tue, 17 Jan 2017 20:43:30 -0800 |
parents | d47c5a8cccec(current diff)1a9e12a852b2(diff) |
children | 794dad4b849f 145da99b3df2 |
files | Lib/test/test_typing.py Lib/typing.py |
diffstat | 2 files changed, 76 insertions(+), 12 deletions(-)[+] [-] Lib/test/test_typing.py 37 Lib/typing.py 51 |
line wrap: on
line diff
--- a/Lib/test/test_typing.py +++ b/Lib/test/test_typing.py @@ -12,7 +12,7 @@ from typing import T, KT, VT # Not in _ from typing import Union, Optional from typing import Tuple, List, MutableMapping from typing import Callable -from typing import Generic, ClassVar +from typing import Generic, ClassVar, GenericMeta from typing import cast from typing import get_type_hints from typing import no_type_check, no_type_check_decorator @@ -23,6 +23,7 @@ from typing import IO, TextIO, BinaryIO from typing import Pattern, Match import abc import typing +import weakref try: import collections.abc as collections_abc except ImportError: @@ -281,6 +282,15 @@ class UnionTests(BaseTestCase): self.assertFalse(Union[str, typing.Iterable[int]] == typing.Iterable[int]) self.assertTrue(Union[str, typing.Iterable] == typing.Iterable)
- def test_union_compare_other(self):
self.assertNotEqual(Union, object)[](#l1.25)
self.assertNotEqual(Union, Any)[](#l1.26)
self.assertNotEqual(ClassVar, Union)[](#l1.27)
self.assertNotEqual(Optional, Union)[](#l1.28)
self.assertNotEqual([None], Optional)[](#l1.29)
self.assertNotEqual(Optional, typing.Mapping)[](#l1.30)
self.assertNotEqual(Optional[typing.MutableMapping], Union)[](#l1.31)
+ def test_optional(self): o = Optional[int] u = Union[int, None] @@ -718,6 +728,12 @@ class GenericTests(BaseTestCase): self.assertEqual(C.orig_bases, (List[T][U][V],)) self.assertEqual(D.orig_bases, (C, List[T][U][V]))
- def test_subscript_meta(self):
T = TypeVar('T')[](#l1.41)
self.assertEqual(Type[GenericMeta], Type[GenericMeta])[](#l1.42)
self.assertEqual(Union[T, int][GenericMeta], Union[GenericMeta, int])[](#l1.43)
self.assertEqual(Callable[..., GenericMeta].__args__, (Ellipsis, GenericMeta))[](#l1.44)
+ def test_extended_generic_rules_eq(self): T = TypeVar('T') U = TypeVar('U') @@ -896,6 +912,14 @@ class GenericTests(BaseTestCase): self.assertEqual(t, copy(t)) self.assertEqual(t, deepcopy(t))
- def test_weakref_all(self):
T = TypeVar('T')[](#l1.54)
things = [Any, Union[T, int], Callable[..., T], Tuple[Any, Any],[](#l1.55)
Optional[List[int]], typing.Mapping[int, str],[](#l1.56)
typing.re.Match[bytes], typing.Iterable['whatever']][](#l1.57)
for t in things:[](#l1.58)
self.assertEqual(weakref.ref(t)(), t)[](#l1.59)
+ def test_parameterized_slots(self): T = TypeVar('T') class C(Generic[T]): @@ -1918,7 +1942,9 @@ class NamedTupleTests(BaseTestCase): self.assertEqual(jim.id, 1) self.assertEqual(Emp.name, 'Emp') self.assertEqual(Emp._fields, ('name', 'id'))
self.assertEqual(Emp._field_types, dict(name=str, id=int))[](#l1.68)
self.assertEqual(Emp.__annotations__,[](#l1.69)
collections.OrderedDict([('name', str), ('id', int)]))[](#l1.70)
self.assertIs(Emp._field_types, Emp.__annotations__)[](#l1.71)
@skipUnless(PY36, 'Python 3.6 required') def test_annotation_usage(self): @@ -1929,7 +1955,9 @@ class NamedTupleTests(BaseTestCase): self.assertEqual(tim.cool, 9000) self.assertEqual(CoolEmployee.name, 'CoolEmployee') self.assertEqual(CoolEmployee._fields, ('name', 'cool'))
self.assertEqual(CoolEmployee._field_types, dict(name=str, cool=int))[](#l1.79)
self.assertEqual(CoolEmployee.__annotations__,[](#l1.80)
collections.OrderedDict(name=str, cool=int))[](#l1.81)
self.assertIs(CoolEmployee._field_types, CoolEmployee.__annotations__)[](#l1.82)
@skipUnless(PY36, 'Python 3.6 required') def test_namedtuple_keyword_usage(self): @@ -1939,7 +1967,8 @@ class NamedTupleTests(BaseTestCase): self.assertEqual(nick.name, 'Nick') self.assertEqual(LocalEmployee.name, 'LocalEmployee') self.assertEqual(LocalEmployee._fields, ('name', 'age'))
self.assertEqual(LocalEmployee._field_types, dict(name=str, age=int))[](#l1.90)
self.assertEqual(LocalEmployee.__annotations__, dict(name=str, age=int))[](#l1.91)
self.assertIs(LocalEmployee._field_types, LocalEmployee.__annotations__)[](#l1.92) with self.assertRaises(TypeError):[](#l1.93) NamedTuple('Name', [('x', int)], y=str)[](#l1.94) with self.assertRaises(TypeError):[](#l1.95)
--- a/Lib/typing.py +++ b/Lib/typing.py @@ -27,6 +27,8 @@ except ImportError: # ABCs (from collections.abc). 'AbstractSet', # collections.abc.Set.
- 'GenericMeta', # subclass of abc.ABCMeta and a metaclass
'ByteString', 'Container', 'Hashable', @@ -145,7 +147,7 @@ class TypingMeta(type): class _TypingBase(metaclass=TypingMeta, _root=True): """Internal indicator of special typing constructs."""# for 'Generic' and ABCs below.[](#l2.8)
def init(self, *args, **kwds): pass @@ -514,7 +516,7 @@ def _replace_arg(arg, tvars, args): if tvars is None: tvars = []
- if hasattr(arg, '_subs_tree') and isinstance(arg, (GenericMeta, _TypingBase)): return arg._subs_tree(tvars, args) if isinstance(arg, TypeVar): for i, tvar in enumerate(tvars):
@@ -523,6 +525,16 @@ def _replace_arg(arg, tvars, args): return arg +# Special typing constructs Union, Optional, Generic, Callable and Tuple +# use three special attributes for internal bookkeeping of generic types: +# * parameters is a tuple of unique free type parameters of a generic +# type, for example, Dict[T, T].parameters == (T,); +# * origin keeps a reference to a type that was subscripted, +# e.g., Union[T, int].origin == Union; +# * args is a tuple of all arguments used in subscripting, +# e.g., Dict[T, int].args == (T, int). + + def _subs_tree(cls, tvars=None, args=None): """An internal helper function: calculate substitution tree for generic cls after replacing its type parameters with @@ -757,9 +769,12 @@ class _Union(_FinalTypingBase, _root=Tru return (Union,) + tree_args def eq(self, other):
if not isinstance(other, _Union):[](#l2.51)
if isinstance(other, _Union):[](#l2.52)
return self.__tree_hash__ == other.__tree_hash__[](#l2.53)
elif self is not Union:[](#l2.54) return self._subs_tree() == other[](#l2.55)
return self.__tree_hash__ == other.__tree_hash__[](#l2.56)
else:[](#l2.57)
return self is other[](#l2.58)
def hash(self): return self.tree_hash @@ -883,10 +898,26 @@ def _no_slots_copy(dct): class GenericMeta(TypingMeta, abc.ABCMeta):
- This is a metaclass for typing.Generic and generic ABCs defined in
- typing module. User defined subclasses of GenericMeta can override
- new and invoke super().new. Note that GenericMeta.new
- has strict rules on what is allowed in its bases argument:
that appear in other bases.[](#l2.76)
- In addition, type of all generic bases is erased, e.g., C[int] is
- stripped to plain C.
- """
def new(cls, name, bases, namespace, tvars=None, args=None, origin=None, extra=None, orig_bases=None):
"""Create a new generic class. GenericMeta.__new__ accepts[](#l2.83)
keyword arguments that are used for internal bookkeeping, therefore[](#l2.84)
an override should pass unused keyword arguments to super().[](#l2.85)
"""[](#l2.86) if tvars is not None:[](#l2.87) # Called from __getitem__() below.[](#l2.88) assert origin is not None[](#l2.89)
@@ -1906,7 +1937,9 @@ def _make_nmtuple(name, types): msg = "NamedTuple('Name', [(f0, t0), (f1, t1), ...]); each t must be a type" types = [(n, _type_check(t, msg)) for n, t in types] nm_tpl = collections.namedtuple(name, [n for n, t in types])
Prior to PEP 526, only _field_types attribute was assigned.
Now, both annotations and _field_types are used to maintain compatibility.
- nm_tpl.annotations = nm_tpl._field_types = collections.OrderedDict(types) try: nm_tpl.module = sys._getframe(2).f_globals.get('name', 'main') except (AttributeError, ValueError): @@ -1941,8 +1974,10 @@ class NamedTuple(metaclass=NamedTupleMet Employee = collections.namedtuple('Employee', ['name', 'id'])
- The resulting class has one extra attribute: _field_types,
- giving a dict mapping field names to types. (The field names
- The resulting class has extra annotations and _field_types
- attributes, giving an ordered dict mapping field names to types.
- annotations should be preferred, while _field_types
- is kept to maintain pre PEP 526 compatibility. (The field names are in the _fields attribute, which is part of the namedtuple API.) Alternative equivalent keyword syntax is also accepted::