Skip to content

Commit fb997ab

Browse files
committed
Add set_object_tag
1 parent 17ccccf commit fb997ab

File tree

3 files changed

+123
-2
lines changed

3 files changed

+123
-2
lines changed

Lib/test/test_sys.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -794,6 +794,20 @@ def test_get_object_tags(self):
794794
for k in keys:
795795
self.assertIn(k, tags)
796796

797+
@support.cpython_only
798+
def test_set_object_tags(self):
799+
keys = ("immortal", "interned")
800+
s = "should never interned before" + str(random.randrange(0, 10**9))
801+
origin_tags = sys.get_object_tags(s)
802+
for k in keys:
803+
sys.set_object_tag(s, k)
804+
sys.set_object_tag(s, "unknown")
805+
after_tags = sys.get_object_tags(s)
806+
self.assertEqual(len(origin_tags), len(after_tags))
807+
for k in keys:
808+
self.assertIn(k, after_tags)
809+
self.assertTrue(after_tags[k])
810+
797811
@support.cpython_only
798812
@requires_subinterpreters
799813
def test_subinterp_intern_dynamically_allocated(self):

Python/clinic/sysmodule.c.h

Lines changed: 81 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Python/sysmodule.c

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1083,7 +1083,7 @@ sys_get_object_tags(PyObject *module, PyObject *op)
10831083
}
10841084
}
10851085

1086-
if (PyUnicode_CHECK_INTERNED(op)) {
1086+
if (PyUnicode_Check(op) && PyUnicode_CHECK_INTERNED(op)) {
10871087
if (PyDict_SetItemString(dict, "interned", Py_True) < 0) {
10881088
Py_DECREF(dict);
10891089
return NULL;
@@ -1111,6 +1111,32 @@ sys_get_object_tags(PyObject *module, PyObject *op)
11111111
return dict;
11121112
}
11131113

1114+
/*[clinic input]
1115+
sys.set_object_tag -> object
1116+
1117+
object: object
1118+
tag: str
1119+
*
1120+
options: object = None
1121+
1122+
Set the tags of the given object.
1123+
[clinic start generated code]*/
1124+
1125+
static PyObject *
1126+
sys_set_object_tag_impl(PyObject *module, PyObject *object, const char *tag,
1127+
PyObject *options)
1128+
/*[clinic end generated code: output=b0fb5e9931feb4aa input=b64c9bd958c75f11]*/
1129+
{
1130+
assert(object != NULL);
1131+
if (strcmp(tag, "immortal") == 0) {
1132+
_Py_SetImmortal(object);
1133+
}
1134+
else if (strcmp(tag, "interned") == 0) {
1135+
_PyUnicode_InternMortal(_PyInterpreterState_GET(), &object);
1136+
}
1137+
Py_RETURN_NONE;
1138+
}
1139+
11141140
/*
11151141
* Cached interned string objects used for calling the profile and
11161142
* trace functions.
@@ -2856,6 +2882,7 @@ static PyMethodDef sys_methods[] = {
28562882
SYS_INTERN_METHODDEF
28572883
SYS__IS_INTERNED_METHODDEF
28582884
SYS_GET_OBJECT_TAGS_METHODDEF
2885+
SYS_SET_OBJECT_TAG_METHODDEF
28592886
SYS_IS_FINALIZING_METHODDEF
28602887
SYS_MDEBUG_METHODDEF
28612888
SYS_SETSWITCHINTERVAL_METHODDEF

0 commit comments

Comments
 (0)