summaryrefslogtreecommitdiffstats
path: root/Lib
diff options
context:
space:
mode:
authorGuido van Rossum <guido@python.org>2016-10-09 03:27:22 (GMT)
committerGuido van Rossum <guido@python.org>2016-10-09 03:27:22 (GMT)
commite259267e52fb14571ae3845d3d93985ad96425b9 (patch)
tree86494f80bfb51d66ee97c0ec7da8fbb42e456528 /Lib
parent7b2aa2e87c524f165f7664fbe473d0be10af8c7a (diff)
downloadcpython-e259267e52fb14571ae3845d3d93985ad96425b9.zip
cpython-e259267e52fb14571ae3845d3d93985ad96425b9.tar.gz
cpython-e259267e52fb14571ae3845d3d93985ad96425b9.tar.bz2
Merge further typing.py changes from upstream.
Diffstat (limited to 'Lib')
-rw-r--r--Lib/test/test_typing.py79
-rw-r--r--Lib/typing.py5
2 files changed, 83 insertions, 1 deletions
diff --git a/Lib/test/test_typing.py b/Lib/test/test_typing.py
index cf3171f..dff737a 100644
--- a/Lib/test/test_typing.py
+++ b/Lib/test/test_typing.py
@@ -20,6 +20,7 @@ from typing import NewType
from typing import NamedTuple
from typing import IO, TextIO, BinaryIO
from typing import Pattern, Match
+import abc
import typing
try:
import collections.abc as collections_abc
@@ -1385,6 +1386,8 @@ class CollectionsAbcTests(BaseTestCase):
return 0
self.assertEqual(len(MMC()), 0)
+ assert callable(MMC.update)
+ self.assertIsInstance(MMC(), typing.Mapping)
class MMB(typing.MutableMapping[KT, VT]):
def __getitem__(self, k):
@@ -1409,6 +1412,82 @@ class CollectionsAbcTests(BaseTestCase):
self.assertIsSubclass(MMB, typing.Mapping)
self.assertIsSubclass(MMC, typing.Mapping)
+ self.assertIsInstance(MMB[KT, VT](), typing.Mapping)
+ self.assertIsInstance(MMB[KT, VT](), collections.Mapping)
+
+ self.assertIsSubclass(MMA, collections.Mapping)
+ self.assertIsSubclass(MMB, collections.Mapping)
+ self.assertIsSubclass(MMC, collections.Mapping)
+
+ self.assertIsSubclass(MMB[str, str], typing.Mapping)
+ self.assertIsSubclass(MMC, MMA)
+
+ class I(typing.Iterable): ...
+ self.assertNotIsSubclass(list, I)
+
+ class G(typing.Generator[int, int, int]): ...
+ def g(): yield 0
+ self.assertIsSubclass(G, typing.Generator)
+ self.assertIsSubclass(G, typing.Iterable)
+ if hasattr(collections, 'Generator'):
+ self.assertIsSubclass(G, collections.Generator)
+ self.assertIsSubclass(G, collections.Iterable)
+ self.assertNotIsSubclass(type(g), G)
+
+ def test_subclassing_subclasshook(self):
+
+ class Base(typing.Iterable):
+ @classmethod
+ def __subclasshook__(cls, other):
+ if other.__name__ == 'Foo':
+ return True
+ else:
+ return False
+
+ class C(Base): ...
+ class Foo: ...
+ class Bar: ...
+ self.assertIsSubclass(Foo, Base)
+ self.assertIsSubclass(Foo, C)
+ self.assertNotIsSubclass(Bar, C)
+
+ def test_subclassing_register(self):
+
+ class A(typing.Container): ...
+ class B(A): ...
+
+ class C: ...
+ A.register(C)
+ self.assertIsSubclass(C, A)
+ self.assertNotIsSubclass(C, B)
+
+ class D: ...
+ B.register(D)
+ self.assertIsSubclass(D, A)
+ self.assertIsSubclass(D, B)
+
+ class M(): ...
+ collections.MutableMapping.register(M)
+ self.assertIsSubclass(M, typing.Mapping)
+
+ def test_collections_as_base(self):
+
+ class M(collections.Mapping): ...
+ self.assertIsSubclass(M, typing.Mapping)
+ self.assertIsSubclass(M, typing.Iterable)
+
+ class S(collections.MutableSequence): ...
+ self.assertIsSubclass(S, typing.MutableSequence)
+ self.assertIsSubclass(S, typing.Iterable)
+
+ class I(collections.Iterable): ...
+ self.assertIsSubclass(I, typing.Iterable)
+
+ class A(collections.Mapping, metaclass=abc.ABCMeta): ...
+ class B: ...
+ A.register(B)
+ self.assertIsSubclass(B, typing.Mapping)
+
class OtherABCTests(BaseTestCase):
diff --git a/Lib/typing.py b/Lib/typing.py
index 05b65b7..557fa58 100644
--- a/Lib/typing.py
+++ b/Lib/typing.py
@@ -993,7 +993,10 @@ class GenericMeta(TypingMeta, abc.ABCMeta):
# This allows unparameterized generic collections to be used
# with issubclass() and isinstance() in the same way as their
# collections.abc counterparts (e.g., isinstance([], Iterable)).
- self.__subclasshook__ = _make_subclasshook(self)
+ if ('__subclasshook__' not in namespace and extra # allow overriding
+ or hasattr(self.__subclasshook__, '__name__') and
+ self.__subclasshook__.__name__ == '__extrahook__'):
+ self.__subclasshook__ = _make_subclasshook(self)
if isinstance(extra, abc.ABCMeta):
self._abc_registry = extra._abc_registry
return self