bpo-36016: Add generation option to gc.getobjects() (GH-11909)
This commit is contained in:
parent
df5cdc1112
commit
175421b58c
|
@ -63,11 +63,14 @@ The :mod:`gc` module provides the following functions:
|
||||||
Return the debugging flags currently set.
|
Return the debugging flags currently set.
|
||||||
|
|
||||||
|
|
||||||
.. function:: get_objects()
|
.. function:: get_objects(generation=None)
|
||||||
|
|
||||||
Returns a list of all objects tracked by the collector, excluding the list
|
Returns a list of all objects tracked by the collector, excluding the list
|
||||||
returned.
|
returned. If *generation* is not None, return only the objects tracked by
|
||||||
|
the collector that are in that generation.
|
||||||
|
|
||||||
|
.. versionchanged:: 3.8
|
||||||
|
New *generation* parameter.
|
||||||
|
|
||||||
.. function:: get_stats()
|
.. function:: get_stats()
|
||||||
|
|
||||||
|
|
|
@ -163,6 +163,15 @@ gettext
|
||||||
Added :func:`~gettext.pgettext` and its variants.
|
Added :func:`~gettext.pgettext` and its variants.
|
||||||
(Contributed by Franz Glasner, Éric Araujo, and Cheryl Sabella in :issue:`2504`.)
|
(Contributed by Franz Glasner, Éric Araujo, and Cheryl Sabella in :issue:`2504`.)
|
||||||
|
|
||||||
|
|
||||||
|
gc
|
||||||
|
--
|
||||||
|
|
||||||
|
:func:`~gc.get_objects` can now receive an optional *generation* parameter
|
||||||
|
indicating a generation to get objects from. Contributed in
|
||||||
|
:issue:`36016` by Pablo Galindo.
|
||||||
|
|
||||||
|
|
||||||
gzip
|
gzip
|
||||||
----
|
----
|
||||||
|
|
||||||
|
|
|
@ -766,6 +766,38 @@ class GCTests(unittest.TestCase):
|
||||||
gc.unfreeze()
|
gc.unfreeze()
|
||||||
self.assertEqual(gc.get_freeze_count(), 0)
|
self.assertEqual(gc.get_freeze_count(), 0)
|
||||||
|
|
||||||
|
def test_get_objects(self):
|
||||||
|
gc.collect()
|
||||||
|
l = []
|
||||||
|
l.append(l)
|
||||||
|
self.assertIn(l, gc.get_objects(generation=0))
|
||||||
|
self.assertNotIn(l, gc.get_objects(generation=1))
|
||||||
|
self.assertNotIn(l, gc.get_objects(generation=2))
|
||||||
|
gc.collect(generation=0)
|
||||||
|
self.assertNotIn(l, gc.get_objects(generation=0))
|
||||||
|
self.assertIn(l, gc.get_objects(generation=1))
|
||||||
|
self.assertNotIn(l, gc.get_objects(generation=2))
|
||||||
|
gc.collect(generation=1)
|
||||||
|
self.assertNotIn(l, gc.get_objects(generation=0))
|
||||||
|
self.assertNotIn(l, gc.get_objects(generation=1))
|
||||||
|
self.assertIn(l, gc.get_objects(generation=2))
|
||||||
|
gc.collect(generation=2)
|
||||||
|
self.assertNotIn(l, gc.get_objects(generation=0))
|
||||||
|
self.assertNotIn(l, gc.get_objects(generation=1))
|
||||||
|
self.assertIn(l, gc.get_objects(generation=2))
|
||||||
|
del l
|
||||||
|
gc.collect()
|
||||||
|
|
||||||
|
def test_get_objects_arguments(self):
|
||||||
|
gc.collect()
|
||||||
|
self.assertEqual(len(gc.get_objects()),
|
||||||
|
len(gc.get_objects(generation=None)))
|
||||||
|
|
||||||
|
self.assertRaises(ValueError, gc.get_objects, 1000)
|
||||||
|
self.assertRaises(ValueError, gc.get_objects, -1000)
|
||||||
|
self.assertRaises(TypeError, gc.get_objects, "1")
|
||||||
|
self.assertRaises(TypeError, gc.get_objects, 1.234)
|
||||||
|
|
||||||
|
|
||||||
class GCCallbackTests(unittest.TestCase):
|
class GCCallbackTests(unittest.TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
``gc.get_objects`` can now receive an optional parameter indicating a
|
||||||
|
generation to get objects from. Patch by Pablo Galindo.
|
|
@ -216,21 +216,39 @@ gc_get_count(PyObject *module, PyObject *Py_UNUSED(ignored))
|
||||||
}
|
}
|
||||||
|
|
||||||
PyDoc_STRVAR(gc_get_objects__doc__,
|
PyDoc_STRVAR(gc_get_objects__doc__,
|
||||||
"get_objects($module, /)\n"
|
"get_objects($module, /, generation=None)\n"
|
||||||
"--\n"
|
"--\n"
|
||||||
"\n"
|
"\n"
|
||||||
"Return a list of objects tracked by the collector (excluding the list returned).");
|
"Return a list of objects tracked by the collector (excluding the list returned).\n"
|
||||||
|
"\n"
|
||||||
|
" generation\n"
|
||||||
|
" Generation to extract the objects from.\n"
|
||||||
|
"\n"
|
||||||
|
"If generation is not None, return only the objects tracked by the collector\n"
|
||||||
|
"that are in that generation.");
|
||||||
|
|
||||||
#define GC_GET_OBJECTS_METHODDEF \
|
#define GC_GET_OBJECTS_METHODDEF \
|
||||||
{"get_objects", (PyCFunction)gc_get_objects, METH_NOARGS, gc_get_objects__doc__},
|
{"get_objects", (PyCFunction)(void(*)(void))gc_get_objects, METH_FASTCALL|METH_KEYWORDS, gc_get_objects__doc__},
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
gc_get_objects_impl(PyObject *module);
|
gc_get_objects_impl(PyObject *module, Py_ssize_t generation);
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
gc_get_objects(PyObject *module, PyObject *Py_UNUSED(ignored))
|
gc_get_objects(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
|
||||||
{
|
{
|
||||||
return gc_get_objects_impl(module);
|
PyObject *return_value = NULL;
|
||||||
|
static const char * const _keywords[] = {"generation", NULL};
|
||||||
|
static _PyArg_Parser _parser = {"|O&:get_objects", _keywords, 0};
|
||||||
|
Py_ssize_t generation = -1;
|
||||||
|
|
||||||
|
if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser,
|
||||||
|
_Py_convert_optional_to_ssize_t, &generation)) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
return_value = gc_get_objects_impl(module, generation);
|
||||||
|
|
||||||
|
exit:
|
||||||
|
return return_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
PyDoc_STRVAR(gc_get_stats__doc__,
|
PyDoc_STRVAR(gc_get_stats__doc__,
|
||||||
|
@ -331,4 +349,4 @@ gc_get_freeze_count(PyObject *module, PyObject *Py_UNUSED(ignored))
|
||||||
exit:
|
exit:
|
||||||
return return_value;
|
return return_value;
|
||||||
}
|
}
|
||||||
/*[clinic end generated code: output=5aa5fdc259503d5f input=a9049054013a1b77]*/
|
/*[clinic end generated code: output=d692bf475f0bb096 input=a9049054013a1b77]*/
|
||||||
|
|
|
@ -1502,27 +1502,61 @@ gc_get_referents(PyObject *self, PyObject *args)
|
||||||
|
|
||||||
/*[clinic input]
|
/*[clinic input]
|
||||||
gc.get_objects
|
gc.get_objects
|
||||||
|
generation: Py_ssize_t(accept={int, NoneType}, c_default="-1") = None
|
||||||
|
Generation to extract the objects from.
|
||||||
|
|
||||||
Return a list of objects tracked by the collector (excluding the list returned).
|
Return a list of objects tracked by the collector (excluding the list returned).
|
||||||
|
|
||||||
|
If generation is not None, return only the objects tracked by the collector
|
||||||
|
that are in that generation.
|
||||||
[clinic start generated code]*/
|
[clinic start generated code]*/
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
gc_get_objects_impl(PyObject *module)
|
gc_get_objects_impl(PyObject *module, Py_ssize_t generation)
|
||||||
/*[clinic end generated code: output=fcb95d2e23e1f750 input=9439fe8170bf35d8]*/
|
/*[clinic end generated code: output=48b35fea4ba6cb0e input=ef7da9df9806754c]*/
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
PyObject* result;
|
PyObject* result;
|
||||||
|
|
||||||
result = PyList_New(0);
|
result = PyList_New(0);
|
||||||
if (result == NULL)
|
if (result == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If generation is passed, we extract only that generation */
|
||||||
|
if (generation != -1) {
|
||||||
|
if (generation >= NUM_GENERATIONS) {
|
||||||
|
PyErr_Format(PyExc_ValueError,
|
||||||
|
"generation parameter must be less than the number of "
|
||||||
|
"available generations (%i)",
|
||||||
|
NUM_GENERATIONS);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (generation < 0) {
|
||||||
|
PyErr_SetString(PyExc_ValueError,
|
||||||
|
"generation parameter cannot be negative");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (append_objects(result, GEN_HEAD(generation))) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If generation is not passed or None, get all objects from all generations */
|
||||||
for (i = 0; i < NUM_GENERATIONS; i++) {
|
for (i = 0; i < NUM_GENERATIONS; i++) {
|
||||||
if (append_objects(result, GEN_HEAD(i))) {
|
if (append_objects(result, GEN_HEAD(i))) {
|
||||||
Py_DECREF(result);
|
goto error;
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
|
error:
|
||||||
|
Py_DECREF(result);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*[clinic input]
|
/*[clinic input]
|
||||||
|
|
Loading…
Reference in New Issue