Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings
Merged
31 changes: 31 additions & 0 deletions 31 Lib/test/test_gc.py
Original file line number Diff line number Diff line change
Expand Up @@ -1155,6 +1155,37 @@ def test_something(self):
""")
assert_python_ok("-c", source)

def test_do_not_cleanup_type_subclasses_before_finalization(self):
# See https://github.com/python/cpython/issues/135552
# If we cleanup weakrefs for tp_subclasses before calling
# the finalizer (__del__) then the line `fail = BaseNode.next.next`
# should fail because we are trying to access a subclass
# attribute. But subclass type cache was not properly invalidated.
code = """
class BaseNode:
def __del__(self):
BaseNode.next = BaseNode.next.next
fail = BaseNode.next.next

class Node(BaseNode):
pass

BaseNode.next = Node()
BaseNode.next.next = Node()
"""
# this test checks garbage collection while interp
# finalization
assert_python_ok("-c", textwrap.dedent(code))

code_inside_function = textwrap.dedent(F"""
def test():
{textwrap.indent(code, ' ')}

test()
""")
# this test checks regular garbage collection
assert_python_ok("-c", code_inside_function)


class IncrementalGCTests(unittest.TestCase):
@unittest.skipIf(_testinternalcapi is None, "requires _testinternalcapi")
Expand Down
26 changes: 26 additions & 0 deletions 26 Lib/test/test_weakref.py
Original file line number Diff line number Diff line change
Expand Up @@ -1044,6 +1044,32 @@ def callback(obj):
stderr = res.err.decode("ascii", "backslashreplace")
self.assertNotRegex(stderr, "_Py_Dealloc: Deallocator of type 'TestObj'")

def test_clearing_weakrefs_in_gc(self):
# This test checks that when finalizers are called:
# 1. weakrefs with callbacks have been cleared
# 2. weakrefs without callbacks have not been cleared
errors = []
def test():
class Class:
def __init__(self):
self._self = self
self.wr1 = weakref.ref(Class, lambda x: None)
self.wr2 = weakref.ref(Class)

def __del__(self):
# we can't use assert* here, because gc will swallow
# exceptions
if self.wr1() is not None:
errors.append("weakref with callback as cleared")
if self.wr2() is not Class:
errors.append("weakref without callback was cleared")

Class()

test()
gc.collect()
self.assertEqual(errors, [])


class SubclassableWeakrefTestCase(TestBase):

Expand Down
Loading
Morty Proxy This is a proxified and sanitized view of the page, visit original site.