Skip to content

Commit c41dbd0

Browse files
authored
[mypyc] Replace deprecated _PY_IDENTIFIER uses (#20460)
Uses of `_PY_IDENTIFIER` will trigger a deprecation warning for Python 3.15. Replace these with statically allocated PyObject unicode objects which are being prevented from garbage collection via `PyUnicode_InternFromString`. The implementation is adopted from a similar one in numpy. https://github.com/numpy/numpy/blob/v2.4.0/numpy/_core/src/multiarray/npy_static_data.h https://github.com/numpy/numpy/blob/v2.4.0/numpy/_core/src/multiarray/npy_static_data.c https://docs.python.org/3/c-api/unicode.html#c.PyUnicode_InternFromString Replaces #19870
1 parent 56c33f2 commit c41dbd0

File tree

12 files changed

+151
-135
lines changed

12 files changed

+151
-135
lines changed

mypyc/codegen/emitmodule.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1087,6 +1087,7 @@ def emit_module_exec_func(
10871087
declaration = f"int CPyExec_{exported_name(module_name)}(PyObject *module)"
10881088
module_static = self.module_internal_static_name(module_name, emitter)
10891089
emitter.emit_lines(declaration, "{")
1090+
emitter.emit_line("intern_strings();")
10901091
if self.compiler_options.depends_on_librt_internal:
10911092
emitter.emit_line("if (import_librt_internal() < 0) {")
10921093
emitter.emit_line("return -1;")

mypyc/codegen/emitwrapper.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -452,9 +452,8 @@ def generate_bin_op_reverse_dunder_call(fn: FuncIR, emitter: Emitter, rmethod: s
452452
if fn.name in ("__pow__", "__rpow__"):
453453
# Ternary pow() will never call the reverse dunder.
454454
emitter.emit_line("if (obj_mod == Py_None) {")
455-
emitter.emit_line(f"_Py_IDENTIFIER({rmethod});")
456455
emitter.emit_line(
457-
'return CPy_CallReverseOpMethod(obj_left, obj_right, "{}", &PyId_{});'.format(
456+
'return CPy_CallReverseOpMethod(obj_left, obj_right, "{}", mypyc_interned_str.{});'.format(
458457
op_methods_to_symbols[fn.name], rmethod
459458
)
460459
)

mypyc/lib-rt/CPy.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -938,7 +938,7 @@ int CPyStatics_Initialize(PyObject **statics,
938938
const int *frozensets);
939939
PyObject *CPy_Super(PyObject *builtins, PyObject *self);
940940
PyObject *CPy_CallReverseOpMethod(PyObject *left, PyObject *right, const char *op,
941-
_Py_Identifier *method);
941+
PyObject *method);
942942

943943
bool CPyImport_ImportMany(PyObject *modules, CPyModule **statics[], PyObject *globals,
944944
PyObject *tb_path, PyObject *tb_function, Py_ssize_t *tb_lines);

mypyc/lib-rt/bytes_extra_ops.c

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,5 @@ PyObject *CPyBytes_Translate(PyObject *bytes, PyObject *table) {
4141
}
4242

4343
// Fallback to Python method call for non-exact types or non-standard tables
44-
_Py_IDENTIFIER(translate);
45-
PyObject *name = _PyUnicode_FromId(&PyId_translate);
46-
if (name == NULL) {
47-
return NULL;
48-
}
49-
return PyObject_CallMethodOneArg(bytes, name, table);
44+
return PyObject_CallMethodOneArg(bytes, mypyc_interned_str.translate, table);
5045
}

mypyc/lib-rt/bytes_ops.c

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -101,12 +101,7 @@ PyObject *CPyBytes_Join(PyObject *sep, PyObject *iter) {
101101
if (PyBytes_CheckExact(sep)) {
102102
return PyBytes_Join(sep, iter);
103103
} else {
104-
_Py_IDENTIFIER(join);
105-
PyObject *name = _PyUnicode_FromId(&PyId_join); /* borrowed */
106-
if (name == NULL) {
107-
return NULL;
108-
}
109-
return PyObject_CallMethodOneArg(sep, name, iter);
104+
return PyObject_CallMethodOneArg(sep, mypyc_interned_str.join, iter);
110105
}
111106
}
112107

@@ -193,12 +188,7 @@ int CPyBytes_Startswith(PyObject *self, PyObject *subobj) {
193188

194189
return memcmp(self_buf, subobj_buf, (size_t)subobj_len) == 0 ? 1 : 0;
195190
}
196-
_Py_IDENTIFIER(startswith);
197-
PyObject *name = _PyUnicode_FromId(&PyId_startswith);
198-
if (name == NULL) {
199-
return 2;
200-
}
201-
PyObject *result = PyObject_CallMethodOneArg(self, name, subobj);
191+
PyObject *result = PyObject_CallMethodOneArg(self, mypyc_interned_str.startswith, subobj);
202192
if (result == NULL) {
203193
return 2;
204194
}

mypyc/lib-rt/dict_ops.c

Lines changed: 14 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -77,12 +77,7 @@ PyObject *CPyDict_SetDefault(PyObject *dict, PyObject *key, PyObject *value) {
7777
Py_XINCREF(ret);
7878
return ret;
7979
}
80-
_Py_IDENTIFIER(setdefault);
81-
PyObject *name = _PyUnicode_FromId(&PyId_setdefault); /* borrowed */
82-
if (name == NULL) {
83-
return NULL;
84-
}
85-
return PyObject_CallMethodObjArgs(dict, name, key, value, NULL);
80+
return PyObject_CallMethodObjArgs(dict, mypyc_interned_str.setdefault, key, value, NULL);
8681
}
8782

8883
PyObject *CPyDict_SetDefaultWithNone(PyObject *dict, PyObject *key) {
@@ -136,12 +131,7 @@ static inline int CPy_ObjectToStatus(PyObject *obj) {
136131
}
137132

138133
static int CPyDict_UpdateGeneral(PyObject *dict, PyObject *stuff) {
139-
_Py_IDENTIFIER(update);
140-
PyObject *name = _PyUnicode_FromId(&PyId_update); /* borrowed */
141-
if (name == NULL) {
142-
return -1;
143-
}
144-
PyObject *res = PyObject_CallMethodOneArg(dict, name, stuff);
134+
PyObject *res = PyObject_CallMethodOneArg(dict, mypyc_interned_str.update, stuff);
145135
return CPy_ObjectToStatus(res);
146136
}
147137

@@ -169,8 +159,7 @@ int CPyDict_Update(PyObject *dict, PyObject *stuff) {
169159
int CPyDict_UpdateFromAny(PyObject *dict, PyObject *stuff) {
170160
if (PyDict_CheckExact(dict)) {
171161
// Argh this sucks
172-
_Py_IDENTIFIER(keys);
173-
if (PyDict_Check(stuff) || _CPyObject_HasAttrId(stuff, &PyId_keys)) {
162+
if (PyDict_Check(stuff) || _CPyObject_HasAttr(stuff, mypyc_interned_str.keys)) {
174163
return PyDict_Update(dict, stuff);
175164
} else {
176165
return PyDict_MergeFromSeq2(dict, stuff, 1);
@@ -189,8 +178,7 @@ PyObject *CPyDict_FromAny(PyObject *obj) {
189178
if (!dict) {
190179
return NULL;
191180
}
192-
_Py_IDENTIFIER(keys);
193-
if (_CPyObject_HasAttrId(obj, &PyId_keys)) {
181+
if (_CPyObject_HasAttr(obj, mypyc_interned_str.keys)) {
194182
res = PyDict_Update(dict, obj);
195183
} else {
196184
res = PyDict_MergeFromSeq2(dict, obj, 1);
@@ -207,36 +195,21 @@ PyObject *CPyDict_KeysView(PyObject *dict) {
207195
if (PyDict_CheckExact(dict)){
208196
return _CPyDictView_New(dict, &PyDictKeys_Type);
209197
}
210-
_Py_IDENTIFIER(keys);
211-
PyObject *name = _PyUnicode_FromId(&PyId_keys); /* borrowed */
212-
if (name == NULL) {
213-
return NULL;
214-
}
215-
return PyObject_CallMethodNoArgs(dict, name);
198+
return PyObject_CallMethodNoArgs(dict, mypyc_interned_str.keys);
216199
}
217200

218201
PyObject *CPyDict_ValuesView(PyObject *dict) {
219202
if (PyDict_CheckExact(dict)){
220203
return _CPyDictView_New(dict, &PyDictValues_Type);
221204
}
222-
_Py_IDENTIFIER(values);
223-
PyObject *name = _PyUnicode_FromId(&PyId_values); /* borrowed */
224-
if (name == NULL) {
225-
return NULL;
226-
}
227-
return PyObject_CallMethodNoArgs(dict, name);
205+
return PyObject_CallMethodNoArgs(dict, mypyc_interned_str.values);
228206
}
229207

230208
PyObject *CPyDict_ItemsView(PyObject *dict) {
231209
if (PyDict_CheckExact(dict)){
232210
return _CPyDictView_New(dict, &PyDictItems_Type);
233211
}
234-
_Py_IDENTIFIER(items);
235-
PyObject *name = _PyUnicode_FromId(&PyId_items); /* borrowed */
236-
if (name == NULL) {
237-
return NULL;
238-
}
239-
return PyObject_CallMethodNoArgs(dict, name);
212+
return PyObject_CallMethodNoArgs(dict, mypyc_interned_str.items);
240213
}
241214

242215
PyObject *CPyDict_Keys(PyObject *dict) {
@@ -245,12 +218,7 @@ PyObject *CPyDict_Keys(PyObject *dict) {
245218
}
246219
// Inline generic fallback logic to also return a list.
247220
PyObject *list = PyList_New(0);
248-
_Py_IDENTIFIER(keys);
249-
PyObject *name = _PyUnicode_FromId(&PyId_keys); /* borrowed */
250-
if (name == NULL) {
251-
return NULL;
252-
}
253-
PyObject *view = PyObject_CallMethodNoArgs(dict, name);
221+
PyObject *view = PyObject_CallMethodNoArgs(dict, mypyc_interned_str.keys);
254222
if (view == NULL) {
255223
return NULL;
256224
}
@@ -268,12 +236,7 @@ PyObject *CPyDict_Values(PyObject *dict) {
268236
}
269237
// Inline generic fallback logic to also return a list.
270238
PyObject *list = PyList_New(0);
271-
_Py_IDENTIFIER(values);
272-
PyObject *name = _PyUnicode_FromId(&PyId_values); /* borrowed */
273-
if (name == NULL) {
274-
return NULL;
275-
}
276-
PyObject *view = PyObject_CallMethodNoArgs(dict, name);
239+
PyObject *view = PyObject_CallMethodNoArgs(dict, mypyc_interned_str.values);
277240
if (view == NULL) {
278241
return NULL;
279242
}
@@ -291,12 +254,7 @@ PyObject *CPyDict_Items(PyObject *dict) {
291254
}
292255
// Inline generic fallback logic to also return a list.
293256
PyObject *list = PyList_New(0);
294-
_Py_IDENTIFIER(items);
295-
PyObject *name = _PyUnicode_FromId(&PyId_items); /* borrowed */
296-
if (name == NULL) {
297-
return NULL;
298-
}
299-
PyObject *view = PyObject_CallMethodNoArgs(dict, name);
257+
PyObject *view = PyObject_CallMethodNoArgs(dict, mypyc_interned_str.items);
300258
if (view == NULL) {
301259
return NULL;
302260
}
@@ -312,12 +270,7 @@ char CPyDict_Clear(PyObject *dict) {
312270
if (PyDict_CheckExact(dict)) {
313271
PyDict_Clear(dict);
314272
} else {
315-
_Py_IDENTIFIER(clear);
316-
PyObject *name = _PyUnicode_FromId(&PyId_clear); /* borrowed */
317-
if (name == NULL) {
318-
return 0;
319-
}
320-
PyObject *res = PyObject_CallMethodNoArgs(dict, name);
273+
PyObject *res = PyObject_CallMethodNoArgs(dict, mypyc_interned_str.clear);
321274
if (res == NULL) {
322275
return 0;
323276
}
@@ -329,12 +282,7 @@ PyObject *CPyDict_Copy(PyObject *dict) {
329282
if (PyDict_CheckExact(dict)) {
330283
return PyDict_Copy(dict);
331284
}
332-
_Py_IDENTIFIER(copy);
333-
PyObject *name = _PyUnicode_FromId(&PyId_copy); /* borrowed */
334-
if (name == NULL) {
335-
return NULL;
336-
}
337-
return PyObject_CallMethodNoArgs(dict, name);
285+
return PyObject_CallMethodNoArgs(dict, mypyc_interned_str.copy);
338286
}
339287

340288
PyObject *CPyDict_GetKeysIter(PyObject *dict) {
@@ -352,12 +300,7 @@ PyObject *CPyDict_GetItemsIter(PyObject *dict) {
352300
Py_INCREF(dict);
353301
return dict;
354302
}
355-
_Py_IDENTIFIER(items);
356-
PyObject *name = _PyUnicode_FromId(&PyId_items); /* borrowed */
357-
if (name == NULL) {
358-
return NULL;
359-
}
360-
PyObject *view = PyObject_CallMethodNoArgs(dict, name);
303+
PyObject *view = PyObject_CallMethodNoArgs(dict, mypyc_interned_str.items);
361304
if (view == NULL) {
362305
return NULL;
363306
}
@@ -372,12 +315,7 @@ PyObject *CPyDict_GetValuesIter(PyObject *dict) {
372315
Py_INCREF(dict);
373316
return dict;
374317
}
375-
_Py_IDENTIFIER(values);
376-
PyObject *name = _PyUnicode_FromId(&PyId_values); /* borrowed */
377-
if (name == NULL) {
378-
return NULL;
379-
}
380-
PyObject *view = PyObject_CallMethodNoArgs(dict, name);
318+
PyObject *view = PyObject_CallMethodNoArgs(dict, mypyc_interned_str.values);
381319
if (view == NULL) {
382320
return NULL;
383321
}

mypyc/lib-rt/init.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#include <Python.h>
22
#include "CPy.h"
3+
#include "static_data.c"
34

45
struct ExcDummyStruct _CPy_ExcDummyStruct = { PyObject_HEAD_INIT(NULL) };
56
PyObject *_CPy_ExcDummy = (PyObject *)&_CPy_ExcDummyStruct;

mypyc/lib-rt/list_ops.c

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,7 @@ char CPyList_Clear(PyObject *list) {
3333
if (PyList_CheckExact(list)) {
3434
PyList_Clear(list);
3535
} else {
36-
_Py_IDENTIFIER(clear);
37-
PyObject *name = _PyUnicode_FromId(&PyId_clear);
38-
if (name == NULL) {
39-
return 0;
40-
}
41-
PyObject *res = PyObject_CallMethodNoArgs(list, name);
36+
PyObject *res = PyObject_CallMethodNoArgs(list, mypyc_interned_str.clear);
4237
if (res == NULL) {
4338
return 0;
4439
}
@@ -50,13 +45,7 @@ PyObject *CPyList_Copy(PyObject *list) {
5045
if(PyList_CheckExact(list)) {
5146
return PyList_GetSlice(list, 0, PyList_GET_SIZE(list));
5247
}
53-
_Py_IDENTIFIER(copy);
54-
55-
PyObject *name = _PyUnicode_FromId(&PyId_copy);
56-
if (name == NULL) {
57-
return NULL;
58-
}
59-
return PyObject_CallMethodNoArgs(list, name);
48+
return PyObject_CallMethodNoArgs(list, mypyc_interned_str.copy);
6049
}
6150

6251
PyObject *CPyList_GetItemShort(PyObject *list, CPyTagged index) {

mypyc/lib-rt/misc_ops.c

Lines changed: 6 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,7 @@ PyObject *CPyIter_Send(PyObject *iter, PyObject *val)
2929
if (Py_IsNone(val)) {
3030
return CPyIter_Next(iter);
3131
} else {
32-
_Py_IDENTIFIER(send);
33-
PyObject *name = _PyUnicode_FromId(&PyId_send); /* borrowed */
34-
if (name == NULL) {
35-
return NULL;
36-
}
37-
return PyObject_CallMethodOneArg(iter, name, val);
32+
return PyObject_CallMethodOneArg(iter, mypyc_interned_str.send, val);
3833
}
3934
}
4035

@@ -50,16 +45,14 @@ PyObject *CPyIter_Send(PyObject *iter, PyObject *val)
5045
// Signals an error (2) if the an exception should be propagated.
5146
int CPy_YieldFromErrorHandle(PyObject *iter, PyObject **outp)
5247
{
53-
_Py_IDENTIFIER(close);
54-
_Py_IDENTIFIER(throw);
5548
PyObject *exc_type = (PyObject *)Py_TYPE(CPy_ExcState()->exc_value);
5649
PyObject *type, *value, *traceback;
5750
PyObject *_m;
5851
PyObject *res;
5952
*outp = NULL;
6053

6154
if (PyErr_GivenExceptionMatches(exc_type, PyExc_GeneratorExit)) {
62-
_m = _PyObject_GetAttrId(iter, &PyId_close);
55+
_m = PyObject_GetAttr(iter, mypyc_interned_str.close_);
6356
if (_m) {
6457
res = PyObject_CallNoArgs(_m);
6558
Py_DECREF(_m);
@@ -72,7 +65,7 @@ int CPy_YieldFromErrorHandle(PyObject *iter, PyObject **outp)
7265
return 2;
7366
}
7467
} else {
75-
_m = _PyObject_GetAttrId(iter, &PyId_throw);
68+
_m = PyObject_GetAttr(iter, mypyc_interned_str.throw_);
7669
if (_m) {
7770
_CPy_GetExcInfo(&type, &value, &traceback);
7871
res = PyObject_CallFunctionObjArgs(_m, type, value, traceback, NULL);
@@ -877,9 +870,9 @@ PyObject *
877870
CPy_CallReverseOpMethod(PyObject *left,
878871
PyObject *right,
879872
const char *op,
880-
_Py_Identifier *method) {
873+
PyObject *method) {
881874
// Look up reverse method
882-
PyObject *m = _PyObject_GetAttrId(right, method);
875+
PyObject *m = PyObject_GetAttr(right, method);
883876
if (m == NULL) {
884877
// If reverse method not defined, generate TypeError instead AttributeError
885878
if (PyErr_ExceptionMatches(PyExc_AttributeError)) {
@@ -1065,9 +1058,7 @@ PyObject *CPy_GetName(PyObject *obj) {
10651058
if (PyType_Check(obj)) {
10661059
return PyType_GetName((PyTypeObject *)obj);
10671060
}
1068-
_Py_IDENTIFIER(__name__);
1069-
PyObject *name = _PyUnicode_FromId(&PyId___name__); /* borrowed */
1070-
return PyObject_GetAttr(obj, name);
1061+
return PyObject_GetAttr(obj, mypyc_interned_str.__name__);
10711062
}
10721063

10731064
#endif

0 commit comments

Comments
 (0)