]> granicus.if.org Git - python/commitdiff
Backport r61286 adding GC to the grouper for itertools.groupby() fixing Issue 2246.
authorRaymond Hettinger <python@rcn.com>
Thu, 6 Mar 2008 22:58:42 +0000 (22:58 +0000)
committerRaymond Hettinger <python@rcn.com>
Thu, 6 Mar 2008 22:58:42 +0000 (22:58 +0000)
Lib/test/test_itertools.py
Modules/itertoolsmodule.c

index 99f9077013c5a20fea8819dfa7d6f614755b0e97..e949cf6ce76ceec1a09768a7dc98b5a5816e3f72 100644 (file)
@@ -449,6 +449,13 @@ class TestGC(unittest.TestCase):
         a = []
         self.makecycle(groupby([a]*2, lambda x:x), a)
 
+    def test_issue2246(self):
+        # Issue 2246 -- the _grouper iterator was not included in GC
+        n = 10
+        keyfunc = lambda x: x
+        for i, j in groupby(xrange(n), key=keyfunc):
+            keyfunc.__dict__.setdefault('x',[]).append(j)
+
     def test_ifilter(self):
         a = []
         self.makecycle(ifilter(lambda x:True, [a]*2), a)
index 31f20c710c732431edd1c034aa93463558b9799d..55731eb92f0fea4d861abde0958b211e38bb4f41 100644 (file)
@@ -199,7 +199,7 @@ _grouper_create(groupbyobject *parent, PyObject *tgtkey)
 {
        _grouperobject *igo;
 
-       igo = PyObject_New(_grouperobject, &_grouper_type);
+       igo = PyObject_GC_New(_grouperobject, &_grouper_type);
        if (igo == NULL)
                return NULL;
        igo->parent = (PyObject *)parent;
@@ -207,15 +207,25 @@ _grouper_create(groupbyobject *parent, PyObject *tgtkey)
        igo->tgtkey = tgtkey;
        Py_INCREF(tgtkey);
 
+       PyObject_GC_Track(igo);
        return (PyObject *)igo;
 }
 
 static void
 _grouper_dealloc(_grouperobject *igo)
 {
+       PyObject_GC_UnTrack(igo);
        Py_DECREF(igo->parent);
        Py_DECREF(igo->tgtkey);
-       PyObject_Del(igo);
+       PyObject_GC_Del(igo);
+}
+
+static int
+_grouper_traverse(_grouperobject *igo, visitproc visit, void *arg)
+{
+       Py_VISIT(igo->parent);
+       Py_VISIT(igo->tgtkey);
+       return 0;
 }
 
 static PyObject *
@@ -282,9 +292,9 @@ static PyTypeObject _grouper_type = {
        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)_grouper_traverse,/* tp_traverse */
        0,                              /* tp_clear */
        0,                              /* tp_richcompare */
        0,                              /* tp_weaklistoffset */
@@ -301,7 +311,7 @@ static PyTypeObject _grouper_type = {
        0,                              /* tp_init */
        0,                              /* tp_alloc */
        0,                              /* tp_new */
-       PyObject_Del,                   /* tp_free */
+       PyObject_GC_Del,                /* tp_free */
 };