[Python-checkins] [3.12] gh-105280: Ensure `isinstance([], collections.abc.Mapping)` always evaluates to `False` (GH-105281) (#105318)

AlexWaygood webhook-mailer at python.org
Mon Jun 5 10:51:34 EDT 2023


https://github.com/python/cpython/commit/2031238eb64150053117e214ca40dc774b95b933
commit: 2031238eb64150053117e214ca40dc774b95b933
branch: 3.12
author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com>
committer: AlexWaygood <Alex.Waygood at Gmail.com>
date: 2023年06月05日T14:51:26Z
summary:
[3.12] gh-105280: Ensure `isinstance([], collections.abc.Mapping)` always evaluates to `False` (GH-105281) (#105318)
gh-105280: Ensure `isinstance([], collections.abc.Mapping)` always evaluates to `False` (GH-105281)
(cherry picked from commit 08756dbba647440803d2ba4545ba0ab2f0cdfe1c)
Co-authored-by: Alex Waygood <Alex.Waygood at Gmail.com>
files:
A Misc/NEWS.d/next/Library/2023-06-04-12-16-47.gh-issue-105280.srRbCe.rst
M Lib/test/test_typing.py
M Lib/typing.py
diff --git a/Lib/test/test_typing.py b/Lib/test/test_typing.py
index 3a2f7393eb46..ef1db06109ec 100644
--- a/Lib/test/test_typing.py
+++ b/Lib/test/test_typing.py
@@ -3,6 +3,7 @@
 import collections.abc
 from collections import defaultdict
 from functools import lru_cache, wraps
+import gc
 import inspect
 import itertools
 import pickle
@@ -2758,6 +2759,19 @@ def x(self): ...
 with self.assertRaisesRegex(TypeError, only_classes_allowed):
 issubclass(1, BadPG)
 
+ def test_isinstance_checks_not_at_whim_of_gc(self):
+ self.addCleanup(gc.enable)
+ gc.disable()
+
+ with self.assertRaisesRegex(
+ TypeError,
+ "Protocols can only inherit from other protocols"
+ ):
+ class Foo(collections.abc.Mapping, Protocol):
+ pass
+
+ self.assertNotIsInstance([], collections.abc.Mapping)
+
 def test_issubclass_and_isinstance_on_Protocol_itself(self):
 class C:
 def x(self): pass
diff --git a/Lib/typing.py b/Lib/typing.py
index 06d50306c475..2acb9f052f2a 100644
--- a/Lib/typing.py
+++ b/Lib/typing.py
@@ -1777,6 +1777,25 @@ def _pickle_pskwargs(pskwargs):
 class _ProtocolMeta(ABCMeta):
 # This metaclass is somewhat unfortunate,
 # but is necessary for several reasons...
+ def __new__(mcls, name, bases, namespace, /, **kwargs):
+ if name == "Protocol" and bases == (Generic,):
+ pass
+ elif Protocol in bases:
+ for base in bases:
+ if not (
+ base in {object, Generic}
+ or base.__name__ in _PROTO_ALLOWLIST.get(base.__module__, [])
+ or (
+ issubclass(base, Generic)
+ and getattr(base, "_is_protocol", False)
+ )
+ ):
+ raise TypeError(
+ f"Protocols can only inherit from other protocols, "
+ f"got {base!r}"
+ )
+ return super().__new__(mcls, name, bases, namespace, **kwargs)
+
 def __init__(cls, *args, **kwargs):
 super().__init__(*args, **kwargs)
 if getattr(cls, "_is_protocol", False):
@@ -1912,14 +1931,7 @@ def _proto_hook(other):
 if not cls._is_protocol:
 return
 
- # ... otherwise check consistency of bases, and prohibit instantiation.
- for base in cls.__bases__:
- if not (base in (object, Generic) or
- base.__module__ in _PROTO_ALLOWLIST and
- base.__name__ in _PROTO_ALLOWLIST[base.__module__] or
- issubclass(base, Generic) and getattr(base, '_is_protocol', False)):
- raise TypeError('Protocols can only inherit from other'
- ' protocols, got %r' % base)
+ # ... otherwise prohibit instantiation.
 if cls.__init__ is Protocol.__init__:
 cls.__init__ = _no_init_or_replace_init
 
diff --git a/Misc/NEWS.d/next/Library/2023-06-04-12-16-47.gh-issue-105280.srRbCe.rst b/Misc/NEWS.d/next/Library/2023-06-04-12-16-47.gh-issue-105280.srRbCe.rst
new file mode 100644
index 000000000000..8e4696466043
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2023-06-04-12-16-47.gh-issue-105280.srRbCe.rst
@@ -0,0 +1,4 @@
+Fix bug where ``isinstance([], collections.abc.Mapping)`` could evaluate to
+``True`` if garbage collection happened at the wrong time. The bug was
+caused by changes to the implementation of :class:`typing.Protocol` in
+Python 3.12.


More information about the Python-checkins mailing list

AltStyle によって変換されたページ (->オリジナル) /