diff options
author | Eric Snow <ericsnowcurrently@gmail.com> | 2023-06-01 22:28:31 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-06-01 22:28:31 (GMT) |
commit | 146939306adcff706ebddb047f7470d148125cdf (patch) | |
tree | 7ba1a0832da33fff49813d51dee801e54efd9fce /Lib | |
parent | 3698fda06eefb3c01e78c4c07f46fcdd0559e0f6 (diff) | |
download | cpython-146939306adcff706ebddb047f7470d148125cdf.zip cpython-146939306adcff706ebddb047f7470d148125cdf.tar.gz cpython-146939306adcff706ebddb047f7470d148125cdf.tar.bz2 |
gh-104614: Make Sure ob_type is Always Set Correctly by PyType_Ready() (gh-105122)
When I added the relevant condition to type_ready_set_bases() in gh-103912, I had missed that the function also sets tp_base and ob_type (if necessary). That led to problems for third-party static types.
We fix that here, by making those extra operations distinct and by adjusting the condition to be more specific.
Diffstat (limited to 'Lib')
-rw-r--r-- | Lib/test/test_capi/test_misc.py | 38 |
1 files changed, 37 insertions, 1 deletions
diff --git a/Lib/test/test_capi/test_misc.py b/Lib/test/test_capi/test_misc.py index 037c811..e1b55cf 100644 --- a/Lib/test/test_capi/test_misc.py +++ b/Lib/test/test_capi/test_misc.py @@ -1,8 +1,9 @@ # Run the _testcapi module tests (tests for the Python/C API): by defn, # these are all functions _testcapi exports whose name begins with 'test_'. -from collections import OrderedDict import _thread +from collections import OrderedDict +import contextlib import importlib.machinery import importlib.util import os @@ -1626,6 +1627,41 @@ class BuiltinStaticTypesTests(unittest.TestCase): self.assertIsNot(mro, None) +class TestStaticTypes(unittest.TestCase): + + _has_run = False + + @classmethod + def setUpClass(cls): + # The tests here don't play nice with our approach to refleak + # detection, so we bail out in that case. + if cls._has_run: + raise unittest.SkipTest('these tests do not support re-running') + cls._has_run = True + + @contextlib.contextmanager + def basic_static_type(self, *args): + cls = _testcapi.get_basic_static_type(*args) + yield cls + + def test_pytype_ready_always_sets_tp_type(self): + # The point of this test is to prevent something like + # https://github.com/python/cpython/issues/104614 + # from happening again. + + # First check when tp_base/tp_bases is *not* set before PyType_Ready(). + with self.basic_static_type() as cls: + self.assertIs(cls.__base__, object); + self.assertEqual(cls.__bases__, (object,)); + self.assertIs(type(cls), type(object)); + + # Then check when we *do* set tp_base/tp_bases first. + with self.basic_static_type(object) as cls: + self.assertIs(cls.__base__, object); + self.assertEqual(cls.__bases__, (object,)); + self.assertIs(type(cls), type(object)); + + class TestThreadState(unittest.TestCase): @threading_helper.reap_threads |