diff options
author | Eric Snow <ericsnowcurrently@gmail.com> | 2022-02-08 13:39:07 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-02-08 13:39:07 -0700 |
commit | 81c72044a181dbbfbf689d7a977d0d99090f26a8 (patch) | |
tree | 14329746bd6f179cf2ae7c9818e1ae881eb46360 /Modules/_abc.c | |
parent | c018d3037b5b62e6d48d5985d1a37b91762fbffb (diff) | |
download | cpython-81c72044a181dbbfbf689d7a977d0d99090f26a8.tar.gz cpython-81c72044a181dbbfbf689d7a977d0d99090f26a8.zip |
bpo-46541: Replace core use of _Py_IDENTIFIER() with statically initialized global objects. (gh-30928)
We're no longer using _Py_IDENTIFIER() (or _Py_static_string()) in any core CPython code. It is still used in a number of non-builtin stdlib modules.
The replacement is: PyUnicodeObject (not pointer) fields under _PyRuntimeState, statically initialized as part of _PyRuntime. A new _Py_GET_GLOBAL_IDENTIFIER() macro facilitates lookup of the fields (along with _Py_GET_GLOBAL_STRING() for non-identifier strings).
https://bugs.python.org/issue46541#msg411799 explains the rationale for this change.
The core of the change is in:
* (new) Include/internal/pycore_global_strings.h - the declarations for the global strings, along with the macros
* Include/internal/pycore_runtime_init.h - added the static initializers for the global strings
* Include/internal/pycore_global_objects.h - where the struct in pycore_global_strings.h is hooked into _PyRuntimeState
* Tools/scripts/generate_global_objects.py - added generation of the global string declarations and static initializers
I've also added a --check flag to generate_global_objects.py (along with make check-global-objects) to check for unused global strings. That check is added to the PR CI config.
The remainder of this change updates the core code to use _Py_GET_GLOBAL_IDENTIFIER() instead of _Py_IDENTIFIER() and the related _Py*Id functions (likewise for _Py_GET_GLOBAL_STRING() instead of _Py_static_string()). This includes adding a few functions where there wasn't already an alternative to _Py*Id(), replacing the _Py_Identifier * parameter with PyObject *.
The following are not changed (yet):
* stop using _Py_IDENTIFIER() in the stdlib modules
* (maybe) get rid of _Py_IDENTIFIER(), etc. entirely -- this may not be doable as at least one package on PyPI using this (private) API
* (maybe) intern the strings during runtime init
https://bugs.python.org/issue46541
Diffstat (limited to 'Modules/_abc.c')
-rw-r--r-- | Modules/_abc.c | 49 |
1 files changed, 21 insertions, 28 deletions
diff --git a/Modules/_abc.c b/Modules/_abc.c index a0439618120..641d6198d1f 100644 --- a/Modules/_abc.c +++ b/Modules/_abc.c @@ -4,8 +4,9 @@ #endif #include "Python.h" -#include "pycore_object.h" // _PyType_GetSubclasses() #include "pycore_moduleobject.h" // _PyModule_GetState() +#include "pycore_object.h" // _PyType_GetSubclasses() +#include "pycore_runtime.h" // _Py_ID() #include "clinic/_abc.c.h" /*[clinic input] @@ -16,15 +17,6 @@ module _abc PyDoc_STRVAR(_abc__doc__, "Module contains faster C implementation of abc.ABCMeta"); -_Py_IDENTIFIER(__abstractmethods__); -_Py_IDENTIFIER(__class__); -_Py_IDENTIFIER(__dict__); -_Py_IDENTIFIER(__abc_tpflags__); -_Py_IDENTIFIER(__bases__); -_Py_IDENTIFIER(_abc_impl); -_Py_IDENTIFIER(__subclasscheck__); -_Py_IDENTIFIER(__subclasshook__); - typedef struct { PyTypeObject *_abc_data_type; unsigned long long abc_invalidation_counter; @@ -122,7 +114,7 @@ static _abc_data * _get_impl(PyObject *module, PyObject *self) { _abcmodule_state *state = get_abc_state(module); - PyObject *impl = _PyObject_GetAttrId(self, &PyId__abc_impl); + PyObject *impl = PyObject_GetAttr(self, &_Py_ID(_abc_impl)); if (impl == NULL) { return NULL; } @@ -311,7 +303,7 @@ compute_abstract_methods(PyObject *self) PyObject *ns = NULL, *items = NULL, *bases = NULL; // Py_XDECREF()ed on error. /* Stage 1: direct abstract methods. */ - ns = _PyObject_GetAttrId(self, &PyId___dict__); + ns = PyObject_GetAttr(self, &_Py_ID(__dict__)); if (!ns) { goto error; } @@ -355,7 +347,7 @@ compute_abstract_methods(PyObject *self) } /* Stage 2: inherited abstract methods. */ - bases = _PyObject_GetAttrId(self, &PyId___bases__); + bases = PyObject_GetAttr(self, &_Py_ID(__bases__)); if (!bases) { goto error; } @@ -368,8 +360,8 @@ compute_abstract_methods(PyObject *self) PyObject *item = PyTuple_GET_ITEM(bases, pos); // borrowed PyObject *base_abstracts, *iter; - if (_PyObject_LookupAttrId(item, &PyId___abstractmethods__, - &base_abstracts) < 0) { + if (_PyObject_LookupAttr(item, &_Py_ID(__abstractmethods__), + &base_abstracts) < 0) { goto error; } if (base_abstracts == NULL) { @@ -409,7 +401,7 @@ compute_abstract_methods(PyObject *self) } } - if (_PyObject_SetAttrId(self, &PyId___abstractmethods__, abstracts) < 0) { + if (PyObject_SetAttr(self, &_Py_ID(__abstractmethods__), abstracts) < 0) { goto error; } @@ -448,7 +440,7 @@ _abc__abc_init(PyObject *module, PyObject *self) if (data == NULL) { return NULL; } - if (_PyObject_SetAttrId(self, &PyId__abc_impl, data) < 0) { + if (PyObject_SetAttr(self, &_Py_ID(_abc_impl), data) < 0) { Py_DECREF(data); return NULL; } @@ -459,7 +451,8 @@ _abc__abc_init(PyObject *module, PyObject *self) * their special status w.r.t. pattern matching. */ if (PyType_Check(self)) { PyTypeObject *cls = (PyTypeObject *)self; - PyObject *flags = _PyDict_GetItemIdWithError(cls->tp_dict, &PyId___abc_tpflags__); + PyObject *flags = PyDict_GetItemWithError(cls->tp_dict, + &_Py_ID(__abc_tpflags__)); if (flags == NULL) { if (PyErr_Occurred()) { return NULL; @@ -477,7 +470,7 @@ _abc__abc_init(PyObject *module, PyObject *self) } ((PyTypeObject *)self)->tp_flags |= (val & COLLECTION_FLAGS); } - if (_PyDict_DelItemId(cls->tp_dict, &PyId___abc_tpflags__) < 0) { + if (PyDict_DelItem(cls->tp_dict, &_Py_ID(__abc_tpflags__)) < 0) { return NULL; } } @@ -593,7 +586,7 @@ _abc__abc_instancecheck_impl(PyObject *module, PyObject *self, return NULL; } - subclass = _PyObject_GetAttrId(instance, &PyId___class__); + subclass = PyObject_GetAttr(instance, &_Py_ID(__class__)); if (subclass == NULL) { Py_DECREF(impl); return NULL; @@ -622,12 +615,12 @@ _abc__abc_instancecheck_impl(PyObject *module, PyObject *self, } } /* Fall back to the subclass check. */ - result = _PyObject_CallMethodIdOneArg(self, &PyId___subclasscheck__, - subclass); + result = PyObject_CallMethodOneArg(self, &_Py_ID(__subclasscheck__), + subclass); goto end; } - result = _PyObject_CallMethodIdOneArg(self, &PyId___subclasscheck__, - subclass); + result = PyObject_CallMethodOneArg(self, &_Py_ID(__subclasscheck__), + subclass); if (result == NULL) { goto end; } @@ -639,8 +632,8 @@ _abc__abc_instancecheck_impl(PyObject *module, PyObject *self, break; case 0: Py_DECREF(result); - result = _PyObject_CallMethodIdOneArg(self, &PyId___subclasscheck__, - subtype); + result = PyObject_CallMethodOneArg(self, &_Py_ID(__subclasscheck__), + subtype); break; case 1: // Nothing to do. break; @@ -723,8 +716,8 @@ _abc__abc_subclasscheck_impl(PyObject *module, PyObject *self, } /* 3. Check the subclass hook. */ - ok = _PyObject_CallMethodIdOneArg((PyObject *)self, &PyId___subclasshook__, - subclass); + ok = PyObject_CallMethodOneArg( + (PyObject *)self, &_Py_ID(__subclasshook__), subclass); if (ok == NULL) { goto end; } |