]> granicus.if.org Git - python/commitdiff
add gc support to slice (closes #26659)
authorBenjamin Peterson <benjamin@python.org>
Sat, 16 Apr 2016 21:47:12 +0000 (14:47 -0700)
committerBenjamin Peterson <benjamin@python.org>
Sat, 16 Apr 2016 21:47:12 +0000 (14:47 -0700)
Lib/test/test_slice.py
Misc/NEWS
Objects/sliceobject.c

index 8c4e670c9d416fc8f6e1abcdf96059c4a31ab185..5e76655ee6deeed830f2162d232ac71219220f14 100644 (file)
@@ -1,11 +1,13 @@
 # tests for slice objects; in particular the indices method.
 
-import unittest
-from pickle import loads, dumps
-
 import itertools
 import operator
 import sys
+import unittest
+import weakref
+
+from pickle import loads, dumps
+from test import support
 
 
 def evaluate_slice_index(arg):
@@ -240,5 +242,14 @@ class SliceTest(unittest.TestCase):
             self.assertEqual(s.indices(15), t.indices(15))
             self.assertNotEqual(id(s), id(t))
 
+    def test_cycle(self):
+        class myobj(): pass
+        o = myobj()
+        o.s = slice(o)
+        w = weakref.ref(o)
+        o = None
+        test_support.gc_collect()
+        self.assertIsNone(w())
+
 if __name__ == "__main__":
     unittest.main()
index 8bf583f4d04776ec104e6b6d1c9b69007392905d..ec6626ffd01b25efbc7526fe862187687dbeb06a 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -10,6 +10,8 @@ Release date: tba
 Core and Builtins
 -----------------
 
+- Issue #26659: Make the builtin slice type support cycle collection.
+
 - Issue #26718: super.__init__ no longer leaks memory if called multiple times.
   NOTE: A direct call of super.__init__ is not endorsed!
 
index 104952333a5ae3ed3214c1b9dbf67b25a206fe82..bf5eb3aeee80950f70f0c10f83cef73f49c57a30 100644 (file)
@@ -119,7 +119,7 @@ PySlice_New(PyObject *start, PyObject *stop, PyObject *step)
         slice_cache = NULL;
         _Py_NewReference((PyObject *)obj);
     } else {
-        obj = PyObject_New(PySliceObject, &PySlice_Type);
+        obj = PyObject_GC_New(PySliceObject, &PySlice_Type);
         if (obj == NULL)
             return NULL;
     }
@@ -135,6 +135,7 @@ PySlice_New(PyObject *start, PyObject *stop, PyObject *step)
     obj->start = start;
     obj->stop = stop;
 
+    _PyObject_GC_TRACK(obj);
     return (PyObject *) obj;
 }
 
@@ -288,13 +289,14 @@ Create a slice object.  This is used for extended slicing (e.g. a[0:10:2]).");
 static void
 slice_dealloc(PySliceObject *r)
 {
+    _PyObject_GC_UNTRACK(r);
     Py_DECREF(r->step);
     Py_DECREF(r->start);
     Py_DECREF(r->stop);
     if (slice_cache == NULL)
         slice_cache = r;
     else
-        PyObject_Del(r);
+        PyObject_GC_Del(r);
 }
 
 static PyObject *
@@ -586,6 +588,15 @@ slice_richcompare(PyObject *v, PyObject *w, int op)
     return res;
 }
 
+static int
+slice_traverse(PySliceObject *v, visitproc visit, void *arg)
+{
+    Py_VISIT(v->start);
+    Py_VISIT(v->stop);
+    Py_VISIT(v->step);
+    return 0;
+}
+
 PyTypeObject PySlice_Type = {
     PyVarObject_HEAD_INIT(&PyType_Type, 0)
     "slice",                    /* Name of this type */
@@ -606,9 +617,9 @@ PyTypeObject PySlice_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 */
     slice_doc,                                  /* tp_doc */
-    0,                                          /* tp_traverse */
+    (traverseproc)slice_traverse,               /* tp_traverse */
     0,                                          /* tp_clear */
     slice_richcompare,                          /* tp_richcompare */
     0,                                          /* tp_weaklistoffset */