From 4fb96a11db5eaca3646bfa697d191469e567d283 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Tue, 29 Aug 2023 02:29:46 +0200 Subject: [PATCH] gh-106320: Remove private _Py_Identifier API (#108593) Remove the private _Py_Identifier type and related private functions from the public C API: * _PyObject_GetAttrId() * _PyObject_LookupSpecialId() * _PyObject_SetAttrId() * _PyType_LookupId() * _Py_IDENTIFIER() * _Py_static_string() * _Py_static_string_init() Move them to the internal C API: add a new pycore_identifier.h header file. No longer export these functions. --- Include/cpython/object.h | 42 ------------------- Include/internal/pycore_call.h | 1 + Include/internal/pycore_dict.h | 1 + Include/internal/pycore_identifier.h | 54 +++++++++++++++++++++++++ Include/internal/pycore_unicodeobject.h | 1 + Makefile.pre.in | 1 + PCbuild/pythoncore.vcxproj | 5 ++- PCbuild/pythoncore.vcxproj.filters | 7 +++- 8 files changed, 66 insertions(+), 46 deletions(-) create mode 100644 Include/internal/pycore_identifier.h diff --git a/Include/cpython/object.h b/Include/cpython/object.h index 5f8b1f7c195501..489b2eecd32991 100644 --- a/Include/cpython/object.h +++ b/Include/cpython/object.h @@ -19,43 +19,6 @@ PyAPI_FUNC(Py_ssize_t) _PyInterpreterState_GetRefTotal(PyInterpreterState *); #endif -/********************* String Literals ****************************************/ -/* This structure helps managing static strings. The basic usage goes like this: - Instead of doing - - r = PyObject_CallMethod(o, "foo", "args", ...); - - do - - _Py_IDENTIFIER(foo); - ... - r = _PyObject_CallMethodId(o, &PyId_foo, "args", ...); - - PyId_foo is a static variable, either on block level or file level. On first - usage, the string "foo" is interned, and the structures are linked. On interpreter - shutdown, all strings are released. - - Alternatively, _Py_static_string allows choosing the variable name. - _PyUnicode_FromId returns a borrowed reference to the interned string. - _PyObject_{Get,Set,Has}AttrId are __getattr__ versions using _Py_Identifier*. -*/ -typedef struct _Py_Identifier { - const char* string; - // Index in PyInterpreterState.unicode.ids.array. It is process-wide - // unique and must be initialized to -1. - Py_ssize_t index; -} _Py_Identifier; - -#ifndef Py_BUILD_CORE -// For now we are keeping _Py_IDENTIFIER for continued use -// in non-builtin extensions (and naughty PyPI modules). - -#define _Py_static_string_init(value) { .string = (value), .index = -1 } -#define _Py_static_string(varname, value) static _Py_Identifier varname = _Py_static_string_init(value) -#define _Py_IDENTIFIER(varname) _Py_static_string(PyId_##varname, #varname) - -#endif /* !Py_BUILD_CORE */ - typedef struct { /* Number implementations must check *both* arguments for proper type and implement the necessary conversions @@ -273,8 +236,6 @@ typedef struct _heaptypeobject { PyAPI_FUNC(const char *) _PyType_Name(PyTypeObject *); PyAPI_FUNC(PyObject *) _PyType_Lookup(PyTypeObject *, PyObject *); -PyAPI_FUNC(PyObject *) _PyType_LookupId(PyTypeObject *, _Py_Identifier *); -PyAPI_FUNC(PyObject *) _PyObject_LookupSpecialId(PyObject *, _Py_Identifier *); PyAPI_FUNC(PyObject *) PyType_GetModuleByDef(PyTypeObject *, PyModuleDef *); PyAPI_FUNC(PyObject *) PyType_GetDict(PyTypeObject *); @@ -282,9 +243,6 @@ PyAPI_FUNC(int) PyObject_Print(PyObject *, FILE *, int); PyAPI_FUNC(void) _Py_BreakPoint(void); PyAPI_FUNC(void) _PyObject_Dump(PyObject *); -PyAPI_FUNC(PyObject *) _PyObject_GetAttrId(PyObject *, _Py_Identifier *); -PyAPI_FUNC(int) _PyObject_SetAttrId(PyObject *, _Py_Identifier *, PyObject *); - PyAPI_FUNC(PyObject **) _PyObject_GetDictPtr(PyObject *); PyAPI_FUNC(void) PyObject_CallFinalizer(PyObject *); PyAPI_FUNC(int) PyObject_CallFinalizerFromDealloc(PyObject *); diff --git a/Include/internal/pycore_call.h b/Include/internal/pycore_call.h index db719234e05bf3..8846155b38defb 100644 --- a/Include/internal/pycore_call.h +++ b/Include/internal/pycore_call.h @@ -8,6 +8,7 @@ extern "C" { # error "this header requires Py_BUILD_CORE define" #endif +#include "pycore_identifier.h" // _Py_Identifier #include "pycore_pystate.h" // _PyThreadState_GET() /* Suggested size (number of positional arguments) for arrays of PyObject* diff --git a/Include/internal/pycore_dict.h b/Include/internal/pycore_dict.h index e79fb207cf75b1..47b5948f66343a 100644 --- a/Include/internal/pycore_dict.h +++ b/Include/internal/pycore_dict.h @@ -9,6 +9,7 @@ extern "C" { # error "this header requires Py_BUILD_CORE define" #endif +#include "pycore_identifier.h" // _Py_Identifier #include "pycore_object.h" // PyDictOrValues // Unsafe flavor of PyDict_GetItemWithError(): no error checking diff --git a/Include/internal/pycore_identifier.h b/Include/internal/pycore_identifier.h new file mode 100644 index 00000000000000..0e015a40c831f4 --- /dev/null +++ b/Include/internal/pycore_identifier.h @@ -0,0 +1,54 @@ +/* String Literals: _Py_Identifier API */ + +#ifndef Py_INTERNAL_IDENTIFIER_H +#define Py_INTERNAL_IDENTIFIER_H +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef Py_BUILD_CORE +# error "this header requires Py_BUILD_CORE define" +#endif + +/* This structure helps managing static strings. The basic usage goes like this: + Instead of doing + + r = PyObject_CallMethod(o, "foo", "args", ...); + + do + + _Py_IDENTIFIER(foo); + ... + r = _PyObject_CallMethodId(o, &PyId_foo, "args", ...); + + PyId_foo is a static variable, either on block level or file level. On first + usage, the string "foo" is interned, and the structures are linked. On interpreter + shutdown, all strings are released. + + Alternatively, _Py_static_string allows choosing the variable name. + _PyUnicode_FromId returns a borrowed reference to the interned string. + _PyObject_{Get,Set,Has}AttrId are __getattr__ versions using _Py_Identifier*. +*/ +typedef struct _Py_Identifier { + const char* string; + // Index in PyInterpreterState.unicode.ids.array. It is process-wide + // unique and must be initialized to -1. + Py_ssize_t index; +} _Py_Identifier; + +// For now we are keeping _Py_IDENTIFIER for continued use +// in non-builtin extensions (and naughty PyPI modules). + +#define _Py_static_string_init(value) { .string = (value), .index = -1 } +#define _Py_static_string(varname, value) static _Py_Identifier varname = _Py_static_string_init(value) +#define _Py_IDENTIFIER(varname) _Py_static_string(PyId_##varname, #varname) + +extern PyObject* _PyType_LookupId(PyTypeObject *, _Py_Identifier *); +extern PyObject* _PyObject_LookupSpecialId(PyObject *, _Py_Identifier *); +extern PyObject* _PyObject_GetAttrId(PyObject *, _Py_Identifier *); +extern int _PyObject_SetAttrId(PyObject *, _Py_Identifier *, PyObject *); + +#ifdef __cplusplus +} +#endif +#endif // !Py_INTERNAL_IDENTIFIER_H diff --git a/Include/internal/pycore_unicodeobject.h b/Include/internal/pycore_unicodeobject.h index 08c3dfec93bf05..360a9e1819f8e8 100644 --- a/Include/internal/pycore_unicodeobject.h +++ b/Include/internal/pycore_unicodeobject.h @@ -9,6 +9,7 @@ extern "C" { #endif #include "pycore_fileutils.h" // _Py_error_handler +#include "pycore_identifier.h" // _Py_Identifier #include "pycore_ucnhash.h" // _PyUnicode_Name_CAPI /* --- Characters Type APIs ----------------------------------------------- */ diff --git a/Makefile.pre.in b/Makefile.pre.in index 54b64e123cd7bc..62a55bb2478fe4 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -1769,6 +1769,7 @@ PYTHON_HEADERS= \ $(srcdir)/Include/internal/pycore_global_objects_fini_generated.h \ $(srcdir)/Include/internal/pycore_hamt.h \ $(srcdir)/Include/internal/pycore_hashtable.h \ + $(srcdir)/Include/internal/pycore_identifier.h \ $(srcdir)/Include/internal/pycore_import.h \ $(srcdir)/Include/internal/pycore_initconfig.h \ $(srcdir)/Include/internal/pycore_interp.h \ diff --git a/PCbuild/pythoncore.vcxproj b/PCbuild/pythoncore.vcxproj index b0e62864421e17..bc1250f63957e2 100644 --- a/PCbuild/pythoncore.vcxproj +++ b/PCbuild/pythoncore.vcxproj @@ -235,6 +235,7 @@ + @@ -248,7 +249,7 @@ - + @@ -280,7 +281,7 @@ - + diff --git a/PCbuild/pythoncore.vcxproj.filters b/PCbuild/pythoncore.vcxproj.filters index d5f61e9c5d7c89..a8a11d3b8b83b1 100644 --- a/PCbuild/pythoncore.vcxproj.filters +++ b/PCbuild/pythoncore.vcxproj.filters @@ -609,6 +609,9 @@ Include\internal + + Include\internal + Include\internal @@ -650,7 +653,7 @@ Include\internal - + Include\internal @@ -737,7 +740,7 @@ Include\internal - + Modules\zlib