Merged revisions 85392 via svnmerge from

svn+ssh://pythondev@svn.python.org/python/branches/py3k

........
  r85392 | benjamin.peterson | 2010-10-12 17:57:59 -0500 (Tue, 12 Oct 2010) | 1 line

  prefer clearing global objects to obscure module.__dict__ bugs #10068
........
This commit is contained in:
Benjamin Peterson 2010-10-12 23:06:22 +00:00
parent 93f5cd42e7
commit 582162e42b
4 changed files with 27 additions and 5 deletions

View File

@ -654,6 +654,13 @@ Modules
Special read-only attribute: :attr:`__dict__` is the module's namespace as a
dictionary object.
.. impl-detail::
Because of the way CPython clears module dictionaries, the module
dictionary will be cleared when the module falls out of scope even if the
dictionary still has live references. To avoid this, copy the dictionary
or keep the module around while using its dictionary directly.
.. index::
single: __name__ (module attribute)
single: __doc__ (module attribute)

View File

@ -1,6 +1,6 @@
# Test the module type
import unittest
from test.support import run_unittest
from test.support import run_unittest, gc_collect
import sys
ModuleType = type(sys)
@ -55,14 +55,29 @@ def test_reinit(self):
{"__name__": "foo", "__doc__": "foodoc", "bar": 42})
self.assertTrue(foo.__dict__ is d)
@unittest.expectedFailure
def test_dont_clear_dict(self):
# See issue 7140.
def f():
foo = ModuleType("foo")
foo.bar = 4
return foo
gc_collect()
self.assertEqual(f().__dict__["bar"], 4)
def test_clear_dict_in_ref_cycle(self):
destroyed = []
m = ModuleType("foo")
m.destroyed = destroyed
s = """class A:
def __del__(self):
destroyed.append(1)
a = A()"""
exec(s, m.__dict__)
del m
gc_collect()
self.assertEqual(destroyed, [1])
def test_main():
run_unittest(ModuleTests)

View File

@ -46,6 +46,9 @@ Core and Builtins
- Issue #83755: Implicit set-to-frozenset conversion was not thread-safe.
- Issue #10068: Global objects which have reference cycles with their module's
dict are now cleared again. This causes issue #7140 to appear again.
- Issue #9416: Fix some issues with complex formatting where the
output with no type specifier failed to match the str output:

View File

@ -312,10 +312,7 @@ module_dealloc(PyModuleObject *m)
if (m->md_def && m->md_def->m_free)
m->md_def->m_free(m);
if (m->md_dict != NULL) {
/* If we are the only ones holding a reference, we can clear
the dictionary. */
if (Py_REFCNT(m->md_dict) == 1)
_PyModule_Clear((PyObject *)m);
_PyModule_Clear((PyObject *)m);
Py_DECREF(m->md_dict);
}
if (m->md_state != NULL)