]> granicus.if.org Git - python/commitdiff
bpo-38008: Move builtin protocol whitelist to mapping instead of list (GH-15647)
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>
Thu, 12 Sep 2019 10:32:36 +0000 (03:32 -0700)
committerGitHub <noreply@github.com>
Thu, 12 Sep 2019 10:32:36 +0000 (03:32 -0700)
Fixes https://bugs.python.org/issue38008
(cherry picked from commit 692a0dc91597b7fb350383b633dc4d044cbd360e)

Co-authored-by: Divij Rajkumar <drajkuma1@gmail.com>
Lib/test/test_typing.py
Lib/typing.py
Misc/NEWS.d/next/Library/2019-09-12-10-47-34.bpo-38008.sH74Iy.rst [new file with mode: 0644]

index ba0800fae90e301f9a123b0da9e73cc1f1ec2da1..3402996b2d2e0a076736bd7316f57d9f3ea655cc 100644 (file)
@@ -1381,6 +1381,14 @@ class ProtocolTests(BaseTestCase):
         self.assertIsSubclass(B, Custom)
         self.assertNotIsSubclass(A, Custom)
 
+    def test_builtin_protocol_whitelist(self):
+        with self.assertRaises(TypeError):
+            class CustomProtocol(TestCase, Protocol):
+                pass
+
+        class CustomContextManager(typing.ContextManager, Protocol):
+            pass
+
 class GenericTests(BaseTestCase):
 
     def test_basics(self):
index 5f1a0ad3d637430e7a7bd639130b7e589ca2e48b..7b07112c3abf84024bac970e77228ca215479c07 100644 (file)
@@ -989,10 +989,13 @@ def _allow_reckless_class_cheks():
         return True
 
 
-_PROTO_WHITELIST = ['Callable', 'Awaitable',
-                    'Iterable', 'Iterator', 'AsyncIterable', 'AsyncIterator',
-                    'Hashable', 'Sized', 'Container', 'Collection', 'Reversible',
-                    'ContextManager', 'AsyncContextManager']
+_PROTO_WHITELIST = {
+    'collections.abc': [
+        'Callable', 'Awaitable', 'Iterable', 'Iterator', 'AsyncIterable',
+        'Hashable', 'Sized', 'Container', 'Collection', 'Reversible',
+    ],
+    'contextlib': ['AbstractContextManager', 'AbstractAsyncContextManager'],
+}
 
 
 class _ProtocolMeta(ABCMeta):
@@ -1105,7 +1108,8 @@ class Protocol(Generic, metaclass=_ProtocolMeta):
         # ... otherwise check consistency of bases, and prohibit instantiation.
         for base in cls.__bases__:
             if not (base in (object, Generic) or
-                    base.__module__ == 'collections.abc' and base.__name__ in _PROTO_WHITELIST or
+                    base.__module__ in _PROTO_WHITELIST and
+                    base.__name__ in _PROTO_WHITELIST[base.__module__] or
                     issubclass(base, Generic) and base._is_protocol):
                 raise TypeError('Protocols can only inherit from other'
                                 ' protocols, got %r' % base)
diff --git a/Misc/NEWS.d/next/Library/2019-09-12-10-47-34.bpo-38008.sH74Iy.rst b/Misc/NEWS.d/next/Library/2019-09-12-10-47-34.bpo-38008.sH74Iy.rst
new file mode 100644 (file)
index 0000000..f696707
--- /dev/null
@@ -0,0 +1,3 @@
+Fix parent class check in protocols to correctly identify the module that
+provides a builtin protocol, instead of assuming they all come from the
+:mod:`collections.abc` module