\versionadded{2.2}
\end{funcdesc}
+\begin{funcdesc}{get_referrents}{*objs}
+Return a list of objects directly referred to by any of the arguments.
+The referrents returned are those objects visited by the arguments'
+C-level \cfunction{tp_traverse} methods (if any), and may not be all
+objects actually directly reachable. \cfunction{tp_traverse} methods
+are supported only by objects that support garbage collection, and are
+only required to visit objects that may be involved in a cycle. So,
+for example, if an integer is directly reachable from an argument, that
+integer object may or may not appear in the result list.
+
+\versionadded{2.3}
+\end{funcdesc}
+
The following variable is provided for read-only access (you can
mutate its value but should not rebind it):
def expect(actual, expected, name):
if actual != expected:
- raise TestFailed, "test_%s: actual %d, expected %d" % (
+ raise TestFailed, "test_%s: actual %r, expected %r" % (
name, actual, expected)
def expect_nonzero(actual, name):
expect(gc.collect(), 4, "boom2")
expect(len(gc.garbage), garbagelen, "boom2")
+def test_get_referrents():
+ alist = [1, 3, 5]
+ got = gc.get_referrents(alist)
+ got.sort()
+ expect(got, alist, "get_referrents")
+
+ atuple = tuple(alist)
+ got = gc.get_referrents(atuple)
+ got.sort()
+ expect(got, alist, "get_referrents")
+
+ adict = {1: 3, 5: 7}
+ expected = [1, 3, 5, 7]
+ got = gc.get_referrents(adict)
+ got.sort()
+ expect(got, expected, "get_referrents")
+
+ got = gc.get_referrents([1, 2], {3: 4}, (0, 0, 0))
+ got.sort()
+ expect(got, [0, 0] + range(5), "get_referrents")
+
+ expect(gc.get_referrents(1, 'a', 4j), [], "get_referrents")
+
def test_all():
gc.collect() # Delete 2nd generation garbage
run_test("lists", test_list)
run_test("trashcan", test_trashcan)
run_test("boom", test_boom)
run_test("boom2", test_boom2)
+ run_test("get_referrents", test_get_referrents)
def test():
if verbose:
Extension modules
-----------------
+- New function gc.get_referrents(obj) returns a list of objects
+ directly referenced by obj. In effect, it exposes what the object's
+ tp_traverse slot does, and can be helpful when debugging memory
+ leaks.
+
- The iconv module has been removed from this release.
- The platform-independent routines for packing floats in IEEE formats
return result;
}
+/* Append obj to list; return true if error (out of memory), false if OK. */
static int
referrentsvisit(PyObject *obj, PyObject *list)
{
- if (PyList_Append(list, obj) < 0)
- return 1;
- return 0;
+ return PyList_Append(list, obj) < 0;
}
PyDoc_STRVAR(gc_get_referrents__doc__,
{
int i;
PyObject *result = PyList_New(0);
+
+ if (result == NULL)
+ return NULL;
+
for (i = 0; i < PyTuple_GET_SIZE(args); i++) {
+ traverseproc traverse;
PyObject *obj = PyTuple_GET_ITEM(args, i);
- traverseproc traverse = obj->ob_type->tp_traverse;
- if (!traverse)
+
+ if (! PyObject_IS_GC(obj))
+ continue;
+ traverse = obj->ob_type->tp_traverse;
+ if (! traverse)
continue;
- if (traverse(obj, (visitproc)referrentsvisit, result))
+ if (traverse(obj, (visitproc)referrentsvisit, result)) {
+ Py_DECREF(result);
return NULL;
+ }
}
return result;
}