]> 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 68518d78f2ab48a1f7f39567b818872ce74c9ebc..262ee12a5fe708c79f91f8d57c6c2f361e2223b2 100644 (file)
@@ -1,8 +1,10 @@
 # tests for slice objects; in particular the indices method.
 
 import unittest
-from test import test_support
+import weakref
+
 from cPickle import loads, dumps
+from test import test_support
 
 import sys
 
@@ -128,6 +130,15 @@ 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())
+
 def test_main():
     test_support.run_unittest(SliceTest)
 
index 9288612dd85e2c683a510f91cde323b56717b161..6a80a280a0458d3f41de41ebb8cd6ff5b208e7bb 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -10,6 +10,8 @@ What's New in Python 2.7.12?
 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 767a50a8c056bf4f9466140bc523b633abbb5641..3c996f9672e027bcdd65c86a747c511ae4102007 100644 (file)
@@ -60,7 +60,7 @@ PyObject _Py_EllipsisObject = {
 PyObject *
 PySlice_New(PyObject *start, PyObject *stop, PyObject *step)
 {
-    PySliceObject *obj = PyObject_New(PySliceObject, &PySlice_Type);
+    PySliceObject *obj = PyObject_GC_New(PySliceObject, &PySlice_Type);
 
     if (obj == NULL)
         return NULL;
@@ -76,6 +76,7 @@ PySlice_New(PyObject *start, PyObject *stop, PyObject *step)
     obj->start = start;
     obj->stop = stop;
 
+    _PyObject_GC_TRACK(obj);
     return (PyObject *) obj;
 }
 
@@ -219,10 +220,11 @@ 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);
-    PyObject_Del(r);
+    PyObject_GC_Del(r);
 }
 
 static PyObject *
@@ -320,6 +322,15 @@ slice_hash(PySliceObject *v)
     return -1L;
 }
 
+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 */
@@ -340,9 +351,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 */
     0,                                          /* tp_richcompare */
     0,                                          /* tp_weaklistoffset */