mirror of
https://github.com/python/cpython.git
synced 2025-11-25 04:34:37 +00:00
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
This commit is contained in:
parent
c018d3037b
commit
81c72044a1
108 changed files with 2282 additions and 1573 deletions
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue