From 05d080706f584d711bec7076a01c614add3c5beb Mon Sep 17 00:00:00 2001 From: George Ogden Date: Mon, 16 Feb 2026 10:13:55 +0000 Subject: [PATCH 1/3] Add failing test for custom isinstance check --- Lib/test/test_types.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/Lib/test/test_types.py b/Lib/test/test_types.py index 39d57c5f5b61c9..e4b2fee3a4a2d0 100644 --- a/Lib/test/test_types.py +++ b/Lib/test/test_types.py @@ -909,6 +909,21 @@ def __subclasscheck__(cls, sub): self.assertIsSubclass(int, x) self.assertRaises(ZeroDivisionError, issubclass, list, x) + def test_custom_instancecheck(self): + class CustomIsInstanceMeta(type): + def __instancecheck__(cls, instance): + return type(instance) is int + + class CustomIsInstance(metaclass=CustomIsInstanceMeta): + ... + + class CustomIsInstanceSubclass(CustomIsInstance): + ... + + self.assertTrue(isinstance(5, CustomIsInstance)) + self.assertFalse(isinstance(CustomIsInstance(), CustomIsInstance)) + self.assertFalse(isinstance(CustomIsInstanceSubclass(), CustomIsInstance)) + def test_or_type_operator_with_TypeVar(self): TV = typing.TypeVar('T') self.assertEqual(TV | str, typing.Union[TV, str]) From dde0b836118882aec06c25c67dfb0f6d92f2a5f3 Mon Sep 17 00:00:00 2001 From: George Ogden Date: Mon, 16 Feb 2026 11:55:34 +0000 Subject: [PATCH 2/3] Remove overzealous isinstance optimization --- Objects/abstract.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/Objects/abstract.c b/Objects/abstract.c index f2c7de3d1ef1ad..a6cc046375c7ec 100644 --- a/Objects/abstract.c +++ b/Objects/abstract.c @@ -2638,11 +2638,6 @@ object_isinstance(PyObject *inst, PyObject *cls) static int object_recursive_isinstance(PyThreadState *tstate, PyObject *inst, PyObject *cls) { - /* Quick test for an exact match */ - if (Py_IS_TYPE(inst, (PyTypeObject *)cls)) { - return 1; - } - /* We know what type's __instancecheck__ does. */ if (PyType_CheckExact(cls)) { return object_isinstance(inst, cls); From 43be5a11a07cc971f52aacf095b96601a47ec656 Mon Sep 17 00:00:00 2001 From: George Ogden Date: Mon, 16 Feb 2026 12:14:03 +0000 Subject: [PATCH 3/3] Add subclasscheck tests --- Lib/test/test_types.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/Lib/test/test_types.py b/Lib/test/test_types.py index e4b2fee3a4a2d0..24d57965b3f814 100644 --- a/Lib/test/test_types.py +++ b/Lib/test/test_types.py @@ -924,6 +924,25 @@ class CustomIsInstanceSubclass(CustomIsInstance): self.assertFalse(isinstance(CustomIsInstance(), CustomIsInstance)) self.assertFalse(isinstance(CustomIsInstanceSubclass(), CustomIsInstance)) + def test_custom_subclasscheck(self): + class CustomIsSubclassMeta(type): + def __subclasscheck__(cls, subcls): + return subcls is int + + class CustomIsSubclass(metaclass=CustomIsSubclassMeta): + ... + + class CustomIsSubclassSubclass(CustomIsSubclass): + ... + + self.assertTrue(issubclass(int, CustomIsSubclass)) + self.assertFalse(isinstance(4, CustomIsSubclass)) + self.assertFalse(issubclass(CustomIsSubclass, CustomIsSubclass)) + self.assertTrue(isinstance(CustomIsSubclass(), CustomIsSubclass)) + self.assertFalse(issubclass(CustomIsSubclassSubclass, CustomIsSubclass)) + self.assertTrue(isinstance(CustomIsSubclassSubclass(), CustomIsSubclass)) + + def test_or_type_operator_with_TypeVar(self): TV = typing.TypeVar('T') self.assertEqual(TV | str, typing.Union[TV, str])