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 @@ -37,6 +37,9 @@ What's New in Python 3.2 Alpha 3?
3737Core and Builtins
3838-----------------
3939
40+ - Issue #10068: Global objects which have reference cycles with their module's
41+ dict are now cleared again. This causes issue #7140 to appear again.
42+
4043- Issue #9738: Document PyErr_SetString() and PyErr_SetFromErrnoWithFilename()
4144 encodings.
4245
Original file line number Diff line number Diff line change @@ -335,10 +335,7 @@ module_dealloc(PyModuleObject *m)
335335 if (m -> md_def && m -> md_def -> m_free )
336336 m -> md_def -> m_free (m );
337337 if (m -> md_dict != NULL ) {
338- /* If we are the only ones holding a reference, we can clear
339- the dictionary. */
340- if (Py_REFCNT (m -> md_dict ) == 1 )
341- _PyModule_Clear ((PyObject * )m );
338+ _PyModule_Clear ((PyObject * )m );
342339 Py_DECREF (m -> md_dict );
343340 }
344341 if (m -> md_state != NULL )
You can’t perform that action at this time.
0 commit comments