From e24771bf3449a12c1c0c71d9fa55b63be059bf30 Mon Sep 17 00:00:00 2001 From: Brandt Bucher Date: Tue, 2 May 2023 18:27:52 -0700 Subject: [PATCH 1/3] Add failing regression tests --- Lib/test/test_builtin.py | 43 +++++++++++++++++++++++----------------- 1 file changed, 25 insertions(+), 18 deletions(-) diff --git a/Lib/test/test_builtin.py b/Lib/test/test_builtin.py index 04dd8ff3070c99..821710a7fa3286 100644 --- a/Lib/test/test_builtin.py +++ b/Lib/test/test_builtin.py @@ -2372,24 +2372,31 @@ def __del__(self): @cpython_only class ImmortalTests(unittest.TestCase): - def test_immortal(self): - none_refcount = sys.getrefcount(None) - true_refcount = sys.getrefcount(True) - false_refcount = sys.getrefcount(False) - smallint_refcount = sys.getrefcount(100) - - # Assert that all of these immortal instances have large ref counts. - self.assertGreater(none_refcount, 2 ** 15) - self.assertGreater(true_refcount, 2 ** 15) - self.assertGreater(false_refcount, 2 ** 15) - self.assertGreater(smallint_refcount, 2 ** 15) - - # Confirm that the refcount doesn't change even with a new ref to them. - l = [None, True, False, 100] - self.assertEqual(sys.getrefcount(None), none_refcount) - self.assertEqual(sys.getrefcount(True), true_refcount) - self.assertEqual(sys.getrefcount(False), false_refcount) - self.assertEqual(sys.getrefcount(100), smallint_refcount) + + if sys.maxsize < (1 << 32): + IMMORTAL_REFCOUNT = (1 << 30) - 1 + else: + IMMORTAL_REFCOUNT = (1 << 32) - 1 + + IMMORTALS = (None, True, False, Ellipsis, NotImplemented, *range(-5, 257)) + + def assert_immortal(self, immortal): + with self.subTest(immortal): + self.assertEqual(sys.getrefcount(immortal), self.IMMORTAL_REFCOUNT) + + def test_immortals(self): + for immortal in self.IMMORTALS: + self.assert_immortal(immortal) + + def test_list_repeat_respect_immortality(self): + refs = list(self.IMMORTALS) * 42 + for immortal in self.IMMORTALS: + self.assert_immortal(immortal) + + def test_tuple_repeat_respect_immortality(self): + refs = tuple(self.IMMORTALS) * 42 + for immortal in self.IMMORTALS: + self.assert_immortal(immortal) class TestType(unittest.TestCase): From 9338eea377684d03f588ae98bb9a93cc2125003b Mon Sep 17 00:00:00 2001 From: Brandt Bucher Date: Tue, 2 May 2023 18:28:06 -0700 Subject: [PATCH 2/3] Fix _Py_RefcntAdd --- Include/internal/pycore_object.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Include/internal/pycore_object.h b/Include/internal/pycore_object.h index 91853ad0525b55..3ad990f2bdc8f4 100644 --- a/Include/internal/pycore_object.h +++ b/Include/internal/pycore_object.h @@ -58,6 +58,9 @@ extern void _Py_DecRefTotal(PyInterpreterState *); // Increment reference count by n static inline void _Py_RefcntAdd(PyObject* op, Py_ssize_t n) { + if (_Py_IsImmortal(op)) { + return; + } #ifdef Py_REF_DEBUG _Py_AddRefTotal(_PyInterpreterState_GET(), n); #endif From be3b1031344dcc83328ca0757843de3fb997499b Mon Sep 17 00:00:00 2001 From: Brandt Bucher Date: Tue, 2 May 2023 18:30:23 -0700 Subject: [PATCH 3/3] blurb add --- .../2023-05-02-18-29-49.gh-issue-104142._5Et6I.rst | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2023-05-02-18-29-49.gh-issue-104142._5Et6I.rst diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-05-02-18-29-49.gh-issue-104142._5Et6I.rst b/Misc/NEWS.d/next/Core and Builtins/2023-05-02-18-29-49.gh-issue-104142._5Et6I.rst new file mode 100644 index 00000000000000..6a19ae84057f4c --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2023-05-02-18-29-49.gh-issue-104142._5Et6I.rst @@ -0,0 +1,2 @@ +Fix an issue where :class:`list` or :class:`tuple` repetition could fail to +respect :pep:`683`.