[Python-checkins] cpython (3.5): Update typing.py and test_typing.py from upstream

guido.van.rossum python-checkins at python.org
Tue Sep 27 18:23:13 EDT 2016


https://hg.python.org/cpython/rev/09cc43df4509
changeset:   104112:09cc43df4509
branch:      3.5
parent:      104109:cf93671100bf
user:        Guido van Rossum <guido at python.org>
date:        Tue Sep 27 15:20:12 2016 -0700
summary:
  Update typing.py and test_typing.py from upstream (https://github.com/python/typing)

files:
  Lib/test/test_typing.py |  337 ++++--------
  Lib/typing.py           |  699 +++++++++++++--------------
  2 files changed, 445 insertions(+), 591 deletions(-)


diff --git a/Lib/test/test_typing.py b/Lib/test/test_typing.py
--- a/Lib/test/test_typing.py
+++ b/Lib/test/test_typing.py
@@ -9,7 +9,7 @@
 from typing import TypeVar, AnyStr
 from typing import T, KT, VT  # Not in __all__.
 from typing import Union, Optional
-from typing import Tuple, List
+from typing import Tuple, List, MutableMapping
 from typing import Callable
 from typing import Generic, ClassVar
 from typing import cast
@@ -21,6 +21,10 @@
 from typing import IO, TextIO, BinaryIO
 from typing import Pattern, Match
 import typing
+try:
+    import collections.abc as collections_abc
+except ImportError:
+    import collections as collections_abc  # Fallback for PY3.2.
 
 
 class BaseTestCase(TestCase):
@@ -62,18 +66,11 @@
         with self.assertRaises(TypeError):
             isinstance(42, Any)
 
-    def test_any_subclass(self):
-        self.assertTrue(issubclass(Employee, Any))
-        self.assertTrue(issubclass(int, Any))
-        self.assertTrue(issubclass(type(None), Any))
-        self.assertTrue(issubclass(object, Any))
-
-    def test_others_any(self):
-        self.assertFalse(issubclass(Any, Employee))
-        self.assertFalse(issubclass(Any, int))
-        self.assertFalse(issubclass(Any, type(None)))
-        # However, Any is a subclass of object (this can't be helped).
-        self.assertTrue(issubclass(Any, object))
+    def test_any_subclass_type_error(self):
+        with self.assertRaises(TypeError):
+            issubclass(Employee, Any)
+        with self.assertRaises(TypeError):
+            issubclass(Any, Employee)
 
     def test_repr(self):
         self.assertEqual(repr(Any), 'typing.Any')
@@ -88,32 +85,21 @@
         with self.assertRaises(TypeError):
             class A(Any):
                 pass
+        with self.assertRaises(TypeError):
+            class A(type(Any)):
+                pass
 
     def test_cannot_instantiate(self):
         with self.assertRaises(TypeError):
             Any()
+        with self.assertRaises(TypeError):
+            type(Any)()
 
     def test_cannot_subscript(self):
         with self.assertRaises(TypeError):
             Any[int]
 
-    def test_any_is_subclass(self):
-        # Any should be considered a subclass of everything.
-        self.assertIsSubclass(Any, Any)
-        self.assertIsSubclass(Any, typing.List)
-        self.assertIsSubclass(Any, typing.List[int])
-        self.assertIsSubclass(Any, typing.List[T])
-        self.assertIsSubclass(Any, typing.Mapping)
-        self.assertIsSubclass(Any, typing.Mapping[str, int])
-        self.assertIsSubclass(Any, typing.Mapping[KT, VT])
-        self.assertIsSubclass(Any, Generic)
-        self.assertIsSubclass(Any, Generic[T])
-        self.assertIsSubclass(Any, Generic[KT, VT])
-        self.assertIsSubclass(Any, AnyStr)
-        self.assertIsSubclass(Any, Union)
-        self.assertIsSubclass(Any, Union[int, str])
-        self.assertIsSubclass(Any, typing.Match)
-        self.assertIsSubclass(Any, typing.Match[str])
+    def test_any_works_with_alias(self):
         # These expressions must simply not fail.
         typing.Match[Any]
         typing.Pattern[Any]
@@ -124,13 +110,8 @@
 
     def test_basic_plain(self):
         T = TypeVar('T')
-        # Every class is a subclass of T.
-        self.assertIsSubclass(int, T)
-        self.assertIsSubclass(str, T)
         # T equals itself.
         self.assertEqual(T, T)
-        # T is a subclass of itself.
-        self.assertIsSubclass(T, T)
         # T is an instance of TypeVar
         self.assertIsInstance(T, TypeVar)
 
@@ -139,16 +120,12 @@
         with self.assertRaises(TypeError):
             isinstance(42, T)
 
-    def test_basic_constrained(self):
-        A = TypeVar('A', str, bytes)
-        # Only str and bytes are subclasses of A.
-        self.assertIsSubclass(str, A)
-        self.assertIsSubclass(bytes, A)
-        self.assertNotIsSubclass(int, A)
-        # A equals itself.
-        self.assertEqual(A, A)
-        # A is a subclass of itself.
-        self.assertIsSubclass(A, A)
+    def test_typevar_subclass_type_error(self):
+        T = TypeVar('T')
+        with self.assertRaises(TypeError):
+            issubclass(int, T)
+        with self.assertRaises(TypeError):
+            issubclass(T, int)
 
     def test_constrained_error(self):
         with self.assertRaises(TypeError):
@@ -185,19 +162,6 @@
         self.assertNotEqual(TypeVar('T'), TypeVar('T'))
         self.assertNotEqual(TypeVar('T', int, str), TypeVar('T', int, str))
 
-    def test_subclass_as_unions(self):
-        # None of these are true -- each type var is its own world.
-        self.assertFalse(issubclass(TypeVar('T', int, str),
-                                    TypeVar('T', int, str)))
-        self.assertFalse(issubclass(TypeVar('T', int, float),
-                                    TypeVar('T', int, float, str)))
-        self.assertFalse(issubclass(TypeVar('T', int, str),
-                                    TypeVar('T', str, int)))
-        A = TypeVar('A', int, str)
-        B = TypeVar('B', int, str, float)
-        self.assertFalse(issubclass(A, B))
-        self.assertFalse(issubclass(B, A))
-
     def test_cannot_subclass_vars(self):
         with self.assertRaises(TypeError):
             class V(TypeVar('T')):
@@ -212,12 +176,6 @@
         with self.assertRaises(TypeError):
             TypeVar('A')()
 
-    def test_bound(self):
-        X = TypeVar('X', bound=Employee)
-        self.assertIsSubclass(Employee, X)
-        self.assertIsSubclass(Manager, X)
-        self.assertNotIsSubclass(int, X)
-
     def test_bound_errors(self):
         with self.assertRaises(TypeError):
             TypeVar('X', bound=42)
@@ -230,8 +188,16 @@
     def test_basics(self):
         u = Union[int, float]
         self.assertNotEqual(u, Union)
-        self.assertTrue(issubclass(int, u))
-        self.assertTrue(issubclass(float, u))
+
+    def test_subclass_error(self):
+        with self.assertRaises(TypeError):
+            issubclass(int, Union)
+        with self.assertRaises(TypeError):
+            issubclass(Union, int)
+        with self.assertRaises(TypeError):
+            issubclass(int, Union[int, str])
+        with self.assertRaises(TypeError):
+            issubclass(Union[int, str], int)
 
     def test_union_any(self):
         u = Union[Any]
@@ -260,18 +226,6 @@
         u2 = Union[float, int]
         self.assertEqual(u1, u2)
 
-    def test_subclass(self):
-        u = Union[int, Employee]
-        self.assertTrue(issubclass(Manager, u))
-
-    def test_self_subclass(self):
-        self.assertTrue(issubclass(Union[KT, VT], Union))
-        self.assertFalse(issubclass(Union, Union[KT, VT]))
-
-    def test_multiple_inheritance(self):
-        u = Union[int, Employee]
-        self.assertTrue(issubclass(ManagingFounder, u))
-
     def test_single_class_disappears(self):
         t = Union[Employee]
         self.assertIs(t, Employee)
@@ -284,13 +238,6 @@
         u = Union[Employee, Manager]
         self.assertIs(u, Employee)
 
-    def test_weird_subclasses(self):
-        u = Union[Employee, int, float]
-        v = Union[int, float]
-        self.assertTrue(issubclass(v, u))
-        w = Union[int, Manager]
-        self.assertTrue(issubclass(w, u))
-
     def test_union_union(self):
         u = Union[int, float]
         v = Union[u, Employee]
@@ -308,15 +255,27 @@
             class C(Union):
                 pass
         with self.assertRaises(TypeError):
+            class C(type(Union)):
+                pass
+        with self.assertRaises(TypeError):
             class C(Union[int, str]):
                 pass
 
     def test_cannot_instantiate(self):
         with self.assertRaises(TypeError):
             Union()
+        with self.assertRaises(TypeError):
+            type(Union)()
         u = Union[int, float]
         with self.assertRaises(TypeError):
             u()
+        with self.assertRaises(TypeError):
+            type(u)()
+
+    def test_union_generalization(self):
+        self.assertFalse(Union[str, typing.Iterable[int]] == str)
+        self.assertFalse(Union[str, typing.Iterable[int]] == typing.Iterable[int])
+        self.assertTrue(Union[str, typing.Iterable] == typing.Iterable)
 
     def test_optional(self):
         o = Optional[int]
@@ -327,10 +286,6 @@
         with self.assertRaises(TypeError):
             Union[()]
 
-    def test_issubclass_union(self):
-        self.assertIsSubclass(Union[int, str], Union)
-        self.assertNotIsSubclass(int, Union)
-
     def test_union_instance_type_error(self):
         with self.assertRaises(TypeError):
             isinstance(42, Union[int, str])
@@ -355,43 +310,19 @@
         Union[Elem, str]  # Nor should this
 
 
-class TypeVarUnionTests(BaseTestCase):
-
-    def test_simpler(self):
-        A = TypeVar('A', int, str, float)
-        B = TypeVar('B', int, str)
-        self.assertIsSubclass(A, A)
-        self.assertIsSubclass(B, B)
-        self.assertNotIsSubclass(B, A)
-        self.assertIsSubclass(A, Union[int, str, float])
-        self.assertNotIsSubclass(Union[int, str, float], A)
-        self.assertNotIsSubclass(Union[int, str], B)
-        self.assertIsSubclass(B, Union[int, str])
-        self.assertNotIsSubclass(A, B)
-        self.assertNotIsSubclass(Union[int, str, float], B)
-        self.assertNotIsSubclass(A, Union[int, str])
-
-    def test_var_union_subclass(self):
-        self.assertTrue(issubclass(T, Union[int, T]))
-        self.assertTrue(issubclass(KT, Union[KT, VT]))
-
-    def test_var_union(self):
-        TU = TypeVar('TU', Union[int, float], None)
-        self.assertIsSubclass(int, TU)
-        self.assertIsSubclass(float, TU)
-
-
 class TupleTests(BaseTestCase):
 
     def test_basics(self):
-        self.assertTrue(issubclass(Tuple[int, str], Tuple))
-        self.assertTrue(issubclass(Tuple[int, str], Tuple[int, str]))
-        self.assertFalse(issubclass(int, Tuple))
-        self.assertFalse(issubclass(Tuple[float, str], Tuple[int, str]))
-        self.assertFalse(issubclass(Tuple[int, str, int], Tuple[int, str]))
-        self.assertFalse(issubclass(Tuple[int, str], Tuple[int, str, int]))
+        with self.assertRaises(TypeError):
+            issubclass(Tuple[int, str], Tuple)
+        with self.assertRaises(TypeError):
+            issubclass(Tuple, Tuple[int, str])
+        with self.assertRaises(TypeError):
+            issubclass(tuple, Tuple[int, str])
+
+        class TP(tuple): ...
         self.assertTrue(issubclass(tuple, Tuple))
-        self.assertFalse(issubclass(Tuple, tuple))  # Can't have it both ways.
+        self.assertTrue(issubclass(TP, Tuple))
 
     def test_equality(self):
         self.assertEqual(Tuple[int], Tuple[int])
@@ -407,21 +338,7 @@
     def test_tuple_instance_type_error(self):
         with self.assertRaises(TypeError):
             isinstance((0, 0), Tuple[int, int])
-        with self.assertRaises(TypeError):
-            isinstance((0, 0), Tuple)
-
-    def test_tuple_ellipsis_subclass(self):
-
-        class B:
-            pass
-
-        class C(B):
-            pass
-
-        self.assertNotIsSubclass(Tuple[B], Tuple[B, ...])
-        self.assertIsSubclass(Tuple[C, ...], Tuple[B, ...])
-        self.assertNotIsSubclass(Tuple[C, ...], Tuple[B])
-        self.assertNotIsSubclass(Tuple[C], Tuple[B, ...])
+        self.assertIsInstance((0, 0), Tuple)
 
     def test_repr(self):
         self.assertEqual(repr(Tuple), 'typing.Tuple')
@@ -439,17 +356,9 @@
 class CallableTests(BaseTestCase):
 
     def test_self_subclass(self):
-        self.assertTrue(issubclass(Callable[[int], int], Callable))
-        self.assertFalse(issubclass(Callable, Callable[[int], int]))
-        self.assertTrue(issubclass(Callable[[int], int], Callable[[int], int]))
-        self.assertFalse(issubclass(Callable[[Employee], int],
-                                    Callable[[Manager], int]))
-        self.assertFalse(issubclass(Callable[[Manager], int],
-                                    Callable[[Employee], int]))
-        self.assertFalse(issubclass(Callable[[int], Employee],
-                                    Callable[[int], Manager]))
-        self.assertFalse(issubclass(Callable[[int], Manager],
-                                    Callable[[int], Employee]))
+        with self.assertRaises(TypeError):
+            self.assertTrue(issubclass(type(lambda x: x), Callable[[int], int]))
+        self.assertTrue(issubclass(type(lambda x: x), Callable))
 
     def test_eq_hash(self):
         self.assertEqual(Callable[[int], int], Callable[[int], int])
@@ -468,15 +377,24 @@
 
         with self.assertRaises(TypeError):
 
+            class C(type(Callable)):
+                pass
+
+        with self.assertRaises(TypeError):
+
             class C(Callable[[int], int]):
                 pass
 
     def test_cannot_instantiate(self):
         with self.assertRaises(TypeError):
             Callable()
+        with self.assertRaises(TypeError):
+            type(Callable)()
         c = Callable[[int], str]
         with self.assertRaises(TypeError):
             c()
+        with self.assertRaises(TypeError):
+            type(c)()
 
     def test_callable_instance_works(self):
         def f():
@@ -616,6 +534,12 @@
         with self.assertRaises(TypeError):
             Y[str, str]
 
+    def test_generic_errors(self):
+        with self.assertRaises(TypeError):
+            isinstance([], List[int])
+        with self.assertRaises(TypeError):
+            issubclass(list, List[int])
+
     def test_init(self):
         T = TypeVar('T')
         S = TypeVar('S')
@@ -671,6 +595,42 @@
         c.bar = 'abc'
         self.assertEqual(c.__dict__, {'bar': 'abc'})
 
+    def test_false_subclasses(self):
+        class MyMapping(MutableMapping[str, str]): pass
+        self.assertNotIsInstance({}, MyMapping)
+        self.assertNotIsSubclass(dict, MyMapping)
+
+    def test_multiple_abc_bases(self):
+        class MM1(MutableMapping[str, str], collections_abc.MutableMapping):
+            def __getitem__(self, k):
+                return None
+            def __setitem__(self, k, v):
+                pass
+            def __delitem__(self, k):
+                pass
+            def __iter__(self):
+                return iter(())
+            def __len__(self):
+                return 0
+        class MM2(collections_abc.MutableMapping, MutableMapping[str, str]):
+            def __getitem__(self, k):
+                return None
+            def __setitem__(self, k, v):
+                pass
+            def __delitem__(self, k):
+                pass
+            def __iter__(self):
+                return iter(())
+            def __len__(self):
+                return 0
+        # these two should just work
+        MM1().update()
+        MM2().update()
+        self.assertIsInstance(MM1(), collections_abc.MutableMapping)
+        self.assertIsInstance(MM1(), MutableMapping)
+        self.assertIsInstance(MM2(), collections_abc.MutableMapping)
+        self.assertIsInstance(MM2(), MutableMapping)
+
     def test_pickle(self):
         global C  # pickle wants to reference the class by name
         T = TypeVar('T')
@@ -854,6 +814,8 @@
 
     def test_cannot_init(self):
         with self.assertRaises(TypeError):
+            ClassVar()
+        with self.assertRaises(TypeError):
             type(ClassVar)()
         with self.assertRaises(TypeError):
             type(ClassVar[Optional[int]])()
@@ -865,52 +827,6 @@
             issubclass(int, ClassVar)
 
 
-class VarianceTests(BaseTestCase):
-
-    def test_invariance(self):
-        # Because of invariance, List[subclass of X] is not a subclass
-        # of List[X], and ditto for MutableSequence.
-        self.assertNotIsSubclass(typing.List[Manager], typing.List[Employee])
-        self.assertNotIsSubclass(typing.MutableSequence[Manager],
-                              typing.MutableSequence[Employee])
-        # It's still reflexive.
-        self.assertIsSubclass(typing.List[Employee], typing.List[Employee])
-        self.assertIsSubclass(typing.MutableSequence[Employee],
-                          typing.MutableSequence[Employee])
-
-    def test_covariance_tuple(self):
-        # Check covariace for Tuple (which are really special cases).
-        self.assertIsSubclass(Tuple[Manager], Tuple[Employee])
-        self.assertNotIsSubclass(Tuple[Employee], Tuple[Manager])
-        # And pairwise.
-        self.assertIsSubclass(Tuple[Manager, Manager],
-                              Tuple[Employee, Employee])
-        self.assertNotIsSubclass(Tuple[Employee, Employee],
-                              Tuple[Manager, Employee])
-        # And using ellipsis.
-        self.assertIsSubclass(Tuple[Manager, ...], Tuple[Employee, ...])
-        self.assertNotIsSubclass(Tuple[Employee, ...], Tuple[Manager, ...])
-
-    def test_covariance_sequence(self):
-        # Check covariance for Sequence (which is just a generic class
-        # for this purpose, but using a type variable with covariant=True).
-        self.assertIsSubclass(typing.Sequence[Manager],
-                              typing.Sequence[Employee])
-        self.assertNotIsSubclass(typing.Sequence[Employee],
-                              typing.Sequence[Manager])
-
-    def test_covariance_mapping(self):
-        # Ditto for Mapping (covariant in the value, invariant in the key).
-        self.assertIsSubclass(typing.Mapping[Employee, Manager],
-                          typing.Mapping[Employee, Employee])
-        self.assertNotIsSubclass(typing.Mapping[Manager, Employee],
-                              typing.Mapping[Employee, Employee])
-        self.assertNotIsSubclass(typing.Mapping[Employee, Manager],
-                              typing.Mapping[Manager, Manager])
-        self.assertNotIsSubclass(typing.Mapping[Manager, Employee],
-                              typing.Mapping[Manager, Manager])
-
-
 class CastTests(BaseTestCase):
 
     def test_basics(self):
@@ -1247,7 +1163,6 @@
         # path and could fail.  So call this a few times.
         self.assertIsInstance([], typing.Iterable)
         self.assertIsInstance([], typing.Iterable)
-        self.assertIsInstance([], typing.Iterable[int])
         self.assertNotIsInstance(42, typing.Iterable)
         # Just in case, also test issubclass() a few times.
         self.assertIsSubclass(list, typing.Iterable)
@@ -1256,7 +1171,6 @@
     def test_iterator(self):
         it = iter([])
         self.assertIsInstance(it, typing.Iterator)
-        self.assertIsInstance(it, typing.Iterator[int])
         self.assertNotIsInstance(42, typing.Iterator)
 
     @skipUnless(PY35, 'Python 3.5 required')
@@ -1268,13 +1182,8 @@
             globals(), ns)
         foo = ns['foo']
         g = foo()
-        self.assertIsSubclass(type(g), typing.Awaitable[int])
         self.assertIsInstance(g, typing.Awaitable)
         self.assertNotIsInstance(foo, typing.Awaitable)
-        self.assertIsSubclass(typing.Awaitable[Manager],
-                          typing.Awaitable[Employee])
-        self.assertNotIsSubclass(typing.Awaitable[Employee],
-                              typing.Awaitable[Manager])
         g.send(None)  # Run foo() till completion, to avoid warning.
 
     @skipUnless(PY35, 'Python 3.5 required')
@@ -1283,8 +1192,6 @@
         it = AsyncIteratorWrapper(base_it)
         self.assertIsInstance(it, typing.AsyncIterable)
         self.assertIsInstance(it, typing.AsyncIterable)
-        self.assertIsSubclass(typing.AsyncIterable[Manager],
-                          typing.AsyncIterable[Employee])
         self.assertNotIsInstance(42, typing.AsyncIterable)
 
     @skipUnless(PY35, 'Python 3.5 required')
@@ -1292,8 +1199,6 @@
         base_it = range(10)  # type: Iterator[int]
         it = AsyncIteratorWrapper(base_it)
         self.assertIsInstance(it, typing.AsyncIterator)
-        self.assertIsSubclass(typing.AsyncIterator[Manager],
-                          typing.AsyncIterator[Employee])
         self.assertNotIsInstance(42, typing.AsyncIterator)
 
     def test_sized(self):
@@ -1457,10 +1362,6 @@
             yield 42
         g = foo()
         self.assertIsSubclass(type(g), typing.Generator)
-        self.assertIsSubclass(typing.Generator[Manager, Employee, Manager],
-                          typing.Generator[Employee, Manager, Employee])
-        self.assertNotIsSubclass(typing.Generator[Manager, Manager, Manager],
-                              typing.Generator[Employee, Employee, Employee])
 
     def test_no_generator_instantiation(self):
         with self.assertRaises(TypeError):
@@ -1511,7 +1412,6 @@
 
         cm = manager()
         self.assertIsInstance(cm, typing.ContextManager)
-        self.assertIsInstance(cm, typing.ContextManager[int])
         self.assertNotIsInstance(42, typing.ContextManager)
 
 
@@ -1653,22 +1553,16 @@
         pat = re.compile('[a-z]+', re.I)
         self.assertIsSubclass(pat.__class__, Pattern)
         self.assertIsSubclass(type(pat), Pattern)
-        self.assertIsSubclass(type(pat), Pattern[str])
+        self.assertIsInstance(pat, Pattern)
 
         mat = pat.search('12345abcde.....')
         self.assertIsSubclass(mat.__class__, Match)
-        self.assertIsSubclass(mat.__class__, Match[str])
-        self.assertIsSubclass(mat.__class__, Match[bytes])  # Sad but true.
         self.assertIsSubclass(type(mat), Match)
-        self.assertIsSubclass(type(mat), Match[str])
+        self.assertIsInstance(mat, Match)
 
+        # these should just work
         p = Pattern[Union[str, bytes]]
-        self.assertIsSubclass(Pattern[str], Pattern)
-        self.assertIsSubclass(Pattern[str], p)
-
         m = Match[Union[bytes, str]]
-        self.assertIsSubclass(Match[bytes], Match)
-        self.assertIsSubclass(Match[bytes], m)
 
     def test_errors(self):
         with self.assertRaises(TypeError):
@@ -1683,9 +1577,6 @@
             m[str]
         with self.assertRaises(TypeError):
             # We don't support isinstance().
-            isinstance(42, Pattern)
-        with self.assertRaises(TypeError):
-            # We don't support isinstance().
             isinstance(42, Pattern[str])
 
     def test_repr(self):
@@ -1710,7 +1601,7 @@
                 pass
 
         self.assertEqual(str(ex.exception),
-                         "A type alias cannot be subclassed")
+                         "Cannot subclass typing._TypeAlias")
 
 
 class AllTests(BaseTestCase):
diff --git a/Lib/typing.py b/Lib/typing.py
--- a/Lib/typing.py
+++ b/Lib/typing.py
@@ -89,6 +89,13 @@
         return x.__name__
 
 
+def _trim_name(nm):
+    if nm.startswith('_') and nm not in ('_TypeAlias',
+                    '_ForwardRef', '_TypingBase', '_FinalTypingBase'):
+        nm = nm[1:]
+    return nm
+
+
 class TypingMeta(type):
     """Metaclass for every type defined below.
 
@@ -127,22 +134,69 @@
         pass
 
     def __repr__(self):
-        return '%s.%s' % (self.__module__, _qualname(self))
+        qname = _trim_name(_qualname(self))
+        return '%s.%s' % (self.__module__, qname)
 
 
-class Final:
+class _TypingBase(metaclass=TypingMeta, _root=True):
+    """Indicator of special typing constructs."""
+
+    __slots__ = ()
+
+
+    def __init__(self, *args, **kwds):
+        pass
+
+    def __new__(cls, *args, **kwds):
+        """Constructor.
+
+        This only exists to give a better error message in case
+        someone tries to subclass a special typing object (not a good idea).
+        """
+        if (len(args) == 3 and
+                isinstance(args[0], str) and
+                isinstance(args[1], tuple)):
+            # Close enough.
+            raise TypeError("Cannot subclass %r" % cls)
+        return object.__new__(cls)
+
+    # Things that are not classes also need these.
+    def _eval_type(self, globalns, localns):
+        return self
+
+    def _get_type_vars(self, tvars):
+        pass
+
+    def __repr__(self):
+        cls = type(self)
+        qname = _trim_name(_qualname(cls))
+        return '%s.%s' % (cls.__module__, qname)
+
+    def __call__(self, *args, **kwds):
+        raise TypeError("Cannot instantiate %r" % type(self))
+
+
+class _FinalTypingBase(_TypingBase, _root=True):
     """Mix-in class to prevent instantiation."""
 
     __slots__ = ()
 
-    def __new__(self, *args, **kwds):
-        raise TypeError("Cannot instantiate %r" % self.__class__)
+    def __new__(cls, *args, _root=False, **kwds):
+        self = super().__new__(cls, *args, **kwds)
+        if _root is True:
+            return self
+        raise TypeError("Cannot instantiate %r" % cls)
 
 
-class _ForwardRef(TypingMeta):
+class _ForwardRef(_TypingBase, _root=True):
     """Wrapper to hold a forward reference."""
 
-    def __new__(cls, arg):
+    __slots__ = ('__forward_arg__', '__forward_code__',
+                 '__forward_evaluated__', '__forward_value__',
+                 '__forward_frame__')
+
+    def __init__(self, arg):
+        super().__init__(arg)
         if not isinstance(arg, str):
             raise TypeError('ForwardRef must be a string -- got %r' % (arg,))
         try:
@@ -150,7 +204,6 @@
         except SyntaxError:
             raise SyntaxError('ForwardRef must be an expression -- got %r' %
                               (arg,))
-        self = super().__new__(cls, arg, (), {}, _root=True)
         self.__forward_arg__ = arg
         self.__forward_code__ = code
         self.__forward_evaluated__ = False
@@ -161,7 +214,6 @@
             frame = frame.f_back
         assert frame is not None
         self.__forward_frame__ = frame
-        return self
 
     def _eval_type(self, globalns, localns):
         if not self.__forward_evaluated__:
@@ -177,49 +229,36 @@
             self.__forward_evaluated__ = True
         return self.__forward_value__
 
+    def __eq__(self, other):
+        if not isinstance(other, _ForwardRef):
+            return NotImplemented
+        return (self.__forward_arg__ == other.__forward_arg__ and
+                self.__forward_frame__ == other.__forward_frame__)
+
+    def __hash__(self):
+        return hash((self.__forward_arg__, self.__forward_frame__))
+
     def __instancecheck__(self, obj):
         raise TypeError("Forward references cannot be used with isinstance().")
 
     def __subclasscheck__(self, cls):
-        if not self.__forward_evaluated__:
-            globalns = self.__forward_frame__.f_globals
-            localns = self.__forward_frame__.f_locals
-            try:
-                self._eval_type(globalns, localns)
-            except NameError:
-                return False  # Too early.
-        return issubclass(cls, self.__forward_value__)
+        raise TypeError("Forward references cannot be used with issubclass().")
 
     def __repr__(self):
         return '_ForwardRef(%r)' % (self.__forward_arg__,)
 
 
-class _TypeAlias:
+class _TypeAlias(_TypingBase, _root=True):
     """Internal helper class for defining generic variants of concrete types.
 
-    Note that this is not a type; let's call it a pseudo-type.  It can
-    be used in instance and subclass checks, e.g. isinstance(m, Match)
-    or issubclass(type(m), Match).  However, it cannot be itself the
-    target of an issubclass() call; e.g. issubclass(Match, C) (for
-    some arbitrary class C) raises TypeError rather than returning
-    False.
+    Note that this is not a type; let's call it a pseudo-type.  It cannot
+    be used in instance and subclass checks in parameterized form, i.e.
+    ``isinstance(42, Match[str])`` raises ``TypeError`` instead of returning
+    ``False``.
     """
 
     __slots__ = ('name', 'type_var', 'impl_type', 'type_checker')
 
-    def __new__(cls, *args, **kwds):
-        """Constructor.
-
-        This only exists to give a better error message in case
-        someone tries to subclass a type alias (not a good idea).
-        """
-        if (len(args) == 3 and
-                isinstance(args[0], str) and
-                isinstance(args[1], tuple)):
-            # Close enough.
-            raise TypeError("A type alias cannot be subclassed")
-        return object.__new__(cls)
-
     def __init__(self, name, type_var, impl_type, type_checker):
         """Initializer.
 
@@ -232,9 +271,9 @@
                 and returns a value that should be a type_var instance.
         """
         assert isinstance(name, str), repr(name)
-        assert isinstance(type_var, type), repr(type_var)
         assert isinstance(impl_type, type), repr(impl_type)
         assert not isinstance(impl_type, TypingMeta), repr(impl_type)
+        assert isinstance(type_var, (type, _TypingBase))
         self.name = name
         self.type_var = type_var
         self.impl_type = impl_type
@@ -244,36 +283,41 @@
         return "%s[%s]" % (self.name, _type_repr(self.type_var))
 
     def __getitem__(self, parameter):
-        assert isinstance(parameter, type), repr(parameter)
         if not isinstance(self.type_var, TypeVar):
             raise TypeError("%s cannot be further parameterized." % self)
-        if self.type_var.__constraints__:
-            if not issubclass(parameter, Union[self.type_var.__constraints__]):
+        if self.type_var.__constraints__ and isinstance(parameter, type):
+            if not issubclass(parameter, self.type_var.__constraints__):
                 raise TypeError("%s is not a valid substitution for %s." %
                                 (parameter, self.type_var))
+        if isinstance(parameter, TypeVar):
+            raise TypeError("%s cannot be re-parameterized." % self.type_var)
         return self.__class__(self.name, parameter,
                               self.impl_type, self.type_checker)
 
+    def __eq__(self, other):
+        if not isinstance(other, _TypeAlias):
+            return NotImplemented
+        return self.name == other.name and self.type_var == other.type_var
+
+    def __hash__(self):
+        return hash((self.name, self.type_var))
+
     def __instancecheck__(self, obj):
-        raise TypeError("Type aliases cannot be used with isinstance().")
+        if not isinstance(self.type_var, TypeVar):
+            raise TypeError("Parameterized type aliases cannot be used "
+                            "with isinstance().")
+        return isinstance(obj, self.impl_type)
 
     def __subclasscheck__(self, cls):
-        if cls is Any:
-            return True
-        if isinstance(cls, _TypeAlias):
-            # Covariance.  For now, we compare by name.
-            return (cls.name == self.name and
-                    issubclass(cls.type_var, self.type_var))
-        else:
-            # Note that this is too lenient, because the
-            # implementation type doesn't carry information about
-            # whether it is about bytes or str (for example).
-            return issubclass(cls, self.impl_type)
+        if not isinstance(self.type_var, TypeVar):
+            raise TypeError("Parameterized type aliases cannot be used "
+                            "with issubclass().")
+        return issubclass(cls, self.impl_type)
 
 
 def _get_type_vars(types, tvars):
     for t in types:
-        if isinstance(t, TypingMeta) or isinstance(t, _ClassVar):
+        if isinstance(t, TypingMeta) or isinstance(t, _TypingBase):
             t._get_type_vars(tvars)
 
 
@@ -284,7 +328,7 @@
 
 
 def _eval_type(t, globalns, localns):
-    if isinstance(t, TypingMeta) or isinstance(t, _ClassVar):
+    if isinstance(t, TypingMeta) or isinstance(t, _TypingBase):
         return t._eval_type(globalns, localns)
     else:
         return t
@@ -306,7 +350,7 @@
         return type(None)
     if isinstance(arg, str):
         arg = _ForwardRef(arg)
-    if not isinstance(arg, (type, _TypeAlias)) and not callable(arg):
+    if not isinstance(arg, (type, _TypingBase)) and not callable(arg):
         raise TypeError(msg + " Got %.100r." % (arg,))
     return arg
 
@@ -328,23 +372,7 @@
         return repr(obj)
 
 
-class AnyMeta(TypingMeta):
-    """Metaclass for Any."""
-
-    def __new__(cls, name, bases, namespace, _root=False):
-        self = super().__new__(cls, name, bases, namespace, _root=_root)
-        return self
-
-    def __instancecheck__(self, obj):
-        raise TypeError("Any cannot be used with isinstance().")
-
-    def __subclasscheck__(self, cls):
-        if not isinstance(cls, type):
-            return super().__subclasscheck__(cls)  # To TypeError.
-        return True
-
-
-class Any(Final, metaclass=AnyMeta, _root=True):
+class _Any(_FinalTypingBase, _root=True):
     """Special type indicating an unconstrained type.
 
     - Any object is an instance of Any.
@@ -354,8 +382,17 @@
 
     __slots__ = ()
 
+    def __instancecheck__(self, obj):
+        raise TypeError("Any cannot be used with isinstance().")
 
-class TypeVar(TypingMeta, metaclass=TypingMeta, _root=True):
+    def __subclasscheck__(self, cls):
+        raise TypeError("Any cannot be used with issubclass().")
+
+
+Any = _Any(_root=True)
+
+
+class TypeVar(_TypingBase, _root=True):
     """Type variable.
 
     Usage::
@@ -400,9 +437,14 @@
       A.__constraints__ == (str, bytes)
     """
 
-    def __new__(cls, name, *constraints, bound=None,
+    __slots__ = ('__name__', '__bound__', '__constraints__',
+                 '__covariant__', '__contravariant__')
+
+    def __init__(self, name, *constraints, bound=None,
                 covariant=False, contravariant=False):
-        self = super().__new__(cls, name, (Final,), {}, _root=True)
+        super().__init__(name, *constraints, bound=bound,
+                         covariant=covariant, contravariant=contravariant)
+        self.__name__ = name
         if covariant and contravariant:
             raise ValueError("Bivariant types are not supported.")
         self.__covariant__ = bool(covariant)
@@ -417,7 +459,6 @@
             self.__bound__ = _type_check(bound, "Bound must be a type.")
         else:
             self.__bound__ = None
-        return self
 
     def _get_type_vars(self, tvars):
         if self not in tvars:
@@ -436,16 +477,7 @@
         raise TypeError("Type variables cannot be used with isinstance().")
 
     def __subclasscheck__(self, cls):
-        # TODO: Make this raise TypeError too?
-        if cls is self:
-            return True
-        if cls is Any:
-            return True
-        if self.__bound__ is not None:
-            return issubclass(cls, self.__bound__)
-        if self.__constraints__:
-            return any(issubclass(cls, c) for c in self.__constraints__)
-        return True
+        raise TypeError("Type variables cannot be used with issubclass().")
 
 
 # Some unconstrained type variables.  These are used by the container types.
@@ -463,124 +495,19 @@
 AnyStr = TypeVar('AnyStr', bytes, str)
 
 
-class UnionMeta(TypingMeta):
-    """Metaclass for Union."""
+def _tp_cache(func):
+    cached = functools.lru_cache()(func)
+    @functools.wraps(func)
+    def inner(*args, **kwds):
+        try:
+            return cached(*args, **kwds)
+        except TypeError:
+            pass  # Do not duplicate real errors.
+        return func(*args, **kwds)
+    return inner
 
-    def __new__(cls, name, bases, namespace, parameters=None, _root=False):
-        if parameters is None:
-            return super().__new__(cls, name, bases, namespace, _root=_root)
-        if not isinstance(parameters, tuple):
-            raise TypeError("Expected parameters=<tuple>")
-        # Flatten out Union[Union[...], ...] and type-check non-Union args.
-        params = []
-        msg = "Union[arg, ...]: each arg must be a type."
-        for p in parameters:
-            if isinstance(p, UnionMeta):
-                params.extend(p.__union_params__)
-            else:
-                params.append(_type_check(p, msg))
-        # Weed out strict duplicates, preserving the first of each occurrence.
-        all_params = set(params)
-        if len(all_params) < len(params):
-            new_params = []
-            for t in params:
-                if t in all_params:
-                    new_params.append(t)
-                    all_params.remove(t)
-            params = new_params
-            assert not all_params, all_params
-        # Weed out subclasses.
-        # E.g. Union[int, Employee, Manager] == Union[int, Employee].
-        # If Any or object is present it will be the sole survivor.
-        # If both Any and object are present, Any wins.
-        # Never discard type variables, except against Any.
-        # (In particular, Union[str, AnyStr] != AnyStr.)
-        all_params = set(params)
-        for t1 in params:
-            if t1 is Any:
-                return Any
-            if isinstance(t1, TypeVar):
-                continue
-            if isinstance(t1, _TypeAlias):
-                # _TypeAlias is not a real class.
-                continue
-            if not isinstance(t1, type):
-                assert callable(t1)  # A callable might sneak through.
-                continue
-            if any(isinstance(t2, type) and issubclass(t1, t2)
-                   for t2 in all_params - {t1} if not isinstance(t2, TypeVar)):
-                all_params.remove(t1)
-        # It's not a union if there's only one type left.
-        if len(all_params) == 1:
-            return all_params.pop()
-        # Create a new class with these params.
-        self = super().__new__(cls, name, bases, {}, _root=True)
-        self.__union_params__ = tuple(t for t in params if t in all_params)
-        self.__union_set_params__ = frozenset(self.__union_params__)
-        return self
 
-    def _eval_type(self, globalns, localns):
-        p = tuple(_eval_type(t, globalns, localns)
-                  for t in self.__union_params__)
-        if p == self.__union_params__:
-            return self
-        else:
-            return self.__class__(self.__name__, self.__bases__, {},
-                                  p, _root=True)
-
-    def _get_type_vars(self, tvars):
-        if self.__union_params__:
-            _get_type_vars(self.__union_params__, tvars)
-
-    def __repr__(self):
-        r = super().__repr__()
-        if self.__union_params__:
-            r += '[%s]' % (', '.join(_type_repr(t)
-                                     for t in self.__union_params__))
-        return r
-
-    def __getitem__(self, parameters):
-        if self.__union_params__ is not None:
-            raise TypeError(
-                "Cannot subscript an existing Union. Use Union[u, t] instead.")
-        if parameters == ():
-            raise TypeError("Cannot take a Union of no types.")
-        if not isinstance(parameters, tuple):
-            parameters = (parameters,)
-        return self.__class__(self.__name__, self.__bases__,
-                              dict(self.__dict__), parameters, _root=True)
-
-    def __eq__(self, other):
-        if not isinstance(other, UnionMeta):
-            return NotImplemented
-        return self.__union_set_params__ == other.__union_set_params__
-
-    def __hash__(self):
-        return hash(self.__union_set_params__)
-
-    def __instancecheck__(self, obj):
-        raise TypeError("Unions cannot be used with isinstance().")
-
-    def __subclasscheck__(self, cls):
-        if cls is Any:
-            return True
-        if self.__union_params__ is None:
-            return isinstance(cls, UnionMeta)
-        elif isinstance(cls, UnionMeta):
-            if cls.__union_params__ is None:
-                return False
-            return all(issubclass(c, self) for c in (cls.__union_params__))
-        elif isinstance(cls, TypeVar):
-            if cls in self.__union_params__:
-                return True
-            if cls.__constraints__:
-                return issubclass(Union[cls.__constraints__], self)
-            return False
-        else:
-            return any(issubclass(cls, t) for t in self.__union_params__)
-
-
-class Union(Final, metaclass=UnionMeta, _root=True):
+class _Union(_FinalTypingBase, _root=True):
     """Union type; Union[X, Y] means either X or Y.
 
     To define a union, use e.g. Union[int, str].  Details:
@@ -632,23 +559,107 @@
     - You can use Optional[X] as a shorthand for Union[X, None].
     """
 
-    # Unsubscripted Union type has params set to None.
-    __union_params__ = None
-    __union_set_params__ = None
+    __slots__ = ('__union_params__', '__union_set_params__')
 
+    def __new__(cls, parameters=None, *args, _root=False):
+        self = super().__new__(cls, parameters, *args, _root=_root)
+        if parameters is None:
+            self.__union_params__ = None
+            self.__union_set_params__ = None
+            return self
+        if not isinstance(parameters, tuple):
+            raise TypeError("Expected parameters=<tuple>")
+        # Flatten out Union[Union[...], ...] and type-check non-Union args.
+        params = []
+        msg = "Union[arg, ...]: each arg must be a type."
+        for p in parameters:
+            if isinstance(p, _Union):
+                params.extend(p.__union_params__)
+            else:
+                params.append(_type_check(p, msg))
+        # Weed out strict duplicates, preserving the first of each occurrence.
+        all_params = set(params)
+        if len(all_params) < len(params):
+            new_params = []
+            for t in params:
+                if t in all_params:
+                    new_params.append(t)
+                    all_params.remove(t)
+            params = new_params
+            assert not all_params, all_params
+        # Weed out subclasses.
+        # E.g. Union[int, Employee, Manager] == Union[int, Employee].
+        # If Any or object is present it will be the sole survivor.
+        # If both Any and object are present, Any wins.
+        # Never discard type variables, except against Any.
+        # (In particular, Union[str, AnyStr] != AnyStr.)
+        all_params = set(params)
+        for t1 in params:
+            if t1 is Any:
+                return Any
+            if not isinstance(t1, type):
+                continue
+            if any(isinstance(t2, type) and issubclass(t1, t2)
+                   for t2 in all_params - {t1}
+                   if not (isinstance(t2, GenericMeta) and
+                           t2.__origin__ is not None)):
+                all_params.remove(t1)
+        # It's not a union if there's only one type left.
+        if len(all_params) == 1:
+            return all_params.pop()
+        self.__union_params__ = tuple(t for t in params if t in all_params)
+        self.__union_set_params__ = frozenset(self.__union_params__)
+        return self
 
-class OptionalMeta(TypingMeta):
-    """Metaclass for Optional."""
+    def _eval_type(self, globalns, localns):
+        p = tuple(_eval_type(t, globalns, localns)
+                  for t in self.__union_params__)
+        if p == self.__union_params__:
+            return self
+        else:
+            return self.__class__(p, _root=True)
 
-    def __new__(cls, name, bases, namespace, _root=False):
-        return super().__new__(cls, name, bases, namespace, _root=_root)
+    def _get_type_vars(self, tvars):
+        if self.__union_params__:
+            _get_type_vars(self.__union_params__, tvars)
 
-    def __getitem__(self, arg):
-        arg = _type_check(arg, "Optional[t] requires a single type.")
-        return Union[arg, type(None)]
+    def __repr__(self):
+        r = super().__repr__()
+        if self.__union_params__:
+            r += '[%s]' % (', '.join(_type_repr(t)
+                                     for t in self.__union_params__))
+        return r
 
+    @_tp_cache
+    def __getitem__(self, parameters):
+        if self.__union_params__ is not None:
+            raise TypeError(
+                "Cannot subscript an existing Union. Use Union[u, t] instead.")
+        if parameters == ():
+            raise TypeError("Cannot take a Union of no types.")
+        if not isinstance(parameters, tuple):
+            parameters = (parameters,)
+        return self.__class__(parameters, _root=True)
 
-class Optional(Final, metaclass=OptionalMeta, _root=True):
+    def __eq__(self, other):
+        if not isinstance(other, _Union):
+            return NotImplemented
+        return self.__union_set_params__ == other.__union_set_params__
+
+    def __hash__(self):
+        return hash(self.__union_set_params__)
+
+    def __instancecheck__(self, obj):
+        raise TypeError("Unions cannot be used with isinstance().")
+
+    def __subclasscheck__(self, cls):
+        raise TypeError("Unions cannot be used with issubclass().")
+
+
+Union = _Union(_root=True)
+
+
+class _Optional(_FinalTypingBase, _root=True):
     """Optional type.
 
     Optional[X] is equivalent to Union[X, type(None)].
@@ -656,16 +667,31 @@
 
     __slots__ = ()
 
+    @_tp_cache
+    def __getitem__(self, arg):
+        arg = _type_check(arg, "Optional[t] requires a single type.")
+        return Union[arg, type(None)]
 
-class TupleMeta(TypingMeta):
-    """Metaclass for Tuple."""
 
-    def __new__(cls, name, bases, namespace, parameters=None,
+Optional = _Optional(_root=True)
+
+
+class _Tuple(_FinalTypingBase, _root=True):
+    """Tuple type; Tuple[X, Y] is the cross-product type of X and Y.
+
+    Example: Tuple[T1, T2] is a tuple of two elements corresponding
+    to type variables T1 and T2.  Tuple[int, float, str] is a tuple
+    of an int, a float and a string.
+
+    To specify a variable-length tuple of homogeneous type, use Tuple[T, ...].
+    """
+
+    __slots__ = ('__tuple_params__', '__tuple_use_ellipsis__')
+
+    def __init__(self, parameters=None,
                 use_ellipsis=False, _root=False):
-        self = super().__new__(cls, name, bases, namespace, _root=_root)
         self.__tuple_params__ = parameters
         self.__tuple_use_ellipsis__ = use_ellipsis
-        return self
 
     def _get_type_vars(self, tvars):
         if self.__tuple_params__:
@@ -679,8 +705,7 @@
         if p == self.__tuple_params__:
             return self
         else:
-            return self.__class__(self.__name__, self.__bases__, {},
-                                  p, _root=True)
+            return self.__class__(p, _root=True)
 
     def __repr__(self):
         r = super().__repr__()
@@ -694,6 +719,7 @@
                 ', '.join(params))
         return r
 
+    @_tp_cache
     def __getitem__(self, parameters):
         if self.__tuple_params__ is not None:
             raise TypeError("Cannot re-parameterize %r" % (self,))
@@ -707,64 +733,50 @@
             use_ellipsis = False
             msg = "Tuple[t0, t1, ...]: each t must be a type."
         parameters = tuple(_type_check(p, msg) for p in parameters)
-        return self.__class__(self.__name__, self.__bases__,
-                              dict(self.__dict__), parameters,
+        return self.__class__(parameters,
                               use_ellipsis=use_ellipsis, _root=True)
 
     def __eq__(self, other):
-        if not isinstance(other, TupleMeta):
+        if not isinstance(other, _Tuple):
             return NotImplemented
         return (self.__tuple_params__ == other.__tuple_params__ and
                 self.__tuple_use_ellipsis__ == other.__tuple_use_ellipsis__)
 
     def __hash__(self):
-        return hash(self.__tuple_params__)
+        return hash((self.__tuple_params__, self.__tuple_use_ellipsis__))
 
     def __instancecheck__(self, obj):
-        raise TypeError("Tuples cannot be used with isinstance().")
+        if self.__tuple_params__ == None:
+            return isinstance(obj, tuple)
+        raise TypeError("Parameterized Tuple cannot be used "
+                        "with isinstance().")
 
     def __subclasscheck__(self, cls):
-        if cls is Any:
-            return True
-        if not isinstance(cls, type):
-            return super().__subclasscheck__(cls)  # To TypeError.
-        if issubclass(cls, tuple):
-            return True  # Special case.
-        if not isinstance(cls, TupleMeta):
-            return super().__subclasscheck__(cls)  # False.
-        if self.__tuple_params__ is None:
-            return True
-        if cls.__tuple_params__ is None:
-            return False  # ???
-        if cls.__tuple_use_ellipsis__ != self.__tuple_use_ellipsis__:
-            return False
-        # Covariance.
-        return (len(self.__tuple_params__) == len(cls.__tuple_params__) and
-                all(issubclass(x, p)
-                    for x, p in zip(cls.__tuple_params__,
-                                    self.__tuple_params__)))
+        if self.__tuple_params__ == None:
+            return issubclass(cls, tuple)
+        raise TypeError("Parameterized Tuple cannot be used "
+                        "with issubclass().")
 
 
-class Tuple(Final, metaclass=TupleMeta, _root=True):
-    """Tuple type; Tuple[X, Y] is the cross-product type of X and Y.
+Tuple = _Tuple(_root=True)
 
-    Example: Tuple[T1, T2] is a tuple of two elements corresponding
-    to type variables T1 and T2.  Tuple[int, float, str] is a tuple
-    of an int, a float and a string.
 
-    To specify a variable-length tuple of homogeneous type, use Sequence[T].
+class _Callable(_FinalTypingBase, _root=True):
+    """Callable type; Callable[[int], str] is a function of (int) -> str.
+
+    The subscription syntax must always be used with exactly two
+    values: the argument list and the return type.  The argument list
+    must be a list of types; the return type must be a single type.
+
+    There is no syntax to indicate optional or keyword arguments,
+    such function types are rarely used as callback types.
     """
 
-    __slots__ = ()
+    __slots__ = ('__args__', '__result__')
 
-
-class CallableMeta(TypingMeta):
-    """Metaclass for Callable."""
-
-    def __new__(cls, name, bases, namespace, _root=False,
-                args=None, result=None):
+    def __init__(self, args=None, result=None, _root=False):
         if args is None and result is None:
-            pass  # Must be 'class Callable'.
+            pass
         else:
             if args is not Ellipsis:
                 if not isinstance(args, list):
@@ -775,10 +787,8 @@
                 args = tuple(_type_check(arg, msg) for arg in args)
             msg = "Callable[args, result]: result must be a type."
             result = _type_check(result, msg)
-        self = super().__new__(cls, name, bases, namespace, _root=_root)
         self.__args__ = args
         self.__result__ = result
-        return self
 
     def _get_type_vars(self, tvars):
         if self.__args__ and self.__args__ is not Ellipsis:
@@ -795,8 +805,7 @@
         if args == self.__args__ and result == self.__result__:
             return self
         else:
-            return self.__class__(self.__name__, self.__bases__, {},
-                                  args=args, result=result, _root=True)
+            return self.__class__(args, result, _root=True)
 
     def __repr__(self):
         r = super().__repr__()
@@ -816,12 +825,10 @@
             raise TypeError(
                 "Callable must be used as Callable[[arg, ...], result].")
         args, result = parameters
-        return self.__class__(self.__name__, self.__bases__,
-                              dict(self.__dict__), _root=True,
-                              args=args, result=result)
+        return self.__class__(args, result, _root=True)
 
     def __eq__(self, other):
-        if not isinstance(other, CallableMeta):
+        if not isinstance(other, _Callable):
             return NotImplemented
         return (self.__args__ == other.__args__ and
                 self.__result__ == other.__result__)
@@ -836,31 +843,18 @@
         if self.__args__ is None and self.__result__ is None:
             return isinstance(obj, collections_abc.Callable)
         else:
-            raise TypeError("Callable[] cannot be used with isinstance().")
+            raise TypeError("Parameterized Callable cannot be used "
+                            "with isinstance().")
 
     def __subclasscheck__(self, cls):
-        if cls is Any:
-            return True
-        if not isinstance(cls, CallableMeta):
-            return super().__subclasscheck__(cls)
         if self.__args__ is None and self.__result__ is None:
-            return True
-        # We're not doing covariance or contravariance -- this is *invariance*.
-        return self == cls
+            return issubclass(cls, collections_abc.Callable)
+        else:
+            raise TypeError("Parameterized Callable cannot be used "
+                            "with issubclass().")
 
 
-class Callable(Final, metaclass=CallableMeta, _root=True):
-    """Callable type; Callable[[int], str] is a function of (int) -> str.
-
-    The subscription syntax must always be used with exactly two
-    values: the argument list and the return type.  The argument list
-    must be a list of types; the return type must be a single type.
-
-    There is no syntax to indicate optional or keyword arguments,
-    such function types are rarely used as callback types.
-    """
-
-    __slots__ = ()
+Callable = _Callable(_root=True)
 
 
 def _gorg(a):
@@ -985,6 +979,7 @@
     def __hash__(self):
         return hash((self.__name__, self.__parameters__))
 
+    @_tp_cache
     def __getitem__(self, params):
         if not isinstance(params, tuple):
             params = (params,)
@@ -1040,44 +1035,18 @@
         return self.__subclasscheck__(instance.__class__)
 
     def __subclasscheck__(self, cls):
-        if cls is Any:
-            return True
-        if isinstance(cls, GenericMeta):
-            # 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__:
-                assert len(self.__args__) == len(origin.__parameters__)
-                assert len(cls.__args__) == len(origin.__parameters__)
-                for p_self, p_cls, p_origin in zip(self.__args__,
-                                                   cls.__args__,
-                                                   origin.__parameters__):
-                    if isinstance(p_origin, TypeVar):
-                        if p_origin.__covariant__:
-                            # Covariant -- p_cls must be a subclass of p_self.
-                            if not issubclass(p_cls, p_self):
-                                break
-                        elif p_origin.__contravariant__:
-                            # Contravariant.  I think it's the opposite. :-)
-                            if not issubclass(p_self, p_cls):
-                                break
-                        else:
-                            # Invariant -- p_cls and p_self must equal.
-                            if p_self != p_cls:
-                                break
-                    else:
-                        # If the origin's parameter is not a typevar,
-                        # insist on invariance.
-                        if p_self != p_cls:
-                            break
-                else:
-                    return True
-                # If we break out of the loop, the superclass gets a chance.
+        if self is Generic:
+            raise TypeError("Class %r cannot be used with class "
+                            "or instance checks" % self)
+        if (self.__origin__ is not None and
+            sys._getframe(1).f_globals['__name__'] != 'abc'):
+            raise TypeError("Parameterized generics cannot be used with class "
+                            "or instance checks")
         if super().__subclasscheck__(cls):
             return True
-        if self.__extra__ is None or isinstance(cls, GenericMeta):
-            return False
-        return issubclass(cls, self.__extra__)
+        if self.__extra__ is not None:
+            return issubclass(cls, self.__extra__)
+        return False
 
 
 # Prevent checks for Generic to crash when defining Generic.
@@ -1117,7 +1086,7 @@
             return obj
 
 
-class _ClassVar(metaclass=TypingMeta, _root=True):
+class _ClassVar(_FinalTypingBase, _root=True):
     """Special type construct to mark class variables.
 
     An annotation wrapped in ClassVar indicates that a given
@@ -1134,36 +1103,35 @@
     be used with isinstance() or issubclass().
     """
 
-    def __init__(self, tp=None, _root=False):
-        cls = type(self)
-        if _root:
-            self.__type__ = tp
-        else:
-            raise TypeError('Cannot initialize {}'.format(cls.__name__[1:]))
+    __slots__ = ('__type__',)
+
+    def __init__(self, tp=None, **kwds):
+        self.__type__ = tp
 
     def __getitem__(self, item):
         cls = type(self)
         if self.__type__ is None:
             return cls(_type_check(item,
-                       '{} accepts only types.'.format(cls.__name__[1:])),
+                       '{} accepts only single type.'.format(cls.__name__[1:])),
                        _root=True)
         raise TypeError('{} cannot be further subscripted'
                         .format(cls.__name__[1:]))
 
     def _eval_type(self, globalns, localns):
-        return type(self)(_eval_type(self.__type__, globalns, localns),
-                          _root=True)
+        new_tp = _eval_type(self.__type__, globalns, localns)
+        if new_tp == self.__type__:
+            return self
+        return type(self)(new_tp, _root=True)
 
     def _get_type_vars(self, tvars):
         if self.__type__:
             _get_type_vars(self.__type__, tvars)
 
     def __repr__(self):
-        cls = type(self)
-        if not self.__type__:
-            return '{}.{}'.format(cls.__module__, cls.__name__[1:])
-        return '{}.{}[{}]'.format(cls.__module__, cls.__name__[1:],
-                                  _type_repr(self.__type__))
+        r = super().__repr__()
+        if self.__type__ is not None:
+            r += '[{}]'.format(_type_repr(self.__type__))
+        return r
 
     def __hash__(self):
         return hash((type(self).__name__, self.__type__))
@@ -1614,52 +1582,52 @@
 if hasattr(collections_abc, 'Collection'):
     class AbstractSet(Collection[T_co],
                       extra=collections_abc.Set):
-        pass
+        __slots__ = ()
 else:
     class AbstractSet(Sized, Iterable[T_co], Container[T_co],
                       extra=collections_abc.Set):
-        pass
+        __slots__ = ()
 
 
 class MutableSet(AbstractSet[T], extra=collections_abc.MutableSet):
-    pass
+    __slots__ = ()
 
 
 # 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
+        __slots__ = ()
 else:
     class Mapping(Sized, Iterable[KT], Container[KT], Generic[KT, VT_co],
                   extra=collections_abc.Mapping):
-        pass
+        __slots__ = ()
 
 
 class MutableMapping(Mapping[KT, VT], extra=collections_abc.MutableMapping):
-    pass
+    __slots__ = ()
 
 if hasattr(collections_abc, 'Reversible'):
     if hasattr(collections_abc, 'Collection'):
         class Sequence(Reversible[T_co], Collection[T_co],
                    extra=collections_abc.Sequence):
-            pass
+            __slots__ = ()
     else:
         class Sequence(Sized, Reversible[T_co], Container[T_co],
                    extra=collections_abc.Sequence):
-            pass
+            __slots__ = ()
 else:
     class Sequence(Sized, Iterable[T_co], Container[T_co],
                    extra=collections_abc.Sequence):
-        pass
+        __slots__ = ()
 
 
 class MutableSequence(Sequence[T], extra=collections_abc.MutableSequence):
-    pass
+    __slots__ = ()
 
 
 class ByteString(Sequence[int], extra=collections_abc.ByteString):
-    pass
+    __slots__ = ()
 
 
 ByteString.register(type(memoryview(b'')))
@@ -1667,6 +1635,8 @@
 
 class List(list, MutableSequence[T], extra=list):
 
+    __slots__ = ()
+
     def __new__(cls, *args, **kwds):
         if _geqv(cls, List):
             raise TypeError("Type List cannot be instantiated; "
@@ -1676,6 +1646,8 @@
 
 class Set(set, MutableSet[T], extra=set):
 
+    __slots__ = ()
+
     def __new__(cls, *args, **kwds):
         if _geqv(cls, Set):
             raise TypeError("Type Set cannot be instantiated; "
@@ -1683,22 +1655,7 @@
         return set.__new__(cls, *args, **kwds)
 
 
-class _FrozenSetMeta(GenericMeta):
-    """This metaclass ensures set is not a subclass of FrozenSet.
-
-    Without this metaclass, set would be considered a subclass of
-    FrozenSet, because FrozenSet.__extra__ is collections.abc.Set, and
-    set is a subclass of that.
-    """
-
-    def __subclasscheck__(self, cls):
-        if issubclass(cls, Set):
-            return False
-        return super().__subclasscheck__(cls)
-
-
-class FrozenSet(frozenset, AbstractSet[T_co], metaclass=_FrozenSetMeta,
-                extra=frozenset):
+class FrozenSet(frozenset, AbstractSet[T_co], extra=frozenset):
     __slots__ = ()
 
     def __new__(cls, *args, **kwds):
@@ -1709,23 +1666,23 @@
 
 
 class MappingView(Sized, Iterable[T_co], extra=collections_abc.MappingView):
-    pass
+    __slots__ = ()
 
 
 class KeysView(MappingView[KT], AbstractSet[KT],
                extra=collections_abc.KeysView):
-    pass
+    __slots__ = ()
 
 
 class ItemsView(MappingView[Tuple[KT, VT_co]],
                 AbstractSet[Tuple[KT, VT_co]],
                 Generic[KT, VT_co],
                 extra=collections_abc.ItemsView):
-    pass
+    __slots__ = ()
 
 
 class ValuesView(MappingView[VT_co], extra=collections_abc.ValuesView):
-    pass
+    __slots__ = ()
 
 
 if hasattr(contextlib, 'AbstractContextManager'):
@@ -1736,6 +1693,8 @@
 
 class Dict(dict, MutableMapping[KT, VT], extra=dict):
 
+    __slots__ = ()
+
     def __new__(cls, *args, **kwds):
         if _geqv(cls, Dict):
             raise TypeError("Type Dict cannot be instantiated; "
@@ -1745,6 +1704,8 @@
 class DefaultDict(collections.defaultdict, MutableMapping[KT, VT],
                   extra=collections.defaultdict):
 
+    __slots__ = ()
+
     def __new__(cls, *args, **kwds):
         if _geqv(cls, DefaultDict):
             raise TypeError("Type DefaultDict cannot be instantiated; "
@@ -1800,6 +1761,8 @@
     At this point the type checker knows that joe has type BasicUser.
     """
 
+    __slots__ = ()
+
 
 def _make_nmtuple(name, types):
     nm_tpl = collections.namedtuple(name, [n for n, t in types])

-- 
Repository URL: https://hg.python.org/cpython


More information about the Python-checkins mailing list