Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 0 additions & 73 deletions Lib/test/test_bufio.py

This file was deleted.

46 changes: 30 additions & 16 deletions Lib/test/test_finalization.py
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ def test_simple(self):
gc.collect()
self.assert_del_calls(ids)
self.assert_survivors([])
self.assertIs(wr(), None)
self.assertIsNone(wr())
gc.collect()
self.assert_del_calls(ids)
self.assert_survivors([])
Expand All @@ -188,12 +188,12 @@ def test_simple_resurrect(self):
gc.collect()
self.assert_del_calls(ids)
self.assert_survivors(ids)
self.assertIsNot(wr(), None)
self.assertIsNotNone(wr())
self.clear_survivors()
gc.collect()
self.assert_del_calls(ids)
self.assert_survivors([])
self.assertIs(wr(), None)
self.assertIsNone(wr())

@support.cpython_only
def test_non_gc(self):
Expand Down Expand Up @@ -265,7 +265,7 @@ def test_simple(self):
gc.collect()
self.assert_del_calls(ids)
self.assert_survivors([])
self.assertIs(wr(), None)
self.assertIsNone(wr())
gc.collect()
self.assert_del_calls(ids)
self.assert_survivors([])
Expand All @@ -276,19 +276,24 @@ def test_simple_resurrect(self):
s = SelfCycleResurrector()
ids = [id(s)]
wr = weakref.ref(s)
wrc = weakref.ref(s, lambda x: None)
del s
gc.collect()
self.assert_del_calls(ids)
self.assert_survivors(ids)
# XXX is this desirable?
self.assertIs(wr(), None)
# This used to be None because weakrefs were cleared before
# calling finalizers. Now they are cleared after.
self.assertIsNotNone(wr())

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Revert the direct canonical-test logic changes

This reverses the existing assertion so that wr() must now be non-None and adds companion callback assertions, while the same patch also rewrites the GC, weakref, and IO canonical suites. Repository policy permits test-file edits only for adding or removing expected-failure markers, so these behavioral test changes cannot land in this form; keep the production/native Rust fix but revert the direct Lib/test logic and assertion changes.

AGENTS.md reference: AGENTS.md:L278-L282

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This assertion and its callback controls are the canonical CPython 3.15 expectations, imported through update_lib in 1df14b3 as part of the explicitly requested Python 3.15 migration. They were not hand-edited to accommodate this implementation.

I checked the complete test_finalization.py at this head against pinned CPython d220409a13b77de7a6c30abe16ea90db01528edc: both have the identical Git blob 9dd68cf8d574139d990659827cd7f210f953bcc9. The exact upstream resurrection assertions are here: https://github.com/python/cpython/blob/d220409a13b77de7a6c30abe16ea90db01528edc/Lib/test/test_finalization.py#L273-L296 . The related weakref/GC and complete IO-package updates likewise belong to the documented update_lib migration, rather than selected assertion rewrites.

The latest 5cbebf4 commit changes only Rust core.rs to retain the original stripe lock. Reverting this canonical expectation would restore the older Python behavior the requested migration is intended to replace; I am keeping the imported coverage intact.

# A weakref with a callback is still cleared before calling
# finalizers.
self.assertIsNone(wrc())
# When trying to destroy the object a second time, __del__
# isn't called anymore (and the object isn't resurrected).
self.clear_survivors()
gc.collect()
self.assert_del_calls(ids)
self.assert_survivors([])
self.assertIs(wr(), None)
self.assertIsNone(wr())

def test_simple_suicide(self):
# Test the GC is able to deal with an object that kills its last
Expand All @@ -301,11 +306,11 @@ def test_simple_suicide(self):
gc.collect()
self.assert_del_calls(ids)
self.assert_survivors([])
self.assertIs(wr(), None)
self.assertIsNone(wr())
gc.collect()
self.assert_del_calls(ids)
self.assert_survivors([])
self.assertIs(wr(), None)
self.assertIsNone(wr())


class ChainedBase:
Expand Down Expand Up @@ -378,18 +383,27 @@ def check_non_resurrecting_chain(self, classes):

def check_resurrecting_chain(self, classes):
N = len(classes)
def dummy_callback(ref):
pass
with SimpleBase.test():
nodes = self.build_chain(classes)
N = len(nodes)
ids = [id(s) for s in nodes]
survivor_ids = [id(s) for s in nodes if isinstance(s, SimpleResurrector)]
wrs = [weakref.ref(s) for s in nodes]
wrcs = [weakref.ref(s, dummy_callback) for s in nodes]
del nodes
gc.collect()
self.assert_del_calls(ids)
self.assert_survivors(survivor_ids)
# XXX desirable?
self.assertEqual([wr() for wr in wrs], [None] * N)
for wr in wrs:
# These values used to be None because weakrefs were cleared
# before calling finalizers. Now they are cleared after.
self.assertIsNotNone(wr())
for wr in wrcs:
# Weakrefs with callbacks are still cleared before calling
# finalizers.
self.assertIsNone(wr())
self.clear_survivors()
gc.collect()
self.assert_del_calls(ids)
Expand Down Expand Up @@ -491,7 +505,7 @@ def test_legacy(self):
self.assert_del_calls(ids)
self.assert_tp_del_calls(ids)
self.assert_survivors([])
self.assertIs(wr(), None)
self.assertIsNone(wr())
gc.collect()
self.assert_del_calls(ids)
self.assert_tp_del_calls(ids)
Expand All @@ -507,13 +521,13 @@ def test_legacy_resurrect(self):
self.assert_tp_del_calls(ids)
self.assert_survivors(ids)
# weakrefs are cleared before tp_del is called.
self.assertIs(wr(), None)
self.assertIsNone(wr())
self.clear_survivors()
gc.collect()
self.assert_del_calls(ids)
self.assert_tp_del_calls(ids * 2)
self.assert_survivors(ids)
self.assertIs(wr(), None)
self.assertIsNone(wr())

def test_legacy_self_cycle(self):
# Self-cycles with legacy finalizers end up in gc.garbage.
Expand All @@ -527,11 +541,11 @@ def test_legacy_self_cycle(self):
self.assert_tp_del_calls([])
self.assert_survivors([])
self.assert_garbage(ids)
self.assertIsNot(wr(), None)
self.assertIsNotNone(wr())
# Break the cycle to allow collection
gc.garbage[0].ref = None
self.assert_garbage([])
self.assertIs(wr(), None)
self.assertIsNone(wr())


if __name__ == "__main__":
Expand Down
Loading
Loading