[Python-checkins] r68265 - in python/branches/release30-maint: Lib/test/test_deque.py Lib/test/test_dict.py Lib/test/test_set.py Misc/NEWS Modules/_collectionsmodule.c Objects/dictobject.c Objects/setobject.c
georg.brandl
python-checkins at python.org
Sun Jan 4 00:52:55 CET 2009
Author: georg.brandl
Date: Sun Jan 4 00:52:55 2009
New Revision: 68265
Log:
Merged revisions 68132 via svnmerge from
svn+ssh://svn.python.org/python/branches/py3k
................
r68132 | antoine.pitrou | 2009-01-01 16:35:33 +0100 (Thu, 01 Jan 2009) | 9 lines
Merged revisions 68128 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/trunk
........
r68128 | antoine.pitrou | 2009-01-01 15:11:22 +0100 (jeu., 01 janv. 2009) | 3 lines
Issue #3680: Reference cycles created through a dict, set or deque iterator did not get collected.
........
................
Modified:
python/branches/release30-maint/ (props changed)
python/branches/release30-maint/Lib/test/test_deque.py
python/branches/release30-maint/Lib/test/test_dict.py
python/branches/release30-maint/Lib/test/test_set.py
python/branches/release30-maint/Misc/NEWS
python/branches/release30-maint/Modules/_collectionsmodule.c
python/branches/release30-maint/Objects/dictobject.c
python/branches/release30-maint/Objects/setobject.c
Modified: python/branches/release30-maint/Lib/test/test_deque.py
==============================================================================
--- python/branches/release30-maint/Lib/test/test_deque.py (original)
+++ python/branches/release30-maint/Lib/test/test_deque.py Sun Jan 4 00:52:55 2009
@@ -1,7 +1,8 @@
from collections import deque
import unittest
from test import support, seq_tests
-from weakref import proxy
+import gc
+import weakref
import copy
import pickle
from io import StringIO
@@ -420,6 +421,22 @@
d.append(1)
gc.collect()
+ def test_container_iterator(self):
+ # Bug #3680: tp_traverse was not implemented for deque iterator objects
+ class C(object):
+ pass
+ for i in range(2):
+ obj = C()
+ ref = weakref.ref(obj)
+ if i == 0:
+ container = deque([obj, 1])
+ else:
+ container = reversed(deque([obj, 1]))
+ obj.x = iter(container)
+ del obj, container
+ gc.collect()
+ self.assert_(ref() is None, "Cycle was not collected")
+
class TestVariousIteratorArgs(unittest.TestCase):
def test_constructor(self):
@@ -530,7 +547,7 @@
def test_weakref(self):
d = deque('gallahad')
- p = proxy(d)
+ p = weakref.proxy(d)
self.assertEqual(str(p), str(d))
d = None
self.assertRaises(ReferenceError, str, p)
Modified: python/branches/release30-maint/Lib/test/test_dict.py
==============================================================================
--- python/branches/release30-maint/Lib/test/test_dict.py (original)
+++ python/branches/release30-maint/Lib/test/test_dict.py Sun Jan 4 00:52:55 2009
@@ -2,6 +2,7 @@
from test import support
import sys, collections, random, string
+import gc, weakref
class DictTest(unittest.TestCase):
@@ -648,6 +649,21 @@
pass
d = {}
+ def test_container_iterator(self):
+ # Bug #3680: tp_traverse was not implemented for dictiter and
+ # dictview objects.
+ class C(object):
+ pass
+ views = (dict.items, dict.values, dict.keys)
+ for v in views:
+ obj = C()
+ ref = weakref.ref(obj)
+ container = {obj: 1}
+ obj.v = v(container)
+ obj.x = iter(obj.v)
+ del obj, container
+ gc.collect()
+ self.assert_(ref() is None, "Cycle was not collected")
from test import mapping_tests
Modified: python/branches/release30-maint/Lib/test/test_set.py
==============================================================================
--- python/branches/release30-maint/Lib/test/test_set.py (original)
+++ python/branches/release30-maint/Lib/test/test_set.py Sun Jan 4 00:52:55 2009
@@ -1,6 +1,7 @@
import unittest
from test import support
-from weakref import proxy
+import gc
+import weakref
import operator
import copy
import pickle
@@ -323,6 +324,18 @@
self.assertEqual(sum(elem.hash_count for elem in d), n)
self.assertEqual(d3, dict.fromkeys(d, 123))
+ def test_container_iterator(self):
+ # Bug #3680: tp_traverse was not implemented for set iterator object
+ class C(object):
+ pass
+ obj = C()
+ ref = weakref.ref(obj)
+ container = set([obj, 1])
+ obj.x = iter(container)
+ del obj, container
+ gc.collect()
+ self.assert_(ref() is None, "Cycle was not collected")
+
class TestSet(TestJointOps):
thetype = set
basetype = set
@@ -546,7 +559,7 @@
def test_weakref(self):
s = self.thetype('gallahad')
- p = proxy(s)
+ p = weakref.proxy(s)
self.assertEqual(str(p), str(s))
s = None
self.assertRaises(ReferenceError, str, p)
Modified: python/branches/release30-maint/Misc/NEWS
==============================================================================
--- python/branches/release30-maint/Misc/NEWS (original)
+++ python/branches/release30-maint/Misc/NEWS Sun Jan 4 00:52:55 2009
@@ -25,6 +25,9 @@
- Issue #4747: When the terminal does not use utf-8, executing a script with
non-ascii characters in its name could fail with a "SyntaxError: None" error.
+- Issue #3680: Reference cycles created through a dict, set or deque iterator
+ did not get collected.
+
- Issue #4701: PyObject_Hash now implicitly calls PyType_Ready on types
where the tp_hash and tp_dict slots are both NULL.
Modified: python/branches/release30-maint/Modules/_collectionsmodule.c
==============================================================================
--- python/branches/release30-maint/Modules/_collectionsmodule.c (original)
+++ python/branches/release30-maint/Modules/_collectionsmodule.c Sun Jan 4 00:52:55 2009
@@ -900,7 +900,7 @@
{
dequeiterobject *it;
- it = PyObject_New(dequeiterobject, &dequeiter_type);
+ it = PyObject_GC_New(dequeiterobject, &dequeiter_type);
if (it == NULL)
return NULL;
it->b = deque->leftblock;
@@ -909,14 +909,22 @@
it->deque = deque;
it->state = deque->state;
it->counter = deque->len;
+ _PyObject_GC_TRACK(it);
return (PyObject *)it;
}
+static int
+dequeiter_traverse(dequeiterobject *dio, visitproc visit, void *arg)
+{
+ Py_VISIT(dio->deque);
+ return 0;
+}
+
static void
dequeiter_dealloc(dequeiterobject *dio)
{
Py_XDECREF(dio->deque);
- Py_TYPE(dio)->tp_free(dio);
+ PyObject_GC_Del(dio);
}
static PyObject *
@@ -981,9 +989,9 @@
PyObject_GenericGetAttr, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT, /* tp_flags */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
0, /* tp_doc */
- 0, /* tp_traverse */
+ (traverseproc)dequeiter_traverse, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
@@ -1002,7 +1010,7 @@
{
dequeiterobject *it;
- it = PyObject_New(dequeiterobject, &dequereviter_type);
+ it = PyObject_GC_New(dequeiterobject, &dequereviter_type);
if (it == NULL)
return NULL;
it->b = deque->rightblock;
@@ -1011,6 +1019,7 @@
it->deque = deque;
it->state = deque->state;
it->counter = deque->len;
+ _PyObject_GC_TRACK(it);
return (PyObject *)it;
}
@@ -1063,9 +1072,9 @@
PyObject_GenericGetAttr, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT, /* tp_flags */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
0, /* tp_doc */
- 0, /* tp_traverse */
+ (traverseproc)dequeiter_traverse, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
Modified: python/branches/release30-maint/Objects/dictobject.c
==============================================================================
--- python/branches/release30-maint/Objects/dictobject.c (original)
+++ python/branches/release30-maint/Objects/dictobject.c Sun Jan 4 00:52:55 2009
@@ -2122,7 +2122,7 @@
dictiter_new(PyDictObject *dict, PyTypeObject *itertype)
{
dictiterobject *di;
- di = PyObject_New(dictiterobject, itertype);
+ di = PyObject_GC_New(dictiterobject, itertype);
if (di == NULL)
return NULL;
Py_INCREF(dict);
@@ -2139,6 +2139,7 @@
}
else
di->di_result = NULL;
+ _PyObject_GC_TRACK(di);
return (PyObject *)di;
}
@@ -2147,7 +2148,15 @@
{
Py_XDECREF(di->di_dict);
Py_XDECREF(di->di_result);
- PyObject_Del(di);
+ PyObject_GC_Del(di);
+}
+
+static int
+dictiter_traverse(dictiterobject *di, visitproc visit, void *arg)
+{
+ Py_VISIT(di->di_dict);
+ Py_VISIT(di->di_result);
+ return 0;
}
static PyObject *
@@ -2228,9 +2237,9 @@
PyObject_GenericGetAttr, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT, /* tp_flags */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
0, /* tp_doc */
- 0, /* tp_traverse */
+ (traverseproc)dictiter_traverse, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
@@ -2300,9 +2309,9 @@
PyObject_GenericGetAttr, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT, /* tp_flags */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
0, /* tp_doc */
- 0, /* tp_traverse */
+ (traverseproc)dictiter_traverse, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
@@ -2386,9 +2395,9 @@
PyObject_GenericGetAttr, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT, /* tp_flags */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
0, /* tp_doc */
- 0, /* tp_traverse */
+ (traverseproc)dictiter_traverse, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
@@ -2415,7 +2424,14 @@
dictview_dealloc(dictviewobject *dv)
{
Py_XDECREF(dv->dv_dict);
- PyObject_Del(dv);
+ PyObject_GC_Del(dv);
+}
+
+static int
+dictview_traverse(dictviewobject *dv, visitproc visit, void *arg)
+{
+ Py_VISIT(dv->dv_dict);
+ return 0;
}
static Py_ssize_t
@@ -2442,11 +2458,12 @@
type->tp_name, dict->ob_type->tp_name);
return NULL;
}
- dv = PyObject_New(dictviewobject, type);
+ dv = PyObject_GC_New(dictviewobject, type);
if (dv == NULL)
return NULL;
Py_INCREF(dict);
dv->dv_dict = (PyDictObject *)dict;
+ _PyObject_GC_TRACK(dv);
return (PyObject *)dv;
}
@@ -2693,9 +2710,9 @@
PyObject_GenericGetAttr, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT, /* tp_flags */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
0, /* tp_doc */
- 0, /* tp_traverse */
+ (traverseproc)dictview_traverse, /* tp_traverse */
0, /* tp_clear */
dictview_richcompare, /* tp_richcompare */
0, /* tp_weaklistoffset */
@@ -2777,9 +2794,9 @@
PyObject_GenericGetAttr, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT, /* tp_flags */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
0, /* tp_doc */
- 0, /* tp_traverse */
+ (traverseproc)dictview_traverse, /* tp_traverse */
0, /* tp_clear */
dictview_richcompare, /* tp_richcompare */
0, /* tp_weaklistoffset */
@@ -2842,9 +2859,9 @@
PyObject_GenericGetAttr, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT, /* tp_flags */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
0, /* tp_doc */
- 0, /* tp_traverse */
+ (traverseproc)dictview_traverse, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
Modified: python/branches/release30-maint/Objects/setobject.c
==============================================================================
--- python/branches/release30-maint/Objects/setobject.c (original)
+++ python/branches/release30-maint/Objects/setobject.c Sun Jan 4 00:52:55 2009
@@ -802,7 +802,14 @@
setiter_dealloc(setiterobject *si)
{
Py_XDECREF(si->si_set);
- PyObject_Del(si);
+ PyObject_GC_Del(si);
+}
+
+static int
+setiter_traverse(setiterobject *si, visitproc visit, void *arg)
+{
+ Py_VISIT(si->si_set);
+ return 0;
}
static PyObject *
@@ -880,9 +887,9 @@
PyObject_GenericGetAttr, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT, /* tp_flags */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
0, /* tp_doc */
- 0, /* tp_traverse */
+ (traverseproc)setiter_traverse, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
@@ -895,7 +902,7 @@
static PyObject *
set_iter(PySetObject *so)
{
- setiterobject *si = PyObject_New(setiterobject, &PySetIter_Type);
+ setiterobject *si = PyObject_GC_New(setiterobject, &PySetIter_Type);
if (si == NULL)
return NULL;
Py_INCREF(so);
@@ -903,6 +910,7 @@
si->si_used = so->used;
si->si_pos = 0;
si->len = so->used;
+ _PyObject_GC_TRACK(si);
return (PyObject *)si;
}
More information about the Python-checkins
mailing list