summaryrefslogtreecommitdiffstats
path: root/Lib/test
diff options
context:
space:
mode:
authorSam Gross <colesbury@gmail.com>2024-06-18 13:57:23 (GMT)
committerGitHub <noreply@github.com>2024-06-18 13:57:23 (GMT)
commite8752d7b80775ec2a348cd4bf38cbe26a4a07615 (patch)
treeaf381ff07ef5c47aa18731fb03d5eb88452a3189 /Lib/test
parent360f14a493d8461d42dc646be40b4b6fb20db57a (diff)
downloadcpython-e8752d7b80775ec2a348cd4bf38cbe26a4a07615.zip
cpython-e8752d7b80775ec2a348cd4bf38cbe26a4a07615.tar.gz
cpython-e8752d7b80775ec2a348cd4bf38cbe26a4a07615.tar.bz2
gh-118789: Add `PyUnstable_Object_ClearWeakRefsNoCallbacks` (#118807)
This exposes `PyUnstable_Object_ClearWeakRefsNoCallbacks` as an unstable C-API function to provide a thread-safe mechanism for clearing weakrefs without executing callbacks. Some C-API extensions need to clear weakrefs without calling callbacks, such as after running finalizers like we do in subtype_dealloc. Previously they could use `_PyWeakref_ClearRef` on each weakref, but that's not thread-safe in the free-threaded build. Co-authored-by: Petr Viktorin <encukou@gmail.com>
Diffstat (limited to 'Lib/test')
-rw-r--r--Lib/test/test_capi/test_object.py28
1 files changed, 28 insertions, 0 deletions
diff --git a/Lib/test/test_capi/test_object.py b/Lib/test/test_capi/test_object.py
index fa23bff..cc9c9b6 100644
--- a/Lib/test/test_capi/test_object.py
+++ b/Lib/test/test_capi/test_object.py
@@ -103,5 +103,33 @@ class PrintTest(unittest.TestCase):
with self.assertRaises(OSError):
_testcapi.pyobject_print_os_error(output_filename)
+
+class ClearWeakRefsNoCallbacksTest(unittest.TestCase):
+ """Test PyUnstable_Object_ClearWeakRefsNoCallbacks"""
+ def test_ClearWeakRefsNoCallbacks(self):
+ """Ensure PyUnstable_Object_ClearWeakRefsNoCallbacks works"""
+ import weakref
+ import gc
+ class C:
+ pass
+ obj = C()
+ messages = []
+ ref = weakref.ref(obj, lambda: messages.append("don't add this"))
+ self.assertIs(ref(), obj)
+ self.assertFalse(messages)
+ _testcapi.pyobject_clear_weakrefs_no_callbacks(obj)
+ self.assertIsNone(ref())
+ gc.collect()
+ self.assertFalse(messages)
+
+ def test_ClearWeakRefsNoCallbacks_no_weakref_support(self):
+ """Don't fail on objects that don't support weakrefs"""
+ import weakref
+ obj = object()
+ with self.assertRaises(TypeError):
+ ref = weakref.ref(obj)
+ _testcapi.pyobject_clear_weakrefs_no_callbacks(obj)
+
+
if __name__ == "__main__":
unittest.main()