From 120bc73de51660d23d06b461878adee875de7f21 Mon Sep 17 00:00:00 2001 From: Peter Bierma Date: Sat, 4 Jan 2025 20:01:18 -0500 Subject: [PATCH 01/17] Add sys._is_immortal --- Lib/test/test_sys.py | 14 ++++++++++++++ Python/clinic/sysmodule.c.h | 30 +++++++++++++++++++++++++++++- Python/sysmodule.c | 16 ++++++++++++++++ 3 files changed, 59 insertions(+), 1 deletion(-) diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py index d839893d2c657e..5f38d5f3e8e663 100644 --- a/Lib/test/test_sys.py +++ b/Lib/test/test_sys.py @@ -713,6 +713,20 @@ def test_43581(self): # the test runs under regrtest. self.assertEqual(sys.__stdout__.encoding, sys.__stderr__.encoding) + @unittest.skipUnless(hasattr(sys, "_is_immortal")) + def test_immortal(self): + # Not extensive + known_immortals = (True, False, None, 0, ()) + for immortal in known_immortals: + with self.subTest(immortal=immortal): + self.assertTrue(sys._is_immortal(immortal)) + + # Some arbitrary mutable objects + non_immortals = (object(), self, [object()]) + for non_immortal in non_immortals: + with self.subTest(non_immortal=non_immortal): + self.assertFalse(sys._is_immortal(non_immortal)) + def test_intern(self): has_is_interned = (test.support.check_impl_detail(cpython=True) or hasattr(sys, '_is_interned')) diff --git a/Python/clinic/sysmodule.c.h b/Python/clinic/sysmodule.c.h index cfcbd55388efa0..31699ce04799de 100644 --- a/Python/clinic/sysmodule.c.h +++ b/Python/clinic/sysmodule.c.h @@ -339,6 +339,34 @@ sys_intern(PyObject *module, PyObject *arg) 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."); + +#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__is_interned__doc__, "_is_interned($module, string, /)\n" "--\n" @@ -1724,4 +1752,4 @@ sys__is_gil_enabled(PyObject *module, PyObject *Py_UNUSED(ignored)) #ifndef SYS_GETANDROIDAPILEVEL_METHODDEF #define SYS_GETANDROIDAPILEVEL_METHODDEF #endif /* !defined(SYS_GETANDROIDAPILEVEL_METHODDEF) */ -/*[clinic end generated code: output=568b0a0069dc43e8 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=5c471bb97c37b214 input=a9049054013a1b77]*/ diff --git a/Python/sysmodule.c b/Python/sysmodule.c index d6719f9bb0af91..7d3c0e27c7aa84 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -955,6 +955,21 @@ sys_intern_impl(PyObject *module, PyObject *s) } } +/*[clinic input] +sys._is_immortal -> bool + + op: object + / + +Return True if the given object is "immortal" per PEP 683. +[clinic start generated code]*/ + +static int +sys__is_immortal_impl(PyObject *module, PyObject *op) +/*[clinic end generated code: output=c2f5d6a80efb8d1a input=83733fc356c78475]*/ +{ + return _Py_IsImmortal(op); +} /*[clinic input] sys._is_interned -> bool @@ -2590,6 +2605,7 @@ static PyMethodDef sys_methods[] = { SYS__GETFRAMEMODULENAME_METHODDEF SYS_GETWINDOWSVERSION_METHODDEF SYS__ENABLELEGACYWINDOWSFSENCODING_METHODDEF + SYS__IS_IMMORTAL_METHODDEF SYS_INTERN_METHODDEF SYS__IS_INTERNED_METHODDEF SYS_IS_FINALIZING_METHODDEF From ac452615437effad4c9c5c81855ea2bd786da5bf Mon Sep 17 00:00:00 2001 From: Peter Bierma Date: Sat, 4 Jan 2025 20:04:03 -0500 Subject: [PATCH 02/17] Add documentation note. --- Doc/library/sys.rst | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/Doc/library/sys.rst b/Doc/library/sys.rst index dd6293c722e7ad..696716b28f8d53 100644 --- a/Doc/library/sys.rst +++ b/Doc/library/sys.rst @@ -1264,6 +1264,17 @@ always available. .. versionadded:: 3.12 +.. function:: _is_immortal(op) + + Return :const:`True` if the given object is :term:`immortal`, :const:`False` + otherwise. + + .. versionadded:: next + + .. impl-detail:: + + It is not guaranteed to exist in all implementations of Python. + .. function:: _is_interned(string) Return :const:`True` if the given string is "interned", :const:`False` From b545f24c58ffd171843002799e29ade3cd30b578 Mon Sep 17 00:00:00 2001 From: Peter Bierma Date: Sat, 4 Jan 2025 20:31:35 -0500 Subject: [PATCH 03/17] Add a note to the docs and fix tests. --- Doc/library/sys.rst | 5 +++++ Lib/test/test_sys.py | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/Doc/library/sys.rst b/Doc/library/sys.rst index 696716b28f8d53..84ad4c71ba28ef 100644 --- a/Doc/library/sys.rst +++ b/Doc/library/sys.rst @@ -1269,6 +1269,11 @@ always available. 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:: diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py index 5f38d5f3e8e663..97116147f7623d 100644 --- a/Lib/test/test_sys.py +++ b/Lib/test/test_sys.py @@ -713,7 +713,7 @@ def test_43581(self): # the test runs under regrtest. self.assertEqual(sys.__stdout__.encoding, sys.__stderr__.encoding) - @unittest.skipUnless(hasattr(sys, "_is_immortal")) + @unittest.skipUnless(hasattr(sys, "_is_immortal"), "immortality is not supported") def test_immortal(self): # Not extensive known_immortals = (True, False, None, 0, ()) From 49b0ea8789cb4f3fd2ad5d577f1e990b945689b2 Mon Sep 17 00:00:00 2001 From: Peter Bierma Date: Sat, 4 Jan 2025 20:40:09 -0500 Subject: [PATCH 04/17] Add some documentation notes. --- Doc/library/sys.rst | 5 +++++ Doc/whatsnew/3.14.rst | 3 +++ 2 files changed, 8 insertions(+) diff --git a/Doc/library/sys.rst b/Doc/library/sys.rst index 84ad4c71ba28ef..637eb7e55562ef 100644 --- a/Doc/library/sys.rst +++ b/Doc/library/sys.rst @@ -855,6 +855,11 @@ always available. 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. + .. impl-detail:: + + :term:`immortal` objects with a large reference count can be identified + with :func:`_is_immortal`. + .. versionchanged:: 3.12 Immortal objects have very large refcounts that do not match the actual number of references to the object. diff --git a/Doc/whatsnew/3.14.rst b/Doc/whatsnew/3.14.rst index 63fa21e17bc834..d56ff87be7cbd1 100644 --- a/Doc/whatsnew/3.14.rst +++ b/Doc/whatsnew/3.14.rst @@ -611,6 +611,9 @@ sys which only exists in specialized builds of Python, may now return objects 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`.) + sys.monitoring -------------- From b31efe5f624475aa6825e2dc6b2ac4a3adaa62d6 Mon Sep 17 00:00:00 2001 From: Peter Bierma Date: Sat, 4 Jan 2025 20:41:35 -0500 Subject: [PATCH 05/17] Add a note in the glossary. --- Doc/glossary.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Doc/glossary.rst b/Doc/glossary.rst index f67f3ecad0bc40..4e3144aef6d3db 100644 --- a/Doc/glossary.rst +++ b/Doc/glossary.rst @@ -658,6 +658,8 @@ Glossary and therefore it is never deallocated while the interpreter is running. For example, :const:`True` and :const:`None` are immortal in CPython. + Immortal objects can be identified via :func:`sys._is_immortal`. + immutable An object with a fixed value. Immutable objects include numbers, strings and tuples. Such an object cannot be altered. A new object has to From 45dc9e09946336c4e49f8e1dbad7e7a5ddd7c17c Mon Sep 17 00:00:00 2001 From: Peter Bierma Date: Sat, 4 Jan 2025 20:50:25 -0500 Subject: [PATCH 06/17] Change up wording. --- Doc/library/sys.rst | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Doc/library/sys.rst b/Doc/library/sys.rst index 637eb7e55562ef..f4a1701c494351 100644 --- a/Doc/library/sys.rst +++ b/Doc/library/sys.rst @@ -857,8 +857,8 @@ always available. .. impl-detail:: - :term:`immortal` objects with a large reference count can be identified - with :func:`_is_immortal`. + :term:`Immortal ` objects with a large reference count can be identified + via :func:`_is_immortal`. .. versionchanged:: 3.12 Immortal objects have very large refcounts that do not match @@ -1283,6 +1283,7 @@ always available. .. 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) From 32d7db015b6d9652b6a0540c91d5aa6a6d0f516b Mon Sep 17 00:00:00 2001 From: Peter Bierma Date: Sat, 4 Jan 2025 20:51:53 -0500 Subject: [PATCH 07/17] Add blur --- .../next/Library/2025-01-04-20-51-48.gh-issue-128509.3gr_-O.rst | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 Misc/NEWS.d/next/Library/2025-01-04-20-51-48.gh-issue-128509.3gr_-O.rst diff --git a/Misc/NEWS.d/next/Library/2025-01-04-20-51-48.gh-issue-128509.3gr_-O.rst b/Misc/NEWS.d/next/Library/2025-01-04-20-51-48.gh-issue-128509.3gr_-O.rst new file mode 100644 index 00000000000000..ba45884304f662 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2025-01-04-20-51-48.gh-issue-128509.3gr_-O.rst @@ -0,0 +1,2 @@ +Add :func:`sys._is_immortal` for identifying :term:`immortal` objects at +runtime. From 638edd0d3e2e955ca16b3d97d31951ec766e74f2 Mon Sep 17 00:00:00 2001 From: Peter Bierma Date: Mon, 27 Jan 2025 10:13:19 -0500 Subject: [PATCH 08/17] Remove redundant test case. --- Lib/test/test_sys.py | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py index 97116147f7623d..d839893d2c657e 100644 --- a/Lib/test/test_sys.py +++ b/Lib/test/test_sys.py @@ -713,20 +713,6 @@ def test_43581(self): # the test runs under regrtest. self.assertEqual(sys.__stdout__.encoding, sys.__stderr__.encoding) - @unittest.skipUnless(hasattr(sys, "_is_immortal"), "immortality is not supported") - def test_immortal(self): - # Not extensive - known_immortals = (True, False, None, 0, ()) - for immortal in known_immortals: - with self.subTest(immortal=immortal): - self.assertTrue(sys._is_immortal(immortal)) - - # Some arbitrary mutable objects - non_immortals = (object(), self, [object()]) - for non_immortal in non_immortals: - with self.subTest(non_immortal=non_immortal): - self.assertFalse(sys._is_immortal(non_immortal)) - def test_intern(self): has_is_interned = (test.support.check_impl_detail(cpython=True) or hasattr(sys, '_is_interned')) From 64c9a5209425a16d7790c428c608924d4634e472 Mon Sep 17 00:00:00 2001 From: Peter Bierma Date: Mon, 27 Jan 2025 10:16:08 -0500 Subject: [PATCH 09/17] Test for sys._is_immortal in the existing case. --- Lib/test/test_capi/test_immortal.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/Lib/test/test_capi/test_immortal.py b/Lib/test/test_capi/test_immortal.py index 660e8a0e789366..656e4a9da44e5e 100644 --- a/Lib/test/test_capi/test_immortal.py +++ b/Lib/test/test_capi/test_immortal.py @@ -1,26 +1,32 @@ import unittest from test.support import import_helper +import sys _testcapi = import_helper.import_module('_testcapi') _testinternalcapi = import_helper.import_module('_testinternalcapi') -class TestUnstableCAPI(unittest.TestCase): - def test_immortal(self): +class TestImmortalAPI(unittest.TestCase): + def immortal_checking(self, func): # Not extensive known_immortals = (True, False, None, 0, ()) for immortal in known_immortals: with self.subTest(immortal=immortal): - self.assertTrue(_testcapi.is_immortal(immortal)) + self.assertTrue(func(immortal)) # Some arbitrary mutable objects non_immortals = (object(), self, [object()]) for non_immortal in non_immortals: with self.subTest(non_immortal=non_immortal): - self.assertFalse(_testcapi.is_immortal(non_immortal)) + self.assertFalse(func(non_immortal)) + def test_unstable_c_api(self): + self.immortal_checking(_testcapi.is_immortal) # CRASHES _testcapi.is_immortal(NULL) + def test_sys(self): + self.immortal_checking(sys._is_immortal) + class TestInternalCAPI(unittest.TestCase): From 7e416e782554d537015c369ba6a6b8bc2d4d5d02 Mon Sep 17 00:00:00 2001 From: Peter Bierma Date: Mon, 27 Jan 2025 10:24:42 -0500 Subject: [PATCH 10/17] Add note about the C API. --- Doc/glossary.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Doc/glossary.rst b/Doc/glossary.rst index d0b7227eb03bbc..d933ca6b467cf3 100644 --- a/Doc/glossary.rst +++ b/Doc/glossary.rst @@ -658,7 +658,8 @@ Glossary and therefore it is never deallocated while the interpreter is running. For example, :const:`True` and :const:`None` are immortal in CPython. - Immortal objects can be identified via :func:`sys._is_immortal`. + Immortal objects can be identified via :func:`sys._is_immortal`, or + via :c:func:`PyUnstable_IsImmortal` in the C API. immutable An object with a fixed value. Immutable objects include numbers, strings and From 10560ef620b3474df9042416f60c4c25e11f3068 Mon Sep 17 00:00:00 2001 From: Peter Bierma Date: Mon, 27 Jan 2025 10:30:31 -0500 Subject: [PATCH 11/17] Revert "Test for sys._is_immortal in the existing case." This reverts commit 64c9a5209425a16d7790c428c608924d4634e472. --- Lib/test/test_capi/test_immortal.py | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/Lib/test/test_capi/test_immortal.py b/Lib/test/test_capi/test_immortal.py index 656e4a9da44e5e..660e8a0e789366 100644 --- a/Lib/test/test_capi/test_immortal.py +++ b/Lib/test/test_capi/test_immortal.py @@ -1,32 +1,26 @@ import unittest from test.support import import_helper -import sys _testcapi = import_helper.import_module('_testcapi') _testinternalcapi = import_helper.import_module('_testinternalcapi') -class TestImmortalAPI(unittest.TestCase): - def immortal_checking(self, func): +class TestUnstableCAPI(unittest.TestCase): + def test_immortal(self): # Not extensive known_immortals = (True, False, None, 0, ()) for immortal in known_immortals: with self.subTest(immortal=immortal): - self.assertTrue(func(immortal)) + self.assertTrue(_testcapi.is_immortal(immortal)) # Some arbitrary mutable objects non_immortals = (object(), self, [object()]) for non_immortal in non_immortals: with self.subTest(non_immortal=non_immortal): - self.assertFalse(func(non_immortal)) + self.assertFalse(_testcapi.is_immortal(non_immortal)) - def test_unstable_c_api(self): - self.immortal_checking(_testcapi.is_immortal) # CRASHES _testcapi.is_immortal(NULL) - def test_sys(self): - self.immortal_checking(sys._is_immortal) - class TestInternalCAPI(unittest.TestCase): From 51daa104aea03d76a109d27c380b33955b3089d2 Mon Sep 17 00:00:00 2001 From: Peter Bierma Date: Mon, 27 Jan 2025 10:31:44 -0500 Subject: [PATCH 12/17] Align to 80 characters. --- Doc/library/sys.rst | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/Doc/library/sys.rst b/Doc/library/sys.rst index e3b39f781f4bb0..58c02389adde97 100644 --- a/Doc/library/sys.rst +++ b/Doc/library/sys.rst @@ -857,8 +857,8 @@ always available. Unless explicitly noted otherwise, all variables are read-only .. impl-detail:: - :term:`Immortal ` objects with a large reference count can be identified - via :func:`_is_immortal`. + :term:`Immortal ` objects with a large reference count can be + identified via :func:`_is_immortal`. .. versionchanged:: 3.12 Immortal objects have very large refcounts that do not match @@ -1276,8 +1276,9 @@ always available. Unless explicitly noted otherwise, all variables are read-only .. 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. + 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 From fdcafec8c3c28ba43244c81e357f7bc62db73be2 Mon Sep 17 00:00:00 2001 From: Peter Bierma Date: Mon, 27 Jan 2025 10:32:50 -0500 Subject: [PATCH 13/17] Move _is_immortal to after _is_interned --- Python/sysmodule.c | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/Python/sysmodule.c b/Python/sysmodule.c index ea02b12952bfba..c0f884cabc2df3 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -956,38 +956,37 @@ sys_intern_impl(PyObject *module, PyObject *s) } /*[clinic input] -sys._is_immortal -> bool +sys._is_interned -> bool - op: object + string: unicode / -Return True if the given object is "immortal" per PEP 683. +Return True if the given string is "interned". [clinic start generated code]*/ static int -sys__is_immortal_impl(PyObject *module, PyObject *op) -/*[clinic end generated code: output=c2f5d6a80efb8d1a input=83733fc356c78475]*/ +sys__is_interned_impl(PyObject *module, PyObject *string) +/*[clinic end generated code: output=c3678267b4e9d7ed input=039843e17883b606]*/ { - return _Py_IsImmortal(op); + return PyUnicode_CHECK_INTERNED(string); } /*[clinic input] -sys._is_interned -> bool +sys._is_immortal -> bool - string: unicode + op: object / -Return True if the given string is "interned". +Return True if the given object is "immortal" per PEP 683. [clinic start generated code]*/ static int -sys__is_interned_impl(PyObject *module, PyObject *string) -/*[clinic end generated code: output=c3678267b4e9d7ed input=039843e17883b606]*/ +sys__is_immortal_impl(PyObject *module, PyObject *op) +/*[clinic end generated code: output=c2f5d6a80efb8d1a input=83733fc356c78475]*/ { - return PyUnicode_CHECK_INTERNED(string); + return _Py_IsImmortal(op); } - /* * Cached interned string objects used for calling the profile and * trace functions. From 380bca79d4fbd508d214ca616233444839e6202a Mon Sep 17 00:00:00 2001 From: Peter Bierma Date: Mon, 27 Jan 2025 12:20:53 -0500 Subject: [PATCH 14/17] Switch to the unstable API --- Python/sysmodule.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Python/sysmodule.c b/Python/sysmodule.c index c0f884cabc2df3..2e6ff23dc09c9b 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -984,7 +984,7 @@ static int sys__is_immortal_impl(PyObject *module, PyObject *op) /*[clinic end generated code: output=c2f5d6a80efb8d1a input=83733fc356c78475]*/ { - return _Py_IsImmortal(op); + return PyUnstable_IsImmortal(op); } /* From 74a751af345b4fcd1ad80f4e0ce4f821f1bc1c37 Mon Sep 17 00:00:00 2001 From: Peter Bierma Date: Mon, 27 Jan 2025 12:37:00 -0500 Subject: [PATCH 15/17] Fix stray newline change --- Python/sysmodule.c | 1 + 1 file changed, 1 insertion(+) diff --git a/Python/sysmodule.c b/Python/sysmodule.c index 2e6ff23dc09c9b..83641b438fa2b9 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -955,6 +955,7 @@ sys_intern_impl(PyObject *module, PyObject *s) } } + /*[clinic input] sys._is_interned -> bool From be49c268a1f0994253293b3970efed596ec37d3e Mon Sep 17 00:00:00 2001 From: Peter Bierma Date: Tue, 28 Jan 2025 09:27:43 -0500 Subject: [PATCH 16/17] Update sysmodule.c Co-authored-by: Kumar Aditya --- Python/sysmodule.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Python/sysmodule.c b/Python/sysmodule.c index 83641b438fa2b9..f0cffb9fee270e 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -979,6 +979,8 @@ sys._is_immortal -> bool / 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 From 1154cfe0f5d0289aad36b6bc07b52f27b739d32a Mon Sep 17 00:00:00 2001 From: Peter Bierma Date: Tue, 28 Jan 2025 10:33:34 -0500 Subject: [PATCH 17/17] Rerun clinic. --- Python/clinic/sysmodule.c.h | 48 +++++++++++++++++++------------------ Python/sysmodule.c | 2 +- 2 files changed, 26 insertions(+), 24 deletions(-) diff --git a/Python/clinic/sysmodule.c.h b/Python/clinic/sysmodule.c.h index 31699ce04799de..1e53624d4d45d7 100644 --- a/Python/clinic/sysmodule.c.h +++ b/Python/clinic/sysmodule.c.h @@ -339,25 +339,31 @@ sys_intern(PyObject *module, PyObject *arg) return return_value; } -PyDoc_STRVAR(sys__is_immortal__doc__, -"_is_immortal($module, op, /)\n" +PyDoc_STRVAR(sys__is_interned__doc__, +"_is_interned($module, string, /)\n" "--\n" "\n" -"Return True if the given object is \"immortal\" per PEP 683."); +"Return True if the given string is \"interned\"."); -#define SYS__IS_IMMORTAL_METHODDEF \ - {"_is_immortal", (PyCFunction)sys__is_immortal, METH_O, sys__is_immortal__doc__}, +#define SYS__IS_INTERNED_METHODDEF \ + {"_is_interned", (PyCFunction)sys__is_interned, METH_O, sys__is_interned__doc__}, static int -sys__is_immortal_impl(PyObject *module, PyObject *op); +sys__is_interned_impl(PyObject *module, PyObject *string); static PyObject * -sys__is_immortal(PyObject *module, PyObject *op) +sys__is_interned(PyObject *module, PyObject *arg) { PyObject *return_value = NULL; + PyObject *string; int _return_value; - _return_value = sys__is_immortal_impl(module, op); + if (!PyUnicode_Check(arg)) { + _PyArg_BadArgument("_is_interned", "argument", "str", arg); + goto exit; + } + string = arg; + _return_value = sys__is_interned_impl(module, string); if ((_return_value == -1) && PyErr_Occurred()) { goto exit; } @@ -367,31 +373,27 @@ sys__is_immortal(PyObject *module, PyObject *op) return return_value; } -PyDoc_STRVAR(sys__is_interned__doc__, -"_is_interned($module, string, /)\n" +PyDoc_STRVAR(sys__is_immortal__doc__, +"_is_immortal($module, op, /)\n" "--\n" "\n" -"Return True if the given string is \"interned\"."); +"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_INTERNED_METHODDEF \ - {"_is_interned", (PyCFunction)sys__is_interned, METH_O, sys__is_interned__doc__}, +#define SYS__IS_IMMORTAL_METHODDEF \ + {"_is_immortal", (PyCFunction)sys__is_immortal, METH_O, sys__is_immortal__doc__}, static int -sys__is_interned_impl(PyObject *module, PyObject *string); +sys__is_immortal_impl(PyObject *module, PyObject *op); static PyObject * -sys__is_interned(PyObject *module, PyObject *arg) +sys__is_immortal(PyObject *module, PyObject *op) { PyObject *return_value = NULL; - PyObject *string; int _return_value; - if (!PyUnicode_Check(arg)) { - _PyArg_BadArgument("_is_interned", "argument", "str", arg); - goto exit; - } - string = arg; - _return_value = sys__is_interned_impl(module, string); + _return_value = sys__is_immortal_impl(module, op); if ((_return_value == -1) && PyErr_Occurred()) { goto exit; } @@ -1752,4 +1754,4 @@ sys__is_gil_enabled(PyObject *module, PyObject *Py_UNUSED(ignored)) #ifndef SYS_GETANDROIDAPILEVEL_METHODDEF #define SYS_GETANDROIDAPILEVEL_METHODDEF #endif /* !defined(SYS_GETANDROIDAPILEVEL_METHODDEF) */ -/*[clinic end generated code: output=5c471bb97c37b214 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=1e5f608092c12636 input=a9049054013a1b77]*/ diff --git a/Python/sysmodule.c b/Python/sysmodule.c index f0cffb9fee270e..670d7b9d506f43 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -985,7 +985,7 @@ This function should be used for specialized purposes only. static int sys__is_immortal_impl(PyObject *module, PyObject *op) -/*[clinic end generated code: output=c2f5d6a80efb8d1a input=83733fc356c78475]*/ +/*[clinic end generated code: output=c2f5d6a80efb8d1a input=4609c9bf5481db76]*/ { return PyUnstable_IsImmortal(op); }