[Python-checkins] r85392 - in python/branches/py3k: Doc/reference/datamodel.rst Lib/test/test_module.py Misc/NEWS Objects/moduleobject.c
benjamin.peterson
python-checkins at python.org
Wed Oct 13 00:57:59 CEST 2010
Author: benjamin.peterson
Date: Wed Oct 13 00:57:59 2010
New Revision: 85392
Log:
prefer clearing global objects to obscure module.__dict__ bugs #10068
Modified:
python/branches/py3k/Doc/reference/datamodel.rst
python/branches/py3k/Lib/test/test_module.py
python/branches/py3k/Misc/NEWS
python/branches/py3k/Objects/moduleobject.c
Modified: python/branches/py3k/Doc/reference/datamodel.rst
==============================================================================
--- python/branches/py3k/Doc/reference/datamodel.rst (original)
+++ python/branches/py3k/Doc/reference/datamodel.rst Wed Oct 13 00:57:59 2010
@@ -654,6 +654,13 @@
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)
Modified: python/branches/py3k/Lib/test/test_module.py
==============================================================================
--- python/branches/py3k/Lib/test/test_module.py (original)
+++ python/branches/py3k/Lib/test/test_module.py Wed Oct 13 00:57:59 2010
@@ -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 @@
{"__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)
Modified: python/branches/py3k/Misc/NEWS
==============================================================================
--- python/branches/py3k/Misc/NEWS (original)
+++ python/branches/py3k/Misc/NEWS Wed Oct 13 00:57:59 2010
@@ -37,6 +37,9 @@
Core and Builtins
-----------------
+- 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 #9738: Document PyErr_SetString() and PyErr_SetFromErrnoWithFilename()
encodings.
Modified: python/branches/py3k/Objects/moduleobject.c
==============================================================================
--- python/branches/py3k/Objects/moduleobject.c (original)
+++ python/branches/py3k/Objects/moduleobject.c Wed Oct 13 00:57:59 2010
@@ -335,10 +335,7 @@
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)
More information about the Python-checkins
mailing list