summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Doc/library/gc.rst21
-rw-r--r--Doc/whatsnew/3.9.rst4
-rw-r--r--Lib/test/test_gc.py18
-rw-r--r--Misc/NEWS.d/next/Core and Builtins/2020-01-13-15-18-13.bpo-39322.aAs-1T.rst2
-rw-r--r--Modules/clinic/gcmodule.c.h11
-rw-r--r--Modules/gcmodule.c20
6 files changed, 75 insertions, 1 deletions
diff --git a/Doc/library/gc.rst b/Doc/library/gc.rst
index 13eda91..0c33c86 100644
--- a/Doc/library/gc.rst
+++ b/Doc/library/gc.rst
@@ -177,6 +177,27 @@ The :mod:`gc` module provides the following functions:
.. versionadded:: 3.1
+.. function:: is_finalized(obj)
+
+ Returns ``True`` if the given object has been finalized by the
+ garbage collector, ``False`` otherwise. ::
+
+ >>> x = None
+ >>> class Lazarus:
+ ... def __del__(self):
+ ... global x
+ ... x = self
+ ...
+ >>> lazarus = Lazarus()
+ >>> gc.is_finalized(lazarus)
+ False
+ >>> del lazarus
+ >>> gc.is_finalized(x)
+ True
+
+ .. versionadded:: 3.9
+
+
.. function:: freeze()
Freeze all the objects tracked by gc - move them to a permanent generation
diff --git a/Doc/whatsnew/3.9.rst b/Doc/whatsnew/3.9.rst
index 00409af..c949999 100644
--- a/Doc/whatsnew/3.9.rst
+++ b/Doc/whatsnew/3.9.rst
@@ -174,6 +174,10 @@ When the garbage collector makes a collection in which some objects resurrect
been executed), do not block the collection of all objects that are still
unreachable. (Contributed by Pablo Galindo and Tim Peters in :issue:`38379`.)
+Added a new function :func:`gc.is_finalized` to check if an object has been
+finalized by the garbage collector. (Contributed by Pablo Galindo in
+:issue:`39322`.)
+
imaplib
-------
diff --git a/Lib/test/test_gc.py b/Lib/test/test_gc.py
index c0d4a75..18f8d10 100644
--- a/Lib/test/test_gc.py
+++ b/Lib/test/test_gc.py
@@ -586,6 +586,24 @@ class GCTests(unittest.TestCase):
self.assertFalse(gc.is_tracked(UserFloatSlots()))
self.assertFalse(gc.is_tracked(UserIntSlots()))
+ def test_is_finalized(self):
+ # Objects not tracked by the always gc return false
+ self.assertFalse(gc.is_finalized(3))
+
+ storage = []
+ class Lazarus:
+ def __del__(self):
+ storage.append(self)
+
+ lazarus = Lazarus()
+ self.assertFalse(gc.is_finalized(lazarus))
+
+ del lazarus
+ gc.collect()
+
+ lazarus = storage.pop()
+ self.assertTrue(gc.is_finalized(lazarus))
+
def test_bug1055820b(self):
# Corresponds to temp2b.py in the bug report.
diff --git a/Misc/NEWS.d/next/Core and Builtins/2020-01-13-15-18-13.bpo-39322.aAs-1T.rst b/Misc/NEWS.d/next/Core and Builtins/2020-01-13-15-18-13.bpo-39322.aAs-1T.rst
new file mode 100644
index 0000000..60df44c
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2020-01-13-15-18-13.bpo-39322.aAs-1T.rst
@@ -0,0 +1,2 @@
+Added a new function :func:`gc.is_finalized` to check if an object has been
+finalized by the garbage collector. Patch by Pablo Galindo.
diff --git a/Modules/clinic/gcmodule.c.h b/Modules/clinic/gcmodule.c.h
index 22d2aa4..72795c6 100644
--- a/Modules/clinic/gcmodule.c.h
+++ b/Modules/clinic/gcmodule.c.h
@@ -304,6 +304,15 @@ PyDoc_STRVAR(gc_is_tracked__doc__,
#define GC_IS_TRACKED_METHODDEF \
{"is_tracked", (PyCFunction)gc_is_tracked, METH_O, gc_is_tracked__doc__},
+PyDoc_STRVAR(gc_is_finalized__doc__,
+"is_finalized($module, obj, /)\n"
+"--\n"
+"\n"
+"Returns true if the object has been already finalized by the GC.");
+
+#define GC_IS_FINALIZED_METHODDEF \
+ {"is_finalized", (PyCFunction)gc_is_finalized, METH_O, gc_is_finalized__doc__},
+
PyDoc_STRVAR(gc_freeze__doc__,
"freeze($module, /)\n"
"--\n"
@@ -373,4 +382,4 @@ gc_get_freeze_count(PyObject *module, PyObject *Py_UNUSED(ignored))
exit:
return return_value;
}
-/*[clinic end generated code: output=e40d384b1f0d513c input=a9049054013a1b77]*/
+/*[clinic end generated code: output=bd6a8056989e2e69 input=a9049054013a1b77]*/
diff --git a/Modules/gcmodule.c b/Modules/gcmodule.c
index 5fef114..4ad9d22 100644
--- a/Modules/gcmodule.c
+++ b/Modules/gcmodule.c
@@ -1870,6 +1870,25 @@ gc_is_tracked(PyObject *module, PyObject *obj)
}
/*[clinic input]
+gc.is_finalized
+
+ obj: object
+ /
+
+Returns true if the object has been already finalized by the GC.
+[clinic start generated code]*/
+
+static PyObject *
+gc_is_finalized(PyObject *module, PyObject *obj)
+/*[clinic end generated code: output=e1516ac119a918ed input=201d0c58f69ae390]*/
+{
+ if (PyObject_IS_GC(obj) && _PyGCHead_FINALIZED(AS_GC(obj))) {
+ Py_RETURN_TRUE;
+ }
+ Py_RETURN_FALSE;
+}
+
+/*[clinic input]
gc.freeze
Freeze all current tracked objects and ignore them for future collections.
@@ -1961,6 +1980,7 @@ static PyMethodDef GcMethods[] = {
GC_GET_OBJECTS_METHODDEF
GC_GET_STATS_METHODDEF
GC_IS_TRACKED_METHODDEF
+ GC_IS_FINALIZED_METHODDEF
{"get_referrers", gc_get_referrers, METH_VARARGS,
gc_get_referrers__doc__},
{"get_referents", gc_get_referents, METH_VARARGS,