From 2cc543c352322e870bbf74a6de20456dc1f7541a Mon Sep 17 00:00:00 2001 From: Donghee Na Date: Tue, 3 Jun 2025 21:17:29 +0900 Subject: [PATCH 01/13] gh-134819: Add sys.set_object_tags and sys.get_object_tags --- Lib/test/test_sys.py | 24 ++++++++------- Python/clinic/sysmodule.c.h | 11 ++++++- Python/sysmodule.c | 60 +++++++++++++++++++++++++++++++++++++ 3 files changed, 83 insertions(+), 12 deletions(-) diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py index 83745f3d0ba46e..8360b98ece8e5d 100644 --- a/Lib/test/test_sys.py +++ b/Lib/test/test_sys.py @@ -753,23 +753,25 @@ def test_43581(self): self.assertEqual(sys.__stdout__.encoding, sys.__stderr__.encoding) def test_intern(self): - has_is_interned = (test.support.check_impl_detail(cpython=True) - or hasattr(sys, '_is_interned')) self.assertRaises(TypeError, sys.intern) self.assertRaises(TypeError, sys.intern, b'abc') + has_is_interned = (test.support.check_impl_detail(cpython=True) + or hasattr(sys, '_is_interned')) if has_is_interned: self.assertRaises(TypeError, sys._is_interned) self.assertRaises(TypeError, sys._is_interned, b'abc') + + def _is_interned(obj): + tags = sys.get_object_tags(obj) + return tags.get("interned", False) + s = "never interned before" + str(random.randrange(0, 10**9)) self.assertTrue(sys.intern(s) is s) - if has_is_interned: - self.assertIs(sys._is_interned(s), True) + self.assertIs(_is_interned(s), True) s2 = s.swapcase().swapcase() - if has_is_interned: - self.assertIs(sys._is_interned(s2), False) + self.assertIs(_is_interned(s2), False) self.assertTrue(sys.intern(s2) is s) - if has_is_interned: - self.assertIs(sys._is_interned(s2), False) + self.assertIs(_is_interned(s2), False) # Subclasses of string can't be interned, because they # provide too much opportunity for insane things to happen. @@ -781,8 +783,7 @@ def __hash__(self): return 123 self.assertRaises(TypeError, sys.intern, S("abc")) - if has_is_interned: - self.assertIs(sys._is_interned(S("abc")), False) + self.assertIs(_is_interned(S("abc")), False) @support.cpython_only @requires_subinterpreters @@ -847,7 +848,8 @@ def test_subinterp_intern_singleton(self): assert id(s) == {id(s)} t = sys.intern(s) ''')) - self.assertTrue(sys._is_interned(s)) + tags = sys.get_object_tags(s) + self.assertTrue(tags.get("interned", False)) def test_sys_flags(self): self.assertTrue(sys.flags) diff --git a/Python/clinic/sysmodule.c.h b/Python/clinic/sysmodule.c.h index a47e4d11b54441..1604554d6c94d0 100644 --- a/Python/clinic/sysmodule.c.h +++ b/Python/clinic/sysmodule.c.h @@ -405,6 +405,15 @@ sys__is_immortal(PyObject *module, PyObject *op) return return_value; } +PyDoc_STRVAR(sys_get_object_tags__doc__, +"get_object_tags($module, op, /)\n" +"--\n" +"\n" +"Return the tags of the given object."); + +#define SYS_GET_OBJECT_TAGS_METHODDEF \ + {"get_object_tags", (PyCFunction)sys_get_object_tags, METH_O, sys_get_object_tags__doc__}, + PyDoc_STRVAR(sys_settrace__doc__, "settrace($module, function, /)\n" "--\n" @@ -1948,4 +1957,4 @@ _jit_is_active(PyObject *module, PyObject *Py_UNUSED(ignored)) #ifndef SYS_GETANDROIDAPILEVEL_METHODDEF #define SYS_GETANDROIDAPILEVEL_METHODDEF #endif /* !defined(SYS_GETANDROIDAPILEVEL_METHODDEF) */ -/*[clinic end generated code: output=449d16326e69dcf6 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=9654d356bd94f235 input=a9049054013a1b77]*/ diff --git a/Python/sysmodule.c b/Python/sysmodule.c index e5ae841d195d4f..669ef9af359c96 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -1052,6 +1052,65 @@ sys__is_immortal_impl(PyObject *module, PyObject *op) return PyUnstable_IsImmortal(op); } + +/*[clinic input] +sys.get_object_tags -> object + + op: object + / +Return the tags of the given object. +[clinic start generated code]*/ + +static PyObject * +sys_get_object_tags(PyObject *module, PyObject *op) +/*[clinic end generated code: output=a68da7f1805c9216 input=75993fb67096e2ff]*/ +{ + assert(op != NULL); + PyObject *dict = PyDict_New(); + if (dict == NULL) { + return NULL; + } + if (PyUnstable_IsImmortal(op)) { + if (PyDict_SetItemString(dict, "immortal", Py_True) < 0) { + Py_DECREF(dict); + return NULL; + } + } + else { + if (PyDict_SetItemString(dict, "immortal", Py_False) < 0) { + Py_DECREF(dict); + return NULL; + } + } + + if (PyUnicode_CHECK_INTERNED(op)) { + if (PyDict_SetItemString(dict, "interned", Py_True) < 0) { + Py_DECREF(dict); + return NULL; + } + } + else { + if (PyDict_SetItemString(dict, "interned", Py_False) < 0) { + Py_DECREF(dict); + return NULL; + } + } + + if (PyUnstable_Object_EnableDeferredRefcount(op)) { + if (PyDict_SetItemString(dict, "deferred_refcount", Py_True) < 0) { + Py_DECREF(dict); + return NULL; + } + } + else { + if (PyDict_SetItemString(dict, "deferred_refcount", Py_False) < 0) { + Py_DECREF(dict); + return NULL; + } + } + return dict; +} + /* * Cached interned string objects used for calling the profile and * trace functions. @@ -2796,6 +2855,7 @@ static PyMethodDef sys_methods[] = { SYS__IS_IMMORTAL_METHODDEF SYS_INTERN_METHODDEF SYS__IS_INTERNED_METHODDEF + SYS_GET_OBJECT_TAGS_METHODDEF SYS_IS_FINALIZING_METHODDEF SYS_MDEBUG_METHODDEF SYS_SETSWITCHINTERVAL_METHODDEF From 17ccccfd1f474622b2563bff7e1edd3a362148e3 Mon Sep 17 00:00:00 2001 From: Donghee Na Date: Tue, 3 Jun 2025 21:21:42 +0900 Subject: [PATCH 02/13] Add test --- Lib/test/test_sys.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py index 8360b98ece8e5d..6c4a26e43c31e6 100644 --- a/Lib/test/test_sys.py +++ b/Lib/test/test_sys.py @@ -785,6 +785,15 @@ def __hash__(self): self.assertRaises(TypeError, sys.intern, S("abc")) self.assertIs(_is_interned(S("abc")), False) + @support.cpython_only + def test_get_object_tags(self): + keys = ("immortal", "interned", "deferred_refcount") + s = "foobar" + tags = sys.get_object_tags(s) + self.assertEqual(len(tags), len(keys)) + for k in keys: + self.assertIn(k, tags) + @support.cpython_only @requires_subinterpreters def test_subinterp_intern_dynamically_allocated(self): From fb997ab1ce4653dd0a927ec3946b69cae1040fdd Mon Sep 17 00:00:00 2001 From: Donghee Na Date: Tue, 3 Jun 2025 21:51:50 +0900 Subject: [PATCH 03/13] Add set_object_tag --- Lib/test/test_sys.py | 14 +++++++ Python/clinic/sysmodule.c.h | 82 ++++++++++++++++++++++++++++++++++++- Python/sysmodule.c | 29 ++++++++++++- 3 files changed, 123 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py index 6c4a26e43c31e6..b0f997521f9a38 100644 --- a/Lib/test/test_sys.py +++ b/Lib/test/test_sys.py @@ -794,6 +794,20 @@ def test_get_object_tags(self): for k in keys: self.assertIn(k, tags) + @support.cpython_only + def test_set_object_tags(self): + keys = ("immortal", "interned") + s = "should never interned before" + str(random.randrange(0, 10**9)) + origin_tags = sys.get_object_tags(s) + for k in keys: + sys.set_object_tag(s, k) + sys.set_object_tag(s, "unknown") + after_tags = sys.get_object_tags(s) + self.assertEqual(len(origin_tags), len(after_tags)) + for k in keys: + self.assertIn(k, after_tags) + self.assertTrue(after_tags[k]) + @support.cpython_only @requires_subinterpreters def test_subinterp_intern_dynamically_allocated(self): diff --git a/Python/clinic/sysmodule.c.h b/Python/clinic/sysmodule.c.h index 1604554d6c94d0..c184e6be34caad 100644 --- a/Python/clinic/sysmodule.c.h +++ b/Python/clinic/sysmodule.c.h @@ -414,6 +414,86 @@ PyDoc_STRVAR(sys_get_object_tags__doc__, #define SYS_GET_OBJECT_TAGS_METHODDEF \ {"get_object_tags", (PyCFunction)sys_get_object_tags, METH_O, sys_get_object_tags__doc__}, +PyDoc_STRVAR(sys_set_object_tag__doc__, +"set_object_tag($module, /, object, tag, *, options=None)\n" +"--\n" +"\n" +"Set the tags of the given object."); + +#define SYS_SET_OBJECT_TAG_METHODDEF \ + {"set_object_tag", _PyCFunction_CAST(sys_set_object_tag), METH_FASTCALL|METH_KEYWORDS, sys_set_object_tag__doc__}, + +static PyObject * +sys_set_object_tag_impl(PyObject *module, PyObject *object, const char *tag, + PyObject *options); + +static PyObject * +sys_set_object_tag(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 3 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + Py_hash_t ob_hash; + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_hash = -1, + .ob_item = { &_Py_ID(object), &_Py_ID(tag), &_Py_ID(options), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"object", "tag", "options", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "set_object_tag", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[3]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; + PyObject *object; + const char *tag; + PyObject *options = Py_None; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, + /*minpos*/ 2, /*maxpos*/ 2, /*minkw*/ 0, /*varpos*/ 0, argsbuf); + if (!args) { + goto exit; + } + object = args[0]; + if (!PyUnicode_Check(args[1])) { + _PyArg_BadArgument("set_object_tag", "argument 'tag'", "str", args[1]); + goto exit; + } + Py_ssize_t tag_length; + tag = PyUnicode_AsUTF8AndSize(args[1], &tag_length); + if (tag == NULL) { + goto exit; + } + if (strlen(tag) != (size_t)tag_length) { + PyErr_SetString(PyExc_ValueError, "embedded null character"); + goto exit; + } + if (!noptargs) { + goto skip_optional_kwonly; + } + options = args[2]; +skip_optional_kwonly: + return_value = sys_set_object_tag_impl(module, object, tag, options); + +exit: + return return_value; +} + PyDoc_STRVAR(sys_settrace__doc__, "settrace($module, function, /)\n" "--\n" @@ -1957,4 +2037,4 @@ _jit_is_active(PyObject *module, PyObject *Py_UNUSED(ignored)) #ifndef SYS_GETANDROIDAPILEVEL_METHODDEF #define SYS_GETANDROIDAPILEVEL_METHODDEF #endif /* !defined(SYS_GETANDROIDAPILEVEL_METHODDEF) */ -/*[clinic end generated code: output=9654d356bd94f235 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=cf56a851495bb951 input=a9049054013a1b77]*/ diff --git a/Python/sysmodule.c b/Python/sysmodule.c index 669ef9af359c96..e2be8c49c83659 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -1083,7 +1083,7 @@ sys_get_object_tags(PyObject *module, PyObject *op) } } - if (PyUnicode_CHECK_INTERNED(op)) { + if (PyUnicode_Check(op) && PyUnicode_CHECK_INTERNED(op)) { if (PyDict_SetItemString(dict, "interned", Py_True) < 0) { Py_DECREF(dict); return NULL; @@ -1111,6 +1111,32 @@ sys_get_object_tags(PyObject *module, PyObject *op) return dict; } +/*[clinic input] +sys.set_object_tag -> object + + object: object + tag: str + * + options: object = None + +Set the tags of the given object. +[clinic start generated code]*/ + +static PyObject * +sys_set_object_tag_impl(PyObject *module, PyObject *object, const char *tag, + PyObject *options) +/*[clinic end generated code: output=b0fb5e9931feb4aa input=b64c9bd958c75f11]*/ +{ + assert(object != NULL); + if (strcmp(tag, "immortal") == 0) { + _Py_SetImmortal(object); + } + else if (strcmp(tag, "interned") == 0) { + _PyUnicode_InternMortal(_PyInterpreterState_GET(), &object); + } + Py_RETURN_NONE; +} + /* * Cached interned string objects used for calling the profile and * trace functions. @@ -2856,6 +2882,7 @@ static PyMethodDef sys_methods[] = { SYS_INTERN_METHODDEF SYS__IS_INTERNED_METHODDEF SYS_GET_OBJECT_TAGS_METHODDEF + SYS_SET_OBJECT_TAG_METHODDEF SYS_IS_FINALIZING_METHODDEF SYS_MDEBUG_METHODDEF SYS_SETSWITCHINTERVAL_METHODDEF From 5027d35300b72ae08725bdff89eed5394c1fa828 Mon Sep 17 00:00:00 2001 From: Donghee Na Date: Tue, 3 Jun 2025 21:55:06 +0900 Subject: [PATCH 04/13] Add NEWS.d --- .../2025-06-03-21-55-03.gh-issue-134819.M9PZZc.rst | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2025-06-03-21-55-03.gh-issue-134819.M9PZZc.rst diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-06-03-21-55-03.gh-issue-134819.M9PZZc.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-06-03-21-55-03.gh-issue-134819.M9PZZc.rst new file mode 100644 index 00000000000000..89b2531a5110df --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2025-06-03-21-55-03.gh-issue-134819.M9PZZc.rst @@ -0,0 +1,2 @@ +Add :func:`sys.get_object_tags` and :func:`sys.set_object_tags` for handling +CPython object implementation detail. Patch By Donghee Na. From ba2c974b0e34cc5896d16f387fb2794c93f77cb4 Mon Sep 17 00:00:00 2001 From: Donghee Na Date: Tue, 3 Jun 2025 21:56:23 +0900 Subject: [PATCH 05/13] nit --- Lib/test/test_sys.py | 1 + 1 file changed, 1 insertion(+) diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py index b0f997521f9a38..bb8eec53f127f3 100644 --- a/Lib/test/test_sys.py +++ b/Lib/test/test_sys.py @@ -800,6 +800,7 @@ def test_set_object_tags(self): s = "should never interned before" + str(random.randrange(0, 10**9)) origin_tags = sys.get_object_tags(s) for k in keys: + self.assertFalse(origin_tags[k]) sys.set_object_tag(s, k) sys.set_object_tag(s, "unknown") after_tags = sys.get_object_tags(s) From 658e7317e7b4a6dff9f989aea48d6b5a695589fd Mon Sep 17 00:00:00 2001 From: Donghee Na Date: Tue, 3 Jun 2025 21:59:56 +0900 Subject: [PATCH 06/13] nit --- Lib/test/test_sys.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py index bb8eec53f127f3..6cb28514ed5b99 100644 --- a/Lib/test/test_sys.py +++ b/Lib/test/test_sys.py @@ -763,7 +763,7 @@ def test_intern(self): def _is_interned(obj): tags = sys.get_object_tags(obj) - return tags.get("interned", False) + return tags["interned"] s = "never interned before" + str(random.randrange(0, 10**9)) self.assertTrue(sys.intern(s) is s) @@ -873,7 +873,7 @@ def test_subinterp_intern_singleton(self): t = sys.intern(s) ''')) tags = sys.get_object_tags(s) - self.assertTrue(tags.get("interned", False)) + self.assertTrue(tags["interned"]) def test_sys_flags(self): self.assertTrue(sys.flags) From e725c7f182b95f6dc4747a67e4a5e4aa5192300a Mon Sep 17 00:00:00 2001 From: Donghee Na Date: Tue, 3 Jun 2025 22:01:19 +0900 Subject: [PATCH 07/13] fix --- Lib/test/test_sys.py | 2 +- Python/sysmodule.c | 13 ------------- 2 files changed, 1 insertion(+), 14 deletions(-) diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py index 6cb28514ed5b99..adb480b58493a1 100644 --- a/Lib/test/test_sys.py +++ b/Lib/test/test_sys.py @@ -787,7 +787,7 @@ def __hash__(self): @support.cpython_only def test_get_object_tags(self): - keys = ("immortal", "interned", "deferred_refcount") + keys = ("immortal", "interned") s = "foobar" tags = sys.get_object_tags(s) self.assertEqual(len(tags), len(keys)) diff --git a/Python/sysmodule.c b/Python/sysmodule.c index e2be8c49c83659..fe36c0912150d2 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -1095,19 +1095,6 @@ sys_get_object_tags(PyObject *module, PyObject *op) return NULL; } } - - if (PyUnstable_Object_EnableDeferredRefcount(op)) { - if (PyDict_SetItemString(dict, "deferred_refcount", Py_True) < 0) { - Py_DECREF(dict); - return NULL; - } - } - else { - if (PyDict_SetItemString(dict, "deferred_refcount", Py_False) < 0) { - Py_DECREF(dict); - return NULL; - } - } return dict; } From 1cdc798b44f1ce072b67f90bada4acef7bd256b1 Mon Sep 17 00:00:00 2001 From: Donghee Na Date: Tue, 3 Jun 2025 22:08:35 +0900 Subject: [PATCH 08/13] Update --- Lib/test/test_sys.py | 4 ++-- Python/sysmodule.c | 17 +++++++++++++++++ 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py index adb480b58493a1..d6df6c3ced14a5 100644 --- a/Lib/test/test_sys.py +++ b/Lib/test/test_sys.py @@ -787,7 +787,7 @@ def __hash__(self): @support.cpython_only def test_get_object_tags(self): - keys = ("immortal", "interned") + keys = ("immortal", "interned", "deferred_refcount") s = "foobar" tags = sys.get_object_tags(s) self.assertEqual(len(tags), len(keys)) @@ -796,7 +796,7 @@ def test_get_object_tags(self): @support.cpython_only def test_set_object_tags(self): - keys = ("immortal", "interned") + keys = ("immortal", "interned", "deferred_refcount") s = "should never interned before" + str(random.randrange(0, 10**9)) origin_tags = sys.get_object_tags(s) for k in keys: diff --git a/Python/sysmodule.c b/Python/sysmodule.c index fe36c0912150d2..38f997a0f00401 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -18,6 +18,7 @@ Data members: #include "pycore_audit.h" // _Py_AuditHookEntry #include "pycore_call.h" // _PyObject_CallNoArgs() #include "pycore_ceval.h" // _PyEval_SetAsyncGenFinalizer() +#include "pycore_object_deferred.h" // _PyObject_HasDeferredRefcount #include "pycore_frame.h" // _PyInterpreterFrame #include "pycore_import.h" // _PyImport_SetDLOpenFlags() #include "pycore_initconfig.h" // _PyStatus_EXCEPTION() @@ -1095,6 +1096,19 @@ sys_get_object_tags(PyObject *module, PyObject *op) return NULL; } } + + if (_PyObject_HasDeferredRefcount(op)) { + if (PyDict_SetItemString(dict, "deferred_refcount", Py_True) < 0) { + Py_DECREF(dict); + return NULL; + } + } + else { + if (PyDict_SetItemString(dict, "deferred_refcount", Py_False) < 0) { + Py_DECREF(dict); + return NULL; + } + } return dict; } @@ -1121,6 +1135,9 @@ sys_set_object_tag_impl(PyObject *module, PyObject *object, const char *tag, else if (strcmp(tag, "interned") == 0) { _PyUnicode_InternMortal(_PyInterpreterState_GET(), &object); } + else if(strcmp(tag, "deferred_refcount") == 0) { + PyUnstable_Object_EnableDeferredRefcount(object); + } Py_RETURN_NONE; } From dbc30b77ed718e50e3446f7ff4576a42b70d0a8a Mon Sep 17 00:00:00 2001 From: Donghee Na Date: Tue, 3 Jun 2025 22:13:25 +0900 Subject: [PATCH 09/13] Address code review --- Python/sysmodule.c | 45 ++++++++++++--------------------------------- 1 file changed, 12 insertions(+), 33 deletions(-) diff --git a/Python/sysmodule.c b/Python/sysmodule.c index 38f997a0f00401..3608b3d2fbbcbc 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -1071,44 +1071,23 @@ sys_get_object_tags(PyObject *module, PyObject *op) if (dict == NULL) { return NULL; } - if (PyUnstable_IsImmortal(op)) { - if (PyDict_SetItemString(dict, "immortal", Py_True) < 0) { - Py_DECREF(dict); - return NULL; - } - } - else { - if (PyDict_SetItemString(dict, "immortal", Py_False) < 0) { - Py_DECREF(dict); - return NULL; - } - } - if (PyUnicode_Check(op) && PyUnicode_CHECK_INTERNED(op)) { - if (PyDict_SetItemString(dict, "interned", Py_True) < 0) { - Py_DECREF(dict); - return NULL; - } - } - else { - if (PyDict_SetItemString(dict, "interned", Py_False) < 0) { - Py_DECREF(dict); - return NULL; - } + if (PyDict_SetItemString(dict, "immortal", PyBool_FromLong(PyUnstable_IsImmortal(op))) < 0) { + Py_DECREF(dict); + return NULL; } - if (_PyObject_HasDeferredRefcount(op)) { - if (PyDict_SetItemString(dict, "deferred_refcount", Py_True) < 0) { - Py_DECREF(dict); - return NULL; - } + + if (PyDict_SetItemString(dict, "interned", PyBool_FromLong((PyUnicode_Check(op) && PyUnicode_CHECK_INTERNED(op)))) < 0) { + Py_DECREF(dict); + return NULL; } - else { - if (PyDict_SetItemString(dict, "deferred_refcount", Py_False) < 0) { - Py_DECREF(dict); - return NULL; - } + + if (PyDict_SetItemString(dict, "deferred_refcount", PyBool_FromLong(_PyObject_HasDeferredRefcount(op))) < 0) { + Py_DECREF(dict); + return NULL; } + return dict; } From e7d06b6725c8856faec66cb580a29a04e71f7137 Mon Sep 17 00:00:00 2001 From: Donghee Na Date: Tue, 3 Jun 2025 22:14:38 +0900 Subject: [PATCH 10/13] nit --- Python/sysmodule.c | 1 - 1 file changed, 1 deletion(-) diff --git a/Python/sysmodule.c b/Python/sysmodule.c index 3608b3d2fbbcbc..afcd2939ed709d 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -1077,7 +1077,6 @@ sys_get_object_tags(PyObject *module, PyObject *op) return NULL; } - if (PyDict_SetItemString(dict, "interned", PyBool_FromLong((PyUnicode_Check(op) && PyUnicode_CHECK_INTERNED(op)))) < 0) { Py_DECREF(dict); return NULL; From ff34816b5d47056a79276232529c8f1c1600527a Mon Sep 17 00:00:00 2001 From: Donghee Na Date: Tue, 3 Jun 2025 22:27:57 +0900 Subject: [PATCH 11/13] Address code review --- Python/sysmodule.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/Python/sysmodule.c b/Python/sysmodule.c index afcd2939ed709d..5eacf5c89c9fca 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -1107,10 +1107,7 @@ sys_set_object_tag_impl(PyObject *module, PyObject *object, const char *tag, /*[clinic end generated code: output=b0fb5e9931feb4aa input=b64c9bd958c75f11]*/ { assert(object != NULL); - if (strcmp(tag, "immortal") == 0) { - _Py_SetImmortal(object); - } - else if (strcmp(tag, "interned") == 0) { + if (strcmp(tag, "interned") == 0) { _PyUnicode_InternMortal(_PyInterpreterState_GET(), &object); } else if(strcmp(tag, "deferred_refcount") == 0) { From 4e1946ffcd93eed70d6ac635bdfaf30d71b2f761 Mon Sep 17 00:00:00 2001 From: Donghee Na Date: Tue, 3 Jun 2025 22:30:03 +0900 Subject: [PATCH 12/13] nit --- Python/sysmodule.c | 1 + 1 file changed, 1 insertion(+) diff --git a/Python/sysmodule.c b/Python/sysmodule.c index 5eacf5c89c9fca..f5933ea1bdac73 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -1108,6 +1108,7 @@ sys_set_object_tag_impl(PyObject *module, PyObject *object, const char *tag, { assert(object != NULL); if (strcmp(tag, "interned") == 0) { + Py_INCREF(object); _PyUnicode_InternMortal(_PyInterpreterState_GET(), &object); } else if(strcmp(tag, "deferred_refcount") == 0) { From 2a0eb8e32605b7c50d571415c3dda2c8133e6101 Mon Sep 17 00:00:00 2001 From: Donghee Na Date: Tue, 3 Jun 2025 22:44:27 +0900 Subject: [PATCH 13/13] Update --- Lib/test/test_sys.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py index d6df6c3ced14a5..b932c860b9f25e 100644 --- a/Lib/test/test_sys.py +++ b/Lib/test/test_sys.py @@ -805,9 +805,6 @@ def test_set_object_tags(self): sys.set_object_tag(s, "unknown") after_tags = sys.get_object_tags(s) self.assertEqual(len(origin_tags), len(after_tags)) - for k in keys: - self.assertIn(k, after_tags) - self.assertTrue(after_tags[k]) @support.cpython_only @requires_subinterpreters pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy