File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -654,6 +654,13 @@ Modules
654654 Special read-only attribute: :attr: `__dict__ ` is the module's namespace as a
655655 dictionary object.
656656
657+ .. impl-detail ::
658+
659+ Because of the way CPython clears module dictionaries, the module
660+ dictionary will be cleared when the module falls out of scope even if the
661+ dictionary still has live references. To avoid this, copy the dictionary
662+ or keep the module around while using its dictionary directly.
663+
657664 .. index ::
658665 single: __name__ (module attribute)
659666 single: __doc__ (module attribute)
Original file line number Diff line number Diff line change 11# Test the module type
22import unittest
3- from test .support import run_unittest
3+ from test .support import run_unittest , gc_collect
44
55import sys
66ModuleType = type (sys )
@@ -55,14 +55,29 @@ def test_reinit(self):
5555 {"__name__" : "foo" , "__doc__" : "foodoc" , "bar" : 42 })
5656 self .assertTrue (foo .__dict__ is d )
5757
58+ @unittest .expectedFailure
5859 def test_dont_clear_dict (self ):
5960 # See issue 7140.
6061 def f ():
6162 foo = ModuleType ("foo" )
6263 foo .bar = 4
6364 return foo
65+ gc_collect ()
6466 self .assertEqual (f ().__dict__ ["bar" ], 4 )
6567
68+ def test_clear_dict_in_ref_cycle (self ):
69+ destroyed = []
70+ m = ModuleType ("foo" )
71+ m .destroyed = destroyed
72+ s = """class A:
73+ def __del__(self):
74+ destroyed.append(1)
75+ a = A()"""
76+ exec (s , m .__dict__ )
77+ del m
78+ gc_collect ()
79+ self .assertEqual (destroyed , [1 ])
80+
6681def test_main ():
6782 run_unittest (ModuleTests )
6883
Original file line number Diff line number Diff line change @@ -46,6 +46,9 @@ Core and Builtins
4646
4747- Issue #83755: Implicit set-to-frozenset conversion was not thread-safe.
4848
49+ - Issue #10068: Global objects which have reference cycles with their module's
50+ dict are now cleared again. This causes issue #7140 to appear again.
51+
4952- Issue #9416: Fix some issues with complex formatting where the
5053 output with no type specifier failed to match the str output:
5154
Original file line number Diff line number Diff line change @@ -312,10 +312,7 @@ module_dealloc(PyModuleObject *m)
312312 if (m -> md_def && m -> md_def -> m_free )
313313 m -> md_def -> m_free (m );
314314 if (m -> md_dict != NULL ) {
315- /* If we are the only ones holding a reference, we can clear
316- the dictionary. */
317- if (Py_REFCNT (m -> md_dict ) == 1 )
318- _PyModule_Clear ((PyObject * )m );
315+ _PyModule_Clear ((PyObject * )m );
319316 Py_DECREF (m -> md_dict );
320317 }
321318 if (m -> md_state != NULL )
You can’t perform that action at this time.
0 commit comments