gh-128509: Add sys._is_immortal for identifying immortal objects (#128510)

Co-authored-by: Kumar Aditya <kumaraditya@python.org>
This commit is contained in:
Peter Bierma 2025-01-31 10:27:08 -05:00 committed by GitHub
parent 60a85415ae
commit 9ba281d871
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 81 additions and 1 deletions

View file

@ -658,6 +658,9 @@ Glossary
and therefore it is never deallocated while the interpreter is running. and therefore it is never deallocated while the interpreter is running.
For example, :const:`True` and :const:`None` are immortal in CPython. For example, :const:`True` and :const:`None` are immortal in CPython.
Immortal objects can be identified via :func:`sys._is_immortal`, or
via :c:func:`PyUnstable_IsImmortal` in the C API.
immutable immutable
An object with a fixed value. Immutable objects include numbers, strings and An object with a fixed value. Immutable objects include numbers, strings and
tuples. Such an object cannot be altered. A new object has to tuples. Such an object cannot be altered. A new object has to

View file

@ -855,6 +855,11 @@ always available. Unless explicitly noted otherwise, all variables are read-only
reflect the actual number of references. Consequently, do not rely reflect the actual number of references. Consequently, do not rely
on the returned value to be accurate, other than a value of 0 or 1. on the returned value to be accurate, other than a value of 0 or 1.
.. impl-detail::
:term:`Immortal <immortal>` objects with a large reference count can be
identified via :func:`_is_immortal`.
.. versionchanged:: 3.12 .. versionchanged:: 3.12
Immortal objects have very large refcounts that do not match Immortal objects have very large refcounts that do not match
the actual number of references to the object. the actual number of references to the object.
@ -1264,6 +1269,24 @@ always available. Unless explicitly noted otherwise, all variables are read-only
.. versionadded:: 3.12 .. versionadded:: 3.12
.. function:: _is_immortal(op)
Return :const:`True` if the given object is :term:`immortal`, :const:`False`
otherwise.
.. note::
Objects that are immortal (and thus return ``True`` upon being passed
to this function) are not guaranteed to be immortal in future versions,
and vice versa for mortal objects.
.. versionadded:: next
.. impl-detail::
This function should be used for specialized purposes only.
It is not guaranteed to exist in all implementations of Python.
.. function:: _is_interned(string) .. function:: _is_interned(string)
Return :const:`True` if the given string is "interned", :const:`False` Return :const:`True` if the given string is "interned", :const:`False`

View file

@ -649,9 +649,13 @@ sys
which only exists in specialized builds of Python, may now return objects which only exists in specialized builds of Python, may now return objects
from other interpreters than the one it's called in. from other interpreters than the one it's called in.
* Add :func:`sys._is_immortal` for determining if an object is :term:`immortal`.
(Contributed by Peter Bierma in :gh:`128509`.)
* On FreeBSD, :data:`sys.platform` doesn't contain the major version anymore. * On FreeBSD, :data:`sys.platform` doesn't contain the major version anymore.
It is always ``'freebsd'``, instead of ``'freebsd13'`` or ``'freebsd14'``. It is always ``'freebsd'``, instead of ``'freebsd13'`` or ``'freebsd14'``.
sys.monitoring sys.monitoring
-------------- --------------

View file

@ -0,0 +1,2 @@
Add :func:`sys._is_immortal` for identifying :term:`immortal` objects at
runtime.

View file

@ -373,6 +373,36 @@ exit:
return return_value; return return_value;
} }
PyDoc_STRVAR(sys__is_immortal__doc__,
"_is_immortal($module, op, /)\n"
"--\n"
"\n"
"Return True if the given object is \"immortal\" per PEP 683.\n"
"\n"
"This function should be used for specialized purposes only.");
#define SYS__IS_IMMORTAL_METHODDEF \
{"_is_immortal", (PyCFunction)sys__is_immortal, METH_O, sys__is_immortal__doc__},
static int
sys__is_immortal_impl(PyObject *module, PyObject *op);
static PyObject *
sys__is_immortal(PyObject *module, PyObject *op)
{
PyObject *return_value = NULL;
int _return_value;
_return_value = sys__is_immortal_impl(module, op);
if ((_return_value == -1) && PyErr_Occurred()) {
goto exit;
}
return_value = PyBool_FromLong((long)_return_value);
exit:
return return_value;
}
PyDoc_STRVAR(sys_settrace__doc__, PyDoc_STRVAR(sys_settrace__doc__,
"settrace($module, function, /)\n" "settrace($module, function, /)\n"
"--\n" "--\n"
@ -1724,4 +1754,4 @@ exit:
#ifndef SYS_GETANDROIDAPILEVEL_METHODDEF #ifndef SYS_GETANDROIDAPILEVEL_METHODDEF
#define SYS_GETANDROIDAPILEVEL_METHODDEF #define SYS_GETANDROIDAPILEVEL_METHODDEF
#endif /* !defined(SYS_GETANDROIDAPILEVEL_METHODDEF) */ #endif /* !defined(SYS_GETANDROIDAPILEVEL_METHODDEF) */
/*[clinic end generated code: output=568b0a0069dc43e8 input=a9049054013a1b77]*/ /*[clinic end generated code: output=1e5f608092c12636 input=a9049054013a1b77]*/

View file

@ -972,6 +972,23 @@ sys__is_interned_impl(PyObject *module, PyObject *string)
return PyUnicode_CHECK_INTERNED(string); return PyUnicode_CHECK_INTERNED(string);
} }
/*[clinic input]
sys._is_immortal -> bool
op: object
/
Return True if the given object is "immortal" per PEP 683.
This function should be used for specialized purposes only.
[clinic start generated code]*/
static int
sys__is_immortal_impl(PyObject *module, PyObject *op)
/*[clinic end generated code: output=c2f5d6a80efb8d1a input=4609c9bf5481db76]*/
{
return PyUnstable_IsImmortal(op);
}
/* /*
* Cached interned string objects used for calling the profile and * Cached interned string objects used for calling the profile and
@ -2588,6 +2605,7 @@ static PyMethodDef sys_methods[] = {
SYS__GETFRAMEMODULENAME_METHODDEF SYS__GETFRAMEMODULENAME_METHODDEF
SYS_GETWINDOWSVERSION_METHODDEF SYS_GETWINDOWSVERSION_METHODDEF
SYS__ENABLELEGACYWINDOWSFSENCODING_METHODDEF SYS__ENABLELEGACYWINDOWSFSENCODING_METHODDEF
SYS__IS_IMMORTAL_METHODDEF
SYS_INTERN_METHODDEF SYS_INTERN_METHODDEF
SYS__IS_INTERNED_METHODDEF SYS__IS_INTERNED_METHODDEF
SYS_IS_FINALIZING_METHODDEF SYS_IS_FINALIZING_METHODDEF