From 436c1b08ddb4d1593895b80061cfdca5fe47ad0c Mon Sep 17 00:00:00 2001 From: Christian Heimes Date: Sat, 14 Nov 2020 16:08:14 +0100 Subject: [PATCH 01/13] Define module constants in PyModuleDef Signed-off-by: Christian Heimes --- Include/moduleobject.h | 37 ++++++++++ Modules/mathmodule.c | 51 ++++++------- Modules/posixmodule.c | 161 +++++++++++++++++++++-------------------- Objects/moduleobject.c | 67 +++++++++++++++++ 4 files changed, 210 insertions(+), 106 deletions(-) diff --git a/Include/moduleobject.h b/Include/moduleobject.h index 49b116ca1c3587..58392c68682a32 100644 --- a/Include/moduleobject.h +++ b/Include/moduleobject.h @@ -72,6 +72,42 @@ typedef struct PyModuleDef_Slot{ #endif /* New in 3.5 */ +struct PyModuleConstants_Def; +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03100000 +/* New in 3.10 */ +#define Py_mc_none 1 +#define Py_mc_long 2 +#define Py_mc_bool 3 +#define Py_mc_double 4 +#define Py_mc_string 5 +#define Py_mc_call 6 +#define Py_mc_type 7 + +typedef struct PyModuleConstants_Def { + const char *name; + int type; + union { + const char *m_str; + long m_long; + double m_double; + PyObject* (*m_call)(void); + } value; +} PyModuleConstants_Def; + +PyAPI_FUNC(int) PyModule_AddConstants(PyObject *, PyModuleConstants_Def *); + +#define PyMC_None(name) {(name), Py_mc_none, {.m_long=0}} +#define PyMC_Long(name, value) {(name), Py_mc_long, {.m_long=(value)}} +#define PyMC_Bool(name, value) {(name), Py_mc_bool, {.m_long=(value)}} +#define PyMC_Double(name, value) {(name), Py_mc_double, {.m_double=(value)}} +#define PyMC_String(name, value) {(name), Py_mc_string, {.m_string=(value)}} +#define PyMC_Call(name, value) {(name), Py_mc_call, {.m_call=(value)}} + +#define PyMC_LongMacro(m) PyMC_Long(#m, m) +#define PyMC_StringMacro(m) PyMC_String(#m, m) + +#endif /* New in 3.10 */ + typedef struct PyModuleDef{ PyModuleDef_Base m_base; const char* m_name; @@ -82,6 +118,7 @@ typedef struct PyModuleDef{ traverseproc m_traverse; inquiry m_clear; freefunc m_free; + struct PyModuleConstants_Def* m_constants; } PyModuleDef; diff --git a/Modules/mathmodule.c b/Modules/mathmodule.c index d0dd12d25966a1..fe8e3816bf4c77 100644 --- a/Modules/mathmodule.c +++ b/Modules/mathmodule.c @@ -270,6 +270,12 @@ m_inf(void) #endif } +static PyObject* +m_inf_o(void) +{ + return PyFloat_FromDouble(m_inf()); +} + /* Constant nan value, generated in the same way as float('nan'). */ /* We don't currently assume that Py_NAN is defined everywhere. */ @@ -285,6 +291,12 @@ m_nan(void) #endif } +static PyObject* +m_nan_o(void) +{ + return PyFloat_FromDouble(m_nan()); +} + #endif static double @@ -3514,30 +3526,6 @@ math_ulp_impl(PyObject *module, double x) return x2 - x; } -static int -math_exec(PyObject *module) -{ - if (PyModule_AddObject(module, "pi", PyFloat_FromDouble(Py_MATH_PI)) < 0) { - return -1; - } - if (PyModule_AddObject(module, "e", PyFloat_FromDouble(Py_MATH_E)) < 0) { - return -1; - } - // 2pi - if (PyModule_AddObject(module, "tau", PyFloat_FromDouble(Py_MATH_TAU)) < 0) { - return -1; - } - if (PyModule_AddObject(module, "inf", PyFloat_FromDouble(m_inf())) < 0) { - return -1; - } -#if !defined(PY_NO_SHORT_FLOAT_REPR) || defined(Py_NAN) - if (PyModule_AddObject(module, "nan", PyFloat_FromDouble(m_nan())) < 0) { - return -1; - } -#endif - return 0; -} - static PyMethodDef math_methods[] = { {"acos", math_acos, METH_O, math_acos_doc}, {"acosh", math_acosh, METH_O, math_acosh_doc}, @@ -3595,9 +3583,16 @@ static PyMethodDef math_methods[] = { {NULL, NULL} /* sentinel */ }; -static PyModuleDef_Slot math_slots[] = { - {Py_mod_exec, math_exec}, - {0, NULL} +static PyModuleConstants_Def math_constants[] = { + PyMC_Double("pi", Py_MATH_PI), + PyMC_Double("e", Py_MATH_E), + // 2pi + PyMC_Double("tau", Py_MATH_TAU), + PyMC_Call("inf", m_inf_o), +#if !defined(PY_NO_SHORT_FLOAT_REPR) || defined(Py_NAN) + PyMC_Call("nan", m_nan_o), +#endif + {NULL, 0}, }; PyDoc_STRVAR(module_doc, @@ -3610,7 +3605,7 @@ static struct PyModuleDef mathmodule = { .m_doc = module_doc, .m_size = 0, .m_methods = math_methods, - .m_slots = math_slots, + .m_constants = math_constants, }; PyMODINIT_FUNC diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index 65e8d5e7bd984d..bca06e67e6d702 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -14834,84 +14834,6 @@ static PyMethodDef posix_methods[] = { static int all_ins(PyObject *m) { -#ifdef F_OK - if (PyModule_AddIntMacro(m, F_OK)) return -1; -#endif -#ifdef R_OK - if (PyModule_AddIntMacro(m, R_OK)) return -1; -#endif -#ifdef W_OK - if (PyModule_AddIntMacro(m, W_OK)) return -1; -#endif -#ifdef X_OK - if (PyModule_AddIntMacro(m, X_OK)) return -1; -#endif -#ifdef NGROUPS_MAX - if (PyModule_AddIntMacro(m, NGROUPS_MAX)) return -1; -#endif -#ifdef TMP_MAX - if (PyModule_AddIntMacro(m, TMP_MAX)) return -1; -#endif -#ifdef WCONTINUED - if (PyModule_AddIntMacro(m, WCONTINUED)) return -1; -#endif -#ifdef WNOHANG - if (PyModule_AddIntMacro(m, WNOHANG)) return -1; -#endif -#ifdef WUNTRACED - if (PyModule_AddIntMacro(m, WUNTRACED)) return -1; -#endif -#ifdef O_RDONLY - if (PyModule_AddIntMacro(m, O_RDONLY)) return -1; -#endif -#ifdef O_WRONLY - if (PyModule_AddIntMacro(m, O_WRONLY)) return -1; -#endif -#ifdef O_RDWR - if (PyModule_AddIntMacro(m, O_RDWR)) return -1; -#endif -#ifdef O_NDELAY - if (PyModule_AddIntMacro(m, O_NDELAY)) return -1; -#endif -#ifdef O_NONBLOCK - if (PyModule_AddIntMacro(m, O_NONBLOCK)) return -1; -#endif -#ifdef O_APPEND - if (PyModule_AddIntMacro(m, O_APPEND)) return -1; -#endif -#ifdef O_DSYNC - if (PyModule_AddIntMacro(m, O_DSYNC)) return -1; -#endif -#ifdef O_RSYNC - if (PyModule_AddIntMacro(m, O_RSYNC)) return -1; -#endif -#ifdef O_SYNC - if (PyModule_AddIntMacro(m, O_SYNC)) return -1; -#endif -#ifdef O_NOCTTY - if (PyModule_AddIntMacro(m, O_NOCTTY)) return -1; -#endif -#ifdef O_CREAT - if (PyModule_AddIntMacro(m, O_CREAT)) return -1; -#endif -#ifdef O_EXCL - if (PyModule_AddIntMacro(m, O_EXCL)) return -1; -#endif -#ifdef O_TRUNC - if (PyModule_AddIntMacro(m, O_TRUNC)) return -1; -#endif -#ifdef O_BINARY - if (PyModule_AddIntMacro(m, O_BINARY)) return -1; -#endif -#ifdef O_TEXT - if (PyModule_AddIntMacro(m, O_TEXT)) return -1; -#endif -#ifdef O_XATTR - if (PyModule_AddIntMacro(m, O_XATTR)) return -1; -#endif -#ifdef O_LARGEFILE - if (PyModule_AddIntMacro(m, O_LARGEFILE)) return -1; -#endif #ifndef __GNU__ #ifdef O_SHLOCK if (PyModule_AddIntMacro(m, O_SHLOCK)) return -1; @@ -15765,6 +15687,88 @@ posixmodule_exec(PyObject *m) return 0; } +static PyModuleConstants_Def _posix_constants[] = { +#ifdef F_OK + PyMC_LongMacro(F_OK), +#endif +#ifdef R_OK + PyMC_LongMacro(R_OK), +#endif +#ifdef W_OK + PyMC_LongMacro(W_OK), +#endif +#ifdef X_OK + PyMC_LongMacro(X_OK), +#endif +#ifdef NGROUPS_MAX + PyMC_LongMacro(NGROUPS_MAX), +#endif +#ifdef TMP_MAX + PyMC_LongMacro(TMP_MAX), +#endif +#ifdef WCONTINUED + PyMC_LongMacro(WCONTINUED), +#endif +#ifdef WNOHANG + PyMC_LongMacro(WNOHANG), +#endif +#ifdef WUNTRACED + PyMC_LongMacro(WUNTRACED), +#endif +#ifdef O_RDONLY + PyMC_LongMacro(O_RDONLY), +#endif +#ifdef O_WRONLY + PyMC_LongMacro(O_WRONLY), +#endif +#ifdef O_RDWR + PyMC_LongMacro(O_RDWR), +#endif +#ifdef O_NDELAY + PyMC_LongMacro(O_NDELAY), +#endif +#ifdef O_NONBLOCK + PyMC_LongMacro(O_NONBLOCK), +#endif +#ifdef O_APPEND + PyMC_LongMacro(O_APPEND), +#endif +#ifdef O_DSYNC + PyMC_LongMacro(O_DSYNC), +#endif +#ifdef O_RSYNC + PyMC_LongMacro(O_RSYNC), +#endif +#ifdef O_SYNC + PyMC_LongMacro(O_SYNC), +#endif +#ifdef O_NOCTTY + PyMC_LongMacro(O_NOCTTY), +#endif +#ifdef O_CREAT + PyMC_LongMacro(O_CREAT), +#endif +#ifdef O_EXCL + PyMC_LongMacro(O_EXCL), +#endif +#ifdef O_TRUNC + PyMC_LongMacro(O_TRUNC), +#endif +#ifdef O_BINARY + PyMC_LongMacro(O_BINARY), +#endif +#ifdef O_TEXT + PyMC_LongMacro(O_TEXT), +#endif +#ifdef O_XATTR + PyMC_LongMacro(O_XATTR), +#endif +#ifdef O_LARGEFILE + PyMC_LongMacro(O_LARGEFILE), +#endif + {NULL, 0}, +}; + static PyModuleDef_Slot posixmodile_slots[] = { {Py_mod_exec, posixmodule_exec}, @@ -15781,6 +15785,7 @@ static struct PyModuleDef posixmodule = { .m_traverse = _posix_traverse, .m_clear = _posix_clear, .m_free = _posix_free, + .m_constants = _posix_constants, }; PyMODINIT_FUNC diff --git a/Objects/moduleobject.c b/Objects/moduleobject.c index e57ea86e7694ce..23a11376c38253 100644 --- a/Objects/moduleobject.c +++ b/Objects/moduleobject.c @@ -245,6 +245,12 @@ _PyModule_CreateInitialized(struct PyModuleDef* module, int module_api_version) return NULL; } } + if (module->m_constants != NULL) { + if (PyModule_AddConstants((PyObject *) m, module->m_constants) != 0) { + Py_DECREF(m); + return NULL; + } + } m->md_def = module; return (PyObject*)m; } @@ -364,6 +370,13 @@ PyModule_FromDefAndSpec2(struct PyModuleDef* def, PyObject *spec, int module_api } } + if (def->m_constants != NULL) { + if (PyModule_AddConstants((PyObject *) m, def->m_constants) != 0) { + Py_DECREF(m); + return NULL; + } + } + Py_DECREF(nameobj); return m; @@ -438,6 +451,60 @@ PyModule_ExecDef(PyObject *module, PyModuleDef *def) return 0; } +int +PyModule_AddConstants(PyObject *module, PyModuleConstants_Def *def) +{ + PyObject *dict; + PyModuleConstants_Def *cur_def; + PyObject *v; + int res; + + dict = PyModule_GetDict(module); + if (dict == NULL) { + return -1; + } + + for (cur_def = def; cur_def && cur_def->name; cur_def++) { + switch(cur_def->type) { + case Py_mc_none: + v = Py_None; + Py_INCREF(v); + break; + case Py_mc_long: + v = PyLong_FromLong(cur_def->value.m_long); + break; + case Py_mc_bool: + v = PyBool_FromLong(cur_def->value.m_long); + break; + case Py_mc_double: + v = PyFloat_FromDouble(cur_def->value.m_double); + break; + case Py_mc_string: + v = PyUnicode_FromString(cur_def->value.m_str); + break; + case Py_mc_call: + v = cur_def->value.m_call(); + break; + default: + v = NULL; + PyErr_Format(PyExc_SystemError, + "Invalid format for '%s'", + cur_def->name); + break; + } + if (v == NULL) { + return -1; + } + res = PyDict_SetItemString(dict, cur_def->name, v); + Py_DECREF(v); + if (res < 0) { + return -1; + } + } + + return 0; +} + int PyModule_AddFunctions(PyObject *m, PyMethodDef *functions) { From d93f2da2bd0d231b9af8c69b4de718692753d5e5 Mon Sep 17 00:00:00 2001 From: Christian Heimes Date: Sun, 15 Nov 2020 14:14:10 +0100 Subject: [PATCH 02/13] Add PyModule_AddTypeFromSpec --- Include/modsupport.h | 5 ++ Include/moduleobject.h | 2 - Modules/_hashopenssl.c | 36 +++---------- Objects/moduleobject.c | 112 ++++++++++++++++++++--------------------- Python/modsupport.c | 20 ++++++++ 5 files changed, 89 insertions(+), 86 deletions(-) diff --git a/Include/modsupport.h b/Include/modsupport.h index f009d586bf6202..927206da1b6555 100644 --- a/Include/modsupport.h +++ b/Include/modsupport.h @@ -154,6 +154,11 @@ PyAPI_FUNC(int) PyModule_AddType(PyObject *module, PyTypeObject *type); #define PyModule_AddIntMacro(m, c) PyModule_AddIntConstant(m, #c, c) #define PyModule_AddStringMacro(m, c) PyModule_AddStringConstant(m, #c, c) +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03100000 +/* New in 3.9 */ +PyAPI_FUNC(int) PyModule_AddTypeFromSpec(PyObject *module, PyType_Spec *spec, PyObject *bases, PyTypeObject **rtype); +#endif + #if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03050000 /* New in 3.5 */ PyAPI_FUNC(int) PyModule_SetDocString(PyObject *, const char *); diff --git a/Include/moduleobject.h b/Include/moduleobject.h index 58392c68682a32..d0f3e2be07ceb6 100644 --- a/Include/moduleobject.h +++ b/Include/moduleobject.h @@ -94,8 +94,6 @@ typedef struct PyModuleConstants_Def { } value; } PyModuleConstants_Def; -PyAPI_FUNC(int) PyModule_AddConstants(PyObject *, PyModuleConstants_Def *); - #define PyMC_None(name) {(name), Py_mc_none, {.m_long=0}} #define PyMC_Long(name, value) {(name), Py_mc_long, {.m_long=(value)}} #define PyMC_Bool(name, value) {(name), Py_mc_bool, {.m_long=(value)}} diff --git a/Modules/_hashopenssl.c b/Modules/_hashopenssl.c index 870ee89fdafc63..070994b7cc3342 100644 --- a/Modules/_hashopenssl.c +++ b/Modules/_hashopenssl.c @@ -2023,16 +2023,8 @@ hashlib_free(void *m) static int hashlib_init_evptype(PyObject *module) { - _hashlibstate *state = get_hashlib_state(module); - - state->EVPtype = (PyTypeObject *)PyType_FromSpec(&EVPtype_spec); - if (state->EVPtype == NULL) { - return -1; - } - if (PyModule_AddType(module, state->EVPtype) < 0) { - return -1; - } - return 0; + return PyModule_AddTypeFromSpec( + module, &EVPtype_spec, NULL, &(get_hashlib_state(module)->EVPtype)); } static int @@ -2044,16 +2036,12 @@ hashlib_init_evpxoftype(PyObject *module) if (state->EVPtype == NULL) { return -1; } - - state->EVPXOFtype = (PyTypeObject *)PyType_FromSpecWithBases( - &EVPXOFtype_spec, (PyObject *)state->EVPtype - ); - if (state->EVPXOFtype == NULL) { - return -1; - } - if (PyModule_AddType(module, state->EVPXOFtype) < 0) { + bases = PyTuple_Pack(1, state->EVPtype); + if (bases == NULL) { return -1; } + return PyModule_AddTypeFromSpec( + module, &EVPXOFtype_spec, state->EVPtype, &(state->EVPXOFtype)); #endif return 0; } @@ -2061,16 +2049,8 @@ hashlib_init_evpxoftype(PyObject *module) static int hashlib_init_hmactype(PyObject *module) { - _hashlibstate *state = get_hashlib_state(module); - - state->HMACtype = (PyTypeObject *)PyType_FromSpec(&HMACtype_spec); - if (state->HMACtype == NULL) { - return -1; - } - if (PyModule_AddType(module, state->HMACtype) < 0) { - return -1; - } - return 0; + return PyModule_AddTypeFromSpec( + module, &HMACtype_spec, NULL, &(get_hashlib_state(module)->HMACtype)); } static int diff --git a/Objects/moduleobject.c b/Objects/moduleobject.c index 23a11376c38253..ced49032f11cba 100644 --- a/Objects/moduleobject.c +++ b/Objects/moduleobject.c @@ -175,6 +175,60 @@ _add_methods_to_object(PyObject *module, PyObject *name, PyMethodDef *functions) return 0; } +static int +module_add_constants(PyObject *module, PyModuleConstants_Def *def) +{ + PyObject *dict; + PyModuleConstants_Def *cur_def; + PyObject *v; + int res; + + dict = PyModule_GetDict(module); + if (dict == NULL) { + return -1; + } + + for (cur_def = def; cur_def && cur_def->name; cur_def++) { + switch(cur_def->type) { + case Py_mc_none: + v = Py_None; + Py_INCREF(v); + break; + case Py_mc_long: + v = PyLong_FromLong(cur_def->value.m_long); + break; + case Py_mc_bool: + v = PyBool_FromLong(cur_def->value.m_long); + break; + case Py_mc_double: + v = PyFloat_FromDouble(cur_def->value.m_double); + break; + case Py_mc_string: + v = PyUnicode_FromString(cur_def->value.m_str); + break; + case Py_mc_call: + v = cur_def->value.m_call(); + break; + default: + v = NULL; + PyErr_Format(PyExc_SystemError, + "Invalid format for '%s'", + cur_def->name); + break; + } + if (v == NULL) { + return -1; + } + res = PyDict_SetItemString(dict, cur_def->name, v); + Py_DECREF(v); + if (res < 0) { + return -1; + } + } + + return 0; +} + PyObject * PyModule_Create2(struct PyModuleDef* module, int module_api_version) { @@ -246,7 +300,7 @@ _PyModule_CreateInitialized(struct PyModuleDef* module, int module_api_version) } } if (module->m_constants != NULL) { - if (PyModule_AddConstants((PyObject *) m, module->m_constants) != 0) { + if (module_add_constants((PyObject *) m, module->m_constants) != 0) { Py_DECREF(m); return NULL; } @@ -371,7 +425,7 @@ PyModule_FromDefAndSpec2(struct PyModuleDef* def, PyObject *spec, int module_api } if (def->m_constants != NULL) { - if (PyModule_AddConstants((PyObject *) m, def->m_constants) != 0) { + if (module_add_constants((PyObject *) m, def->m_constants) != 0) { Py_DECREF(m); return NULL; } @@ -451,60 +505,6 @@ PyModule_ExecDef(PyObject *module, PyModuleDef *def) return 0; } -int -PyModule_AddConstants(PyObject *module, PyModuleConstants_Def *def) -{ - PyObject *dict; - PyModuleConstants_Def *cur_def; - PyObject *v; - int res; - - dict = PyModule_GetDict(module); - if (dict == NULL) { - return -1; - } - - for (cur_def = def; cur_def && cur_def->name; cur_def++) { - switch(cur_def->type) { - case Py_mc_none: - v = Py_None; - Py_INCREF(v); - break; - case Py_mc_long: - v = PyLong_FromLong(cur_def->value.m_long); - break; - case Py_mc_bool: - v = PyBool_FromLong(cur_def->value.m_long); - break; - case Py_mc_double: - v = PyFloat_FromDouble(cur_def->value.m_double); - break; - case Py_mc_string: - v = PyUnicode_FromString(cur_def->value.m_str); - break; - case Py_mc_call: - v = cur_def->value.m_call(); - break; - default: - v = NULL; - PyErr_Format(PyExc_SystemError, - "Invalid format for '%s'", - cur_def->name); - break; - } - if (v == NULL) { - return -1; - } - res = PyDict_SetItemString(dict, cur_def->name, v); - Py_DECREF(v); - if (res < 0) { - return -1; - } - } - - return 0; -} - int PyModule_AddFunctions(PyObject *m, PyMethodDef *functions) { diff --git a/Python/modsupport.c b/Python/modsupport.c index 8655daa1fc5e0e..c47b9a1c70440f 100644 --- a/Python/modsupport.c +++ b/Python/modsupport.c @@ -712,3 +712,23 @@ PyModule_AddType(PyObject *module, PyTypeObject *type) return PyModule_AddObjectRef(module, name, (PyObject *)type); } + +int +PyModule_AddTypeFromSpec(PyObject *module, PyType_Spec *spec, PyObject *bases, PyTypeObject **rtype) +{ + PyTypeObject *type; + + type = (PyTypeObject *)PyType_FromModuleAndSpec(module, spec, bases); + /* steal ref to bases */ + Py_XDECREF(bases); + if (type == NULL) { + return -1; + } + if (PyModule_AddType(module, type) < 0) { + return -1; + } + if (rtype != NULL) { + *rtype = type; + } + return 0; +} From a1c824032ef245c0d5d8590b27305d210995cbcf Mon Sep 17 00:00:00 2001 From: Christian Heimes Date: Sun, 15 Nov 2020 22:52:40 +0100 Subject: [PATCH 03/13] PyModule_AddNew* helpers Add helpers to create new type/exception and add it to the module dict in one call. Signed-off-by: Christian Heimes --- Include/modsupport.h | 6 ++++- Modules/_hashopenssl.c | 23 +++++++++++-------- Python/modsupport.c | 52 +++++++++++++++++++++++++++++++++++------- 3 files changed, 62 insertions(+), 19 deletions(-) diff --git a/Include/modsupport.h b/Include/modsupport.h index 927206da1b6555..67a48d4e93b0de 100644 --- a/Include/modsupport.h +++ b/Include/modsupport.h @@ -156,7 +156,11 @@ PyAPI_FUNC(int) PyModule_AddType(PyObject *module, PyTypeObject *type); #if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03100000 /* New in 3.9 */ -PyAPI_FUNC(int) PyModule_AddTypeFromSpec(PyObject *module, PyType_Spec *spec, PyObject *bases, PyTypeObject **rtype); +PyAPI_FUNC(PyTypeObject *) PyModule_AddNewTypeFromSpec( + PyObject *module, PyType_Spec *spec, PyObject *base); +PyAPI_FUNC(PyObject *) PyModule_AddNewException( + PyObject *module, const char *name, const char *doc, + PyObject *base, PyObject *dict); #endif #if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03050000 diff --git a/Modules/_hashopenssl.c b/Modules/_hashopenssl.c index 070994b7cc3342..c98fa82b2901b6 100644 --- a/Modules/_hashopenssl.c +++ b/Modules/_hashopenssl.c @@ -2023,8 +2023,11 @@ hashlib_free(void *m) static int hashlib_init_evptype(PyObject *module) { - return PyModule_AddTypeFromSpec( - module, &EVPtype_spec, NULL, &(get_hashlib_state(module)->EVPtype)); + _hashlibstate *state = get_hashlib_state(module); + + state->EVPtype = PyModule_AddNewTypeFromSpec( + module, &EVPtype_spec, NULL); + return state->EVPtype == NULL ? -1 : 0; } static int @@ -2036,12 +2039,9 @@ hashlib_init_evpxoftype(PyObject *module) if (state->EVPtype == NULL) { return -1; } - bases = PyTuple_Pack(1, state->EVPtype); - if (bases == NULL) { - return -1; - } - return PyModule_AddTypeFromSpec( - module, &EVPXOFtype_spec, state->EVPtype, &(state->EVPXOFtype)); + state->EVPXOFtype = PyModule_AddNewTypeFromSpec( + module, &EVPXOFtype_spec, (PyObject *)state->EVPtype); + return state->EVPXOFtype == NULL ? -1 : 0; #endif return 0; } @@ -2049,8 +2049,11 @@ hashlib_init_evpxoftype(PyObject *module) static int hashlib_init_hmactype(PyObject *module) { - return PyModule_AddTypeFromSpec( - module, &HMACtype_spec, NULL, &(get_hashlib_state(module)->HMACtype)); + _hashlibstate *state = get_hashlib_state(module); + + state->HMACtype = PyModule_AddNewTypeFromSpec( + module, &HMACtype_spec, NULL); + return state->HMACtype == NULL ? -1 : 0; } static int diff --git a/Python/modsupport.c b/Python/modsupport.c index c47b9a1c70440f..22f281440287d1 100644 --- a/Python/modsupport.c +++ b/Python/modsupport.c @@ -713,22 +713,58 @@ PyModule_AddType(PyObject *module, PyTypeObject *type) return PyModule_AddObjectRef(module, name, (PyObject *)type); } -int -PyModule_AddTypeFromSpec(PyObject *module, PyType_Spec *spec, PyObject *bases, PyTypeObject **rtype) +PyTypeObject * +PyModule_AddNewTypeFromSpec(PyObject *module, PyType_Spec *spec, + PyObject *base) { PyTypeObject *type; + PyObject *bases; + + /* Support single, optional type like PyErr_NewException() */ + if (base == NULL) { + bases = NULL; + } + else if (PyTuple_Check(base)) { + bases = base; + Py_INCREF(bases); + } else { + bases = PyTuple_Pack(1, base); + if (bases == NULL) + return NULL; + } type = (PyTypeObject *)PyType_FromModuleAndSpec(module, spec, bases); - /* steal ref to bases */ Py_XDECREF(bases); if (type == NULL) { - return -1; + return NULL; } + if (PyModule_AddType(module, type) < 0) { - return -1; + Py_DECREF(type); + return NULL; } - if (rtype != NULL) { - *rtype = type; + return type; +} + +PyObject * +PyModule_AddNewException(PyObject *module, const char *name, const char *doc, + PyObject *base, PyObject *dict) +{ + PyObject *exc = PyErr_NewExceptionWithDoc(name, doc, base, dict); + if (exc == NULL) { + return NULL; } - return 0; + + const char *shortname = strrchr(name, '.'); + if (shortname == NULL) { + shortname = name; + } + else { + shortname++; + } + if (PyModule_AddObjectRef(module, shortname, exc) < 0) { + Py_DECREF(exc); + return NULL; + } + return exc; } From a277939afe1038956ea4e9bde20fc3be89e0b69d Mon Sep 17 00:00:00 2001 From: Christian Heimes Date: Mon, 16 Nov 2020 11:19:10 +0100 Subject: [PATCH 04/13] Rename new API to PyModuleConst_ Signed-off-by: Christian Heimes --- Include/moduleobject.h | 55 ++++++++++++++++++++++++------------------ Modules/mathmodule.c | 12 ++++----- Modules/posixmodule.c | 54 ++++++++++++++++++++--------------------- Objects/moduleobject.c | 22 ++++++++--------- 4 files changed, 76 insertions(+), 67 deletions(-) diff --git a/Include/moduleobject.h b/Include/moduleobject.h index d0f3e2be07ceb6..2f32a5a3da2bb8 100644 --- a/Include/moduleobject.h +++ b/Include/moduleobject.h @@ -72,37 +72,46 @@ typedef struct PyModuleDef_Slot{ #endif /* New in 3.5 */ -struct PyModuleConstants_Def; +struct PyModuleConst_Def; #if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03100000 /* New in 3.10 */ -#define Py_mc_none 1 -#define Py_mc_long 2 -#define Py_mc_bool 3 -#define Py_mc_double 4 -#define Py_mc_string 5 -#define Py_mc_call 6 -#define Py_mc_type 7 - -typedef struct PyModuleConstants_Def { +enum PyModuleConst_type { + PyModuleConst_none_type = 1, + PyModuleConst_long_type = 2, + PyModuleConst_bool_type = 3, + PyModuleConst_double_type = 4, + PyModuleConst_string_type = 5, + PyModuleConst_call_type = 6, +}; + +typedef struct PyModuleConst_Def { const char *name; - int type; + enum PyModuleConst_type type; union { const char *m_str; long m_long; double m_double; PyObject* (*m_call)(void); } value; -} PyModuleConstants_Def; - -#define PyMC_None(name) {(name), Py_mc_none, {.m_long=0}} -#define PyMC_Long(name, value) {(name), Py_mc_long, {.m_long=(value)}} -#define PyMC_Bool(name, value) {(name), Py_mc_bool, {.m_long=(value)}} -#define PyMC_Double(name, value) {(name), Py_mc_double, {.m_double=(value)}} -#define PyMC_String(name, value) {(name), Py_mc_string, {.m_string=(value)}} -#define PyMC_Call(name, value) {(name), Py_mc_call, {.m_call=(value)}} - -#define PyMC_LongMacro(m) PyMC_Long(#m, m) -#define PyMC_StringMacro(m) PyMC_String(#m, m) +} PyModuleConst_Def; + +PyAPI_FUNC(int) PyModule_AddConstants(PyObject *, PyModuleConst_Def *); + +#define PyModuleConst_None(name) \ + {(name), PyModuleConst_none_type, {.m_long=0}} +#define PyModuleConst_Long(name, value) \ + {(name), PyModuleConst_long_type, {.m_long=(value)}} +#define PyModuleConst_Bool(name, value) \ + {(name), PyModuleConst_bool_type, {.m_long=(value)}} +#define PyModuleConst_Double(name, value) \ + {(name), PyModuleConst_double_type, {.m_double=(value)}} +#define PyModuleConst_String(name, value) \ + {(name), PyModuleConst_string_type, {.m_string=(value)}} +#define PyModuleConst_Call(name, value) \ + {(name), PyModuleConst_call_type, {.m_call=(value)}} + +#define PyModuleConst_LongMacro(m) PyModuleConst_Long(#m, m) +#define PyModuleConst_StringMacro(m) PyModuleConst_String(#m, m) #endif /* New in 3.10 */ @@ -116,7 +125,7 @@ typedef struct PyModuleDef{ traverseproc m_traverse; inquiry m_clear; freefunc m_free; - struct PyModuleConstants_Def* m_constants; + struct PyModuleConst_Def* m_constants; } PyModuleDef; diff --git a/Modules/mathmodule.c b/Modules/mathmodule.c index fe8e3816bf4c77..83ced7d2a5fa94 100644 --- a/Modules/mathmodule.c +++ b/Modules/mathmodule.c @@ -3583,14 +3583,14 @@ static PyMethodDef math_methods[] = { {NULL, NULL} /* sentinel */ }; -static PyModuleConstants_Def math_constants[] = { - PyMC_Double("pi", Py_MATH_PI), - PyMC_Double("e", Py_MATH_E), +static PyModuleConst_Def math_constants[] = { + PyModuleConst_Double("pi", Py_MATH_PI), + PyModuleConst_Double("e", Py_MATH_E), // 2pi - PyMC_Double("tau", Py_MATH_TAU), - PyMC_Call("inf", m_inf_o), + PyModuleConst_Double("tau", Py_MATH_TAU), + PyModuleConst_Call("inf", m_inf_o), #if !defined(PY_NO_SHORT_FLOAT_REPR) || defined(Py_NAN) - PyMC_Call("nan", m_nan_o), + PyModuleConst_Call("nan", m_nan_o), #endif {NULL, 0}, }; diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index bca06e67e6d702..2f81c295cd4ce9 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -15687,84 +15687,84 @@ posixmodule_exec(PyObject *m) return 0; } -static PyModuleConstants_Def _posix_constants[] = { +static PyModuleConst_Def _posix_constants[] = { #ifdef F_OK - PyMC_LongMacro(F_OK), + PyModuleConst_LongMacro(F_OK), #endif #ifdef R_OK - PyMC_LongMacro(R_OK), + PyModuleConst_LongMacro(R_OK), #endif #ifdef W_OK - PyMC_LongMacro(W_OK), + PyModuleConst_LongMacro(W_OK), #endif #ifdef X_OK - PyMC_LongMacro(X_OK), + PyModuleConst_LongMacro(X_OK), #endif #ifdef NGROUPS_MAX - PyMC_LongMacro(NGROUPS_MAX), + PyModuleConst_LongMacro(NGROUPS_MAX), #endif #ifdef TMP_MAX - PyMC_LongMacro(TMP_MAX), + PyModuleConst_LongMacro(TMP_MAX), #endif #ifdef WCONTINUED - PyMC_LongMacro(WCONTINUED), + PyModuleConst_LongMacro(WCONTINUED), #endif #ifdef WNOHANG - PyMC_LongMacro(WNOHANG), + PyModuleConst_LongMacro(WNOHANG), #endif #ifdef WUNTRACED - PyMC_LongMacro(WUNTRACED), + PyModuleConst_LongMacro(WUNTRACED), #endif #ifdef O_RDONLY - PyMC_LongMacro(O_RDONLY), + PyModuleConst_LongMacro(O_RDONLY), #endif #ifdef O_WRONLY - PyMC_LongMacro(O_WRONLY), + PyModuleConst_LongMacro(O_WRONLY), #endif #ifdef O_RDWR - PyMC_LongMacro(O_RDWR), + PyModuleConst_LongMacro(O_RDWR), #endif #ifdef O_NDELAY - PyMC_LongMacro(O_NDELAY), + PyModuleConst_LongMacro(O_NDELAY), #endif #ifdef O_NONBLOCK - PyMC_LongMacro(O_NONBLOCK), + PyModuleConst_LongMacro(O_NONBLOCK), #endif #ifdef O_APPEND - PyMC_LongMacro(O_APPEND), + PyModuleConst_LongMacro(O_APPEND), #endif #ifdef O_DSYNC - PyMC_LongMacro(O_DSYNC), + PyModuleConst_LongMacro(O_DSYNC), #endif #ifdef O_RSYNC - PyMC_LongMacro(O_RSYNC), + PyModuleConst_LongMacro(O_RSYNC), #endif #ifdef O_SYNC - PyMC_LongMacro(O_SYNC), + PyModuleConst_LongMacro(O_SYNC), #endif #ifdef O_NOCTTY - PyMC_LongMacro(O_NOCTTY), + PyModuleConst_LongMacro(O_NOCTTY), #endif #ifdef O_CREAT - PyMC_LongMacro(O_CREAT), + PyModuleConst_LongMacro(O_CREAT), #endif #ifdef O_EXCL - PyMC_LongMacro(O_EXCL), + PyModuleConst_LongMacro(O_EXCL), #endif #ifdef O_TRUNC - PyMC_LongMacro(O_TRUNC), + PyModuleConst_LongMacro(O_TRUNC), #endif #ifdef O_BINARY - PyMC_LongMacro(O_BINARY), + PyModuleConst_LongMacro(O_BINARY), #endif #ifdef O_TEXT - PyMC_LongMacro(O_TEXT), + PyModuleConst_LongMacro(O_TEXT), #endif #ifdef O_XATTR - PyMC_LongMacro(O_XATTR), + PyModuleConst_LongMacro(O_XATTR), #endif #ifdef O_LARGEFILE - PyMC_LongMacro(O_LARGEFILE), + PyModuleConst_LongMacro(O_LARGEFILE), #endif {NULL, 0}, }; diff --git a/Objects/moduleobject.c b/Objects/moduleobject.c index ced49032f11cba..d560fa13932bda 100644 --- a/Objects/moduleobject.c +++ b/Objects/moduleobject.c @@ -175,11 +175,11 @@ _add_methods_to_object(PyObject *module, PyObject *name, PyMethodDef *functions) return 0; } -static int -module_add_constants(PyObject *module, PyModuleConstants_Def *def) +int +PyModule_AddConstants(PyObject *module, PyModuleConst_Def *def) { PyObject *dict; - PyModuleConstants_Def *cur_def; + PyModuleConst_Def *cur_def; PyObject *v; int res; @@ -190,23 +190,23 @@ module_add_constants(PyObject *module, PyModuleConstants_Def *def) for (cur_def = def; cur_def && cur_def->name; cur_def++) { switch(cur_def->type) { - case Py_mc_none: + case PyModuleConst_none_type: v = Py_None; Py_INCREF(v); break; - case Py_mc_long: + case PyModuleConst_long_type: v = PyLong_FromLong(cur_def->value.m_long); break; - case Py_mc_bool: + case PyModuleConst_bool_type: v = PyBool_FromLong(cur_def->value.m_long); break; - case Py_mc_double: + case PyModuleConst_double_type: v = PyFloat_FromDouble(cur_def->value.m_double); break; - case Py_mc_string: + case PyModuleConst_string_type: v = PyUnicode_FromString(cur_def->value.m_str); break; - case Py_mc_call: + case PyModuleConst_call_type: v = cur_def->value.m_call(); break; default: @@ -300,7 +300,7 @@ _PyModule_CreateInitialized(struct PyModuleDef* module, int module_api_version) } } if (module->m_constants != NULL) { - if (module_add_constants((PyObject *) m, module->m_constants) != 0) { + if (PyModule_AddConstants((PyObject *) m, module->m_constants) != 0) { Py_DECREF(m); return NULL; } @@ -425,7 +425,7 @@ PyModule_FromDefAndSpec2(struct PyModuleDef* def, PyObject *spec, int module_api } if (def->m_constants != NULL) { - if (module_add_constants((PyObject *) m, def->m_constants) != 0) { + if (PyModule_AddConstants(m, def->m_constants) != 0) { Py_DECREF(m); return NULL; } From 22e4f7f12d5f186a9be4b5444963ebff7b583295 Mon Sep 17 00:00:00 2001 From: Christian Heimes Date: Mon, 16 Nov 2020 12:05:54 +0100 Subject: [PATCH 05/13] Use Py_mod_constants instead of PyModuleDef.m_constants --- Include/moduleobject.h | 7 +++++-- Modules/mathmodule.c | 7 ++++++- Modules/posixmodule.c | 2 +- Objects/moduleobject.c | 19 ++++++------------- 4 files changed, 18 insertions(+), 17 deletions(-) diff --git a/Include/moduleobject.h b/Include/moduleobject.h index 2f32a5a3da2bb8..06bc57daa0cb99 100644 --- a/Include/moduleobject.h +++ b/Include/moduleobject.h @@ -66,8 +66,12 @@ typedef struct PyModuleDef_Slot{ #define Py_mod_create 1 #define Py_mod_exec 2 +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03100000 +#define Py_mod_constants 3 +#endif + #ifndef Py_LIMITED_API -#define _Py_mod_LAST_SLOT 2 +#define _Py_mod_LAST_SLOT 3 #endif #endif /* New in 3.5 */ @@ -125,7 +129,6 @@ typedef struct PyModuleDef{ traverseproc m_traverse; inquiry m_clear; freefunc m_free; - struct PyModuleConst_Def* m_constants; } PyModuleDef; diff --git a/Modules/mathmodule.c b/Modules/mathmodule.c index 83ced7d2a5fa94..3e3ea8e8bdc49b 100644 --- a/Modules/mathmodule.c +++ b/Modules/mathmodule.c @@ -3599,13 +3599,18 @@ PyDoc_STRVAR(module_doc, "This module provides access to the mathematical functions\n" "defined by the C standard."); +static PyModuleDef_Slot math_slots[] = { + {Py_mod_constants, math_constants}, + {0, NULL} +}; + static struct PyModuleDef mathmodule = { PyModuleDef_HEAD_INIT, .m_name = "math", .m_doc = module_doc, .m_size = 0, .m_methods = math_methods, - .m_constants = math_constants, + .m_slots = math_slots, }; PyMODINIT_FUNC diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index 2f81c295cd4ce9..baefa91b528e0f 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -15772,6 +15772,7 @@ static PyModuleConst_Def _posix_constants[] = { static PyModuleDef_Slot posixmodile_slots[] = { {Py_mod_exec, posixmodule_exec}, + {Py_mod_constants, _posix_constants}, {0, NULL} }; @@ -15785,7 +15786,6 @@ static struct PyModuleDef posixmodule = { .m_traverse = _posix_traverse, .m_clear = _posix_clear, .m_free = _posix_free, - .m_constants = _posix_constants, }; PyMODINIT_FUNC diff --git a/Objects/moduleobject.c b/Objects/moduleobject.c index d560fa13932bda..347a3c76c0f79c 100644 --- a/Objects/moduleobject.c +++ b/Objects/moduleobject.c @@ -299,12 +299,6 @@ _PyModule_CreateInitialized(struct PyModuleDef* module, int module_api_version) return NULL; } } - if (module->m_constants != NULL) { - if (PyModule_AddConstants((PyObject *) m, module->m_constants) != 0) { - Py_DECREF(m); - return NULL; - } - } m->md_def = module; return (PyObject*)m; } @@ -424,13 +418,6 @@ PyModule_FromDefAndSpec2(struct PyModuleDef* def, PyObject *spec, int module_api } } - if (def->m_constants != NULL) { - if (PyModule_AddConstants(m, def->m_constants) != 0) { - Py_DECREF(m); - return NULL; - } - } - Py_DECREF(nameobj); return m; @@ -494,6 +481,12 @@ PyModule_ExecDef(PyObject *module, PyModuleDef *def) return -1; } break; + case Py_mod_constants: + ret = PyModule_AddConstants(module, (PyModuleConst_Def *)cur_slot->value); + if (ret == -1) { + return -1; + } + break; default: PyErr_Format( PyExc_SystemError, From 31f818933ae1fe3820dfa5bb551ad73848f596f5 Mon Sep 17 00:00:00 2001 From: Christian Heimes Date: Mon, 16 Nov 2020 13:41:08 +0100 Subject: [PATCH 06/13] Revert "Use Py_mod_constants instead of PyModuleDef.m_constants" This reverts commit 042e0999ed5ecf88de63de1140d968ab14745e3f. --- Include/moduleobject.h | 7 ++----- Modules/mathmodule.c | 7 +------ Modules/posixmodule.c | 2 +- Objects/moduleobject.c | 19 +++++++++++++------ 4 files changed, 17 insertions(+), 18 deletions(-) diff --git a/Include/moduleobject.h b/Include/moduleobject.h index 06bc57daa0cb99..2f32a5a3da2bb8 100644 --- a/Include/moduleobject.h +++ b/Include/moduleobject.h @@ -66,12 +66,8 @@ typedef struct PyModuleDef_Slot{ #define Py_mod_create 1 #define Py_mod_exec 2 -#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03100000 -#define Py_mod_constants 3 -#endif - #ifndef Py_LIMITED_API -#define _Py_mod_LAST_SLOT 3 +#define _Py_mod_LAST_SLOT 2 #endif #endif /* New in 3.5 */ @@ -129,6 +125,7 @@ typedef struct PyModuleDef{ traverseproc m_traverse; inquiry m_clear; freefunc m_free; + struct PyModuleConst_Def* m_constants; } PyModuleDef; diff --git a/Modules/mathmodule.c b/Modules/mathmodule.c index 3e3ea8e8bdc49b..83ced7d2a5fa94 100644 --- a/Modules/mathmodule.c +++ b/Modules/mathmodule.c @@ -3599,18 +3599,13 @@ PyDoc_STRVAR(module_doc, "This module provides access to the mathematical functions\n" "defined by the C standard."); -static PyModuleDef_Slot math_slots[] = { - {Py_mod_constants, math_constants}, - {0, NULL} -}; - static struct PyModuleDef mathmodule = { PyModuleDef_HEAD_INIT, .m_name = "math", .m_doc = module_doc, .m_size = 0, .m_methods = math_methods, - .m_slots = math_slots, + .m_constants = math_constants, }; PyMODINIT_FUNC diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index baefa91b528e0f..2f81c295cd4ce9 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -15772,7 +15772,6 @@ static PyModuleConst_Def _posix_constants[] = { static PyModuleDef_Slot posixmodile_slots[] = { {Py_mod_exec, posixmodule_exec}, - {Py_mod_constants, _posix_constants}, {0, NULL} }; @@ -15786,6 +15785,7 @@ static struct PyModuleDef posixmodule = { .m_traverse = _posix_traverse, .m_clear = _posix_clear, .m_free = _posix_free, + .m_constants = _posix_constants, }; PyMODINIT_FUNC diff --git a/Objects/moduleobject.c b/Objects/moduleobject.c index 347a3c76c0f79c..d560fa13932bda 100644 --- a/Objects/moduleobject.c +++ b/Objects/moduleobject.c @@ -299,6 +299,12 @@ _PyModule_CreateInitialized(struct PyModuleDef* module, int module_api_version) return NULL; } } + if (module->m_constants != NULL) { + if (PyModule_AddConstants((PyObject *) m, module->m_constants) != 0) { + Py_DECREF(m); + return NULL; + } + } m->md_def = module; return (PyObject*)m; } @@ -418,6 +424,13 @@ PyModule_FromDefAndSpec2(struct PyModuleDef* def, PyObject *spec, int module_api } } + if (def->m_constants != NULL) { + if (PyModule_AddConstants(m, def->m_constants) != 0) { + Py_DECREF(m); + return NULL; + } + } + Py_DECREF(nameobj); return m; @@ -481,12 +494,6 @@ PyModule_ExecDef(PyObject *module, PyModuleDef *def) return -1; } break; - case Py_mod_constants: - ret = PyModule_AddConstants(module, (PyModuleConst_Def *)cur_slot->value); - if (ret == -1) { - return -1; - } - break; default: PyErr_Format( PyExc_SystemError, From 366e810efce0a95c40bf089d2068ee64ebc8feeb Mon Sep 17 00:00:00 2001 From: Christian Heimes Date: Mon, 16 Nov 2020 15:28:43 +0100 Subject: [PATCH 07/13] Remove PyModuleDef.m_constants again --- Doc/c-api/module.rst | 137 +++++++++++++++++++++++++++++++++++++++++ Include/moduleobject.h | 1 - Modules/mathmodule.c | 13 +++- Modules/posixmodule.c | 10 ++- Objects/moduleobject.c | 13 ---- 5 files changed, 157 insertions(+), 17 deletions(-) diff --git a/Doc/c-api/module.rst b/Doc/c-api/module.rst index a2541afb685c30..7b9d8428c6dd57 100644 --- a/Doc/c-api/module.rst +++ b/Doc/c-api/module.rst @@ -571,6 +571,143 @@ state: .. versionadded:: 3.9 +.. c:function:: PyTypeeObject * PyModule_AddNewTypeFromSpec(PyObject *module, PyType_Spec *spec, PyObject *base) + + Initialize a new type and add it to *module*. + The function is equivalent to :c:func:`PyType_FromModuleAndSpec` followed + by :c:func:`PyModule_AddType`. *base* must be either ``NULL``, a single + type object, or a tuple of types. + Return ``NULL`` on error; otherwise a borrowed reference to a + ``PyTypeObject *``, which can be assigned to a module state object. + + .. versionadded:: 3.10 + +.. c:function:: PyObject * PyModule_AddNewException(PyObject *module, const char *name, const char *doc, PyObject *base, PyObject *dict) + + Create a new exception and add it to *module*. + The function is equivalent to :c:func:`PyErr_NewExceptionWithDoc` followed + by :c:func:`PyModule_AddObjectRef`. The name of the exception object is + taken from the last component of *name* after dot. + Return ``NULL`` on error; otherwise a borrowed reference to a + ``PyObject *``, which can be assigned to a module state object. + + .. versionadded:: 3.10 + +.. c:function:: int PyModule_AddConstants(PyObject *module, PyModuleConst_Def *def) + + Initialize module constants from a PyModuleConst_Def array. The function + provides a convenient way to declare module-level constants. + Return ``-1`` on error, ``0`` on success. + + Example:: + + static PyObject* + example_call(void *) + { + return PyBytes_FromString("23"); + } + + #define EXAMPLE_INT 23 + #define EXAMPLE_STRING "world" + + static PyModuleConst_Def example_constants[] = { + PyModuleConst_None("none_value"), + PyModuleConst_Long("integer", 42), + PyModuleConst_Bool("false_value", 0), + PyModuleConst_Bool("true_value", 1), + #ifdef Py_MATH_PI + PyModuleConst_Double("pi", Py_MATH_PI), + #endif + PyModuleConst_String("somestring", "Hello"), + PyModuleConst_Call("call", example_call), + PyModuleConst_LongMacro(EXAMPLE_INT), + PyModuleConst_StringMacro(EXAMPLE_STRING), + {NULL}, + } + + static int + example_init_constants(PyObject *module) + { + return PyModule_AddConstants(module, posix_constants); + } + + static PyModuleDef_Slot example_slots[] = { + {Py_mod_exec, example_init_constants}, + {0, NULL} + }; + + +.. c:type:: PyModuleConst_Def + + The values for *type* and the definition of the *value* union are + internal implementation details. Use any of the ``PyModuleConst_`` macros + to define entries. The array must be terminated by an entry with name + set to ``NULL``. + + .. c:member:: const char *name + + Attribute name. + + .. c:member:: int type + + Attribute type. + + .. c:member:: union value + + Value of the module constant definition, whose meaning depends on + *type*. + + .. versionadded:: 3.10 + +.. c:macro:: PyModuleConst_None(name) + + Add an entry for None. + + .. versionadded:: 3.10 + +.. c:macro:: PyModuleConst_Long(name, value) + + Add an entry for an int constant. + + .. versionadded:: 3.10 + +.. c:macro:: PyModuleConst_Bool(name, value) + + Add an entry for a bool constant. + + .. versionadded:: 3.10 + +.. c:macro:: PyModuleConst_Double(name, value) + + Add an entry for a float constant. + + .. versionadded:: 3.10 + +.. c:macro:: PyModuleConst_String(name, value) + + Add an entry for a string constant. + + .. versionadded:: 3.10 + +.. c:macro:: PyModuleConst_Call(name, c_function) + + Add an entry for a constant as returned by *c_function*. + + .. versionadded:: 3.10 + +.. c:macro:: PyModuleConst_LongMacro(macro) + + Add an entry for an int constant. The name and the value are taken from + *macro*. + + .. versionadded:: 3.10 + +.. c:macro:: PyModuleConst_StringMacro(macro) + + Add an entry for a string constant. The name and the value are taken from + *macro*. + + .. versionadded:: 3.10 Module lookup ^^^^^^^^^^^^^ diff --git a/Include/moduleobject.h b/Include/moduleobject.h index 2f32a5a3da2bb8..941e7f4e18c890 100644 --- a/Include/moduleobject.h +++ b/Include/moduleobject.h @@ -125,7 +125,6 @@ typedef struct PyModuleDef{ traverseproc m_traverse; inquiry m_clear; freefunc m_free; - struct PyModuleConst_Def* m_constants; } PyModuleDef; diff --git a/Modules/mathmodule.c b/Modules/mathmodule.c index 83ced7d2a5fa94..d1186b4ef6cac5 100644 --- a/Modules/mathmodule.c +++ b/Modules/mathmodule.c @@ -3595,6 +3595,17 @@ static PyModuleConst_Def math_constants[] = { {NULL, 0}, }; +static int +math_init_constants(PyObject *module) +{ + return PyModule_AddConstants(module, math_constants); +} + +static PyModuleDef_Slot math_slots[] = { + {Py_mod_exec, math_init_constants}, + {0, NULL} +}; + PyDoc_STRVAR(module_doc, "This module provides access to the mathematical functions\n" "defined by the C standard."); @@ -3605,7 +3616,7 @@ static struct PyModuleDef mathmodule = { .m_doc = module_doc, .m_size = 0, .m_methods = math_methods, - .m_constants = math_constants, + .m_slots = math_slots, }; PyMODINIT_FUNC diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index 2f81c295cd4ce9..bd17c9fccb97c5 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -15687,7 +15687,7 @@ posixmodule_exec(PyObject *m) return 0; } -static PyModuleConst_Def _posix_constants[] = { +static PyModuleConst_Def posix_constants[] = { #ifdef F_OK PyModuleConst_LongMacro(F_OK), #endif @@ -15769,9 +15769,16 @@ static PyModuleConst_Def _posix_constants[] = { {NULL, 0}, }; +static int +posixmodule_init_constants(PyObject *module) +{ + return PyModule_AddConstants(module, posix_constants); +} + static PyModuleDef_Slot posixmodile_slots[] = { {Py_mod_exec, posixmodule_exec}, + {Py_mod_exec, posixmodule_init_constants}, {0, NULL} }; @@ -15785,7 +15792,6 @@ static struct PyModuleDef posixmodule = { .m_traverse = _posix_traverse, .m_clear = _posix_clear, .m_free = _posix_free, - .m_constants = _posix_constants, }; PyMODINIT_FUNC diff --git a/Objects/moduleobject.c b/Objects/moduleobject.c index d560fa13932bda..e44d34d3529c21 100644 --- a/Objects/moduleobject.c +++ b/Objects/moduleobject.c @@ -299,12 +299,6 @@ _PyModule_CreateInitialized(struct PyModuleDef* module, int module_api_version) return NULL; } } - if (module->m_constants != NULL) { - if (PyModule_AddConstants((PyObject *) m, module->m_constants) != 0) { - Py_DECREF(m); - return NULL; - } - } m->md_def = module; return (PyObject*)m; } @@ -424,13 +418,6 @@ PyModule_FromDefAndSpec2(struct PyModuleDef* def, PyObject *spec, int module_api } } - if (def->m_constants != NULL) { - if (PyModule_AddConstants(m, def->m_constants) != 0) { - Py_DECREF(m); - return NULL; - } - } - Py_DECREF(nameobj); return m; From bb41d82e4e9e2a88157bf148e97cd3fa364a795f Mon Sep 17 00:00:00 2001 From: Christian Heimes Date: Mon, 16 Nov 2020 20:31:17 +0100 Subject: [PATCH 08/13] bpo-42376: New C-APIs to simplify module attribute declaration --- Doc/c-api/module.rst | 4 ++-- Doc/data/refcounts.dat | 16 ++++++++++++++++ .../2020-11-16-20-29-59.bpo-42376.vO9Tvu.rst | 3 +++ 3 files changed, 21 insertions(+), 2 deletions(-) create mode 100644 Misc/NEWS.d/next/C API/2020-11-16-20-29-59.bpo-42376.vO9Tvu.rst diff --git a/Doc/c-api/module.rst b/Doc/c-api/module.rst index 7b9d8428c6dd57..f1c67fd6c7bad4 100644 --- a/Doc/c-api/module.rst +++ b/Doc/c-api/module.rst @@ -571,7 +571,7 @@ state: .. versionadded:: 3.9 -.. c:function:: PyTypeeObject * PyModule_AddNewTypeFromSpec(PyObject *module, PyType_Spec *spec, PyObject *base) +.. c:function:: PyTypeObject * PyModule_AddNewTypeFromSpec(PyObject *module, PyType_Spec *spec, PyObject *base) Initialize a new type and add it to *module*. The function is equivalent to :c:func:`PyType_FromModuleAndSpec` followed @@ -652,7 +652,7 @@ state: Attribute type. - .. c:member:: union value + .. c:member:: void *value Value of the module constant definition, whose meaning depends on *type*. diff --git a/Doc/data/refcounts.dat b/Doc/data/refcounts.dat index 505f1203dd1bdd..c4d041a2ac4c04 100644 --- a/Doc/data/refcounts.dat +++ b/Doc/data/refcounts.dat @@ -1325,6 +1325,10 @@ PyMethod_New:PyObject*:class:0: PyMethod_Self:PyObject*::0: PyMethod_Self:PyObject*:im:0: +PyModule_AddConstants:int::: +PyModule_AddConstants:PyObject*:module:0: +PyModule_AddConstants:PyModuleConst_Def*:def:: + PyModule_AddFunctions:int::: PyModule_AddFunctions:PyObject*:module:0: PyModule_AddFunctions:PyMethodDef*:functions:: @@ -1343,6 +1347,18 @@ PyModule_AddObject:PyObject*:module:0: PyModule_AddObject:const char*:name:: PyModule_AddObject:PyObject*:value:+1: +PyModule_AddNewException:PyObject*::+1: +PyModule_AddNewException:PyObject*:module:0: +PyModule_AddNewException:const char*:name:: +PyModule_AddNewException:const char*:doc:: +PyModule_AddNewException:PyObject*:base:0: +PyModule_AddNewException:PyObject*:dict:0: + +PyModule_AddNewTypeFromSpec:PyObject*::+1: +PyModule_AddNewTypeFromSpec:PyObject*:module:0: +PyModule_AddNewTypeFromSpec:PyType_spec*:spec:: +PyModule_AddNewTypeFromSpec:PyObject*:base:0: + PyModule_AddStringConstant:int::: PyModule_AddStringConstant:PyObject*:module:0: PyModule_AddStringConstant:const char*:name:: diff --git a/Misc/NEWS.d/next/C API/2020-11-16-20-29-59.bpo-42376.vO9Tvu.rst b/Misc/NEWS.d/next/C API/2020-11-16-20-29-59.bpo-42376.vO9Tvu.rst new file mode 100644 index 00000000000000..f28f78297ab948 --- /dev/null +++ b/Misc/NEWS.d/next/C API/2020-11-16-20-29-59.bpo-42376.vO9Tvu.rst @@ -0,0 +1,3 @@ +Add new functions :c:func:`PyModule_AddConstants`, +:c:func:`PyModule_AddNewTypeFromSpec`, :c:func:`PyModule_AddNewException` to +simplify the declaration of attribute in modules. From 751c560728b1e2f6559fd6c3c7f7be756f8dae1e Mon Sep 17 00:00:00 2001 From: Christian Heimes Date: Wed, 18 Nov 2020 18:17:54 +0100 Subject: [PATCH 09/13] ULong, private types, add module to call --- Doc/c-api/module.rst | 20 ++++++++++++++------ Include/moduleobject.h | 34 +++++++++++++++++++--------------- Modules/mathmodule.c | 4 ++-- Objects/moduleobject.c | 17 ++++++++++------- 4 files changed, 45 insertions(+), 30 deletions(-) diff --git a/Doc/c-api/module.rst b/Doc/c-api/module.rst index f1c67fd6c7bad4..194765812c1f5d 100644 --- a/Doc/c-api/module.rst +++ b/Doc/c-api/module.rst @@ -602,7 +602,7 @@ state: Example:: static PyObject* - example_call(void *) + example_call(PyObject *module) { return PyBytes_FromString("23"); } @@ -613,6 +613,7 @@ state: static PyModuleConst_Def example_constants[] = { PyModuleConst_None("none_value"), PyModuleConst_Long("integer", 42), + PyModuleConst_ULong("unsigned", 42UL), PyModuleConst_Bool("false_value", 0), PyModuleConst_Bool("true_value", 1), #ifdef Py_MATH_PI @@ -628,7 +629,7 @@ state: static int example_init_constants(PyObject *module) { - return PyModule_AddConstants(module, posix_constants); + return PyModule_AddConstants(module, example_constants); } static PyModuleDef_Slot example_slots[] = { @@ -667,13 +668,19 @@ state: .. c:macro:: PyModuleConst_Long(name, value) - Add an entry for an int constant. + Add an entry for an integer constant. + + .. versionadded:: 3.10 + +.. c:macro:: PyModuleConst_Long(name, value) + + Add an entry for an unsigned integer constant. .. versionadded:: 3.10 .. c:macro:: PyModuleConst_Bool(name, value) - Add an entry for a bool constant. + Add an entry for a bool constant. ``0`` is false, ``1`` is true. .. versionadded:: 3.10 @@ -689,9 +696,10 @@ state: .. versionadded:: 3.10 -.. c:macro:: PyModuleConst_Call(name, c_function) +.. c:macro:: PyModuleConst_Call(name, func) - Add an entry for a constant as returned by *c_function*. + Add an entry for a constant as returned by callback with signature + ``PyObject* (*func)(PyObject *module)``. .. versionadded:: 3.10 diff --git a/Include/moduleobject.h b/Include/moduleobject.h index 941e7f4e18c890..cbb04770eebc90 100644 --- a/Include/moduleobject.h +++ b/Include/moduleobject.h @@ -75,40 +75,44 @@ typedef struct PyModuleDef_Slot{ struct PyModuleConst_Def; #if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03100000 /* New in 3.10 */ -enum PyModuleConst_type { - PyModuleConst_none_type = 1, - PyModuleConst_long_type = 2, - PyModuleConst_bool_type = 3, - PyModuleConst_double_type = 4, - PyModuleConst_string_type = 5, - PyModuleConst_call_type = 6, +enum _PyModuleConst_type { + _PyModuleConst_none_type = 1, + _PyModuleConst_long_type = 2, + _PyModuleConst_ulong_type = 3, + _PyModuleConst_bool_type = 4, + _PyModuleConst_double_type = 5, + _PyModuleConst_string_type = 6, + _PyModuleConst_call_type = 7, }; typedef struct PyModuleConst_Def { const char *name; - enum PyModuleConst_type type; + enum _PyModuleConst_type type; union { const char *m_str; long m_long; + unsigned long m_ulong; double m_double; - PyObject* (*m_call)(void); + PyObject* (*m_call)(PyObject *module); } value; } PyModuleConst_Def; PyAPI_FUNC(int) PyModule_AddConstants(PyObject *, PyModuleConst_Def *); #define PyModuleConst_None(name) \ - {(name), PyModuleConst_none_type, {.m_long=0}} + {(name), _PyModuleConst_none_type, {.m_long=0}} #define PyModuleConst_Long(name, value) \ - {(name), PyModuleConst_long_type, {.m_long=(value)}} + {(name), _PyModuleConst_long_type, {.m_long=(value)}} +#define PyModuleConst_ULong(name, value) \ + {(name), _PyModuleConst_ulong_type, {.m_ulong=(value)}} #define PyModuleConst_Bool(name, value) \ - {(name), PyModuleConst_bool_type, {.m_long=(value)}} + {(name), _PyModuleConst_bool_type, {.m_long=(value)}} #define PyModuleConst_Double(name, value) \ - {(name), PyModuleConst_double_type, {.m_double=(value)}} + {(name), _PyModuleConst_double_type, {.m_double=(value)}} #define PyModuleConst_String(name, value) \ - {(name), PyModuleConst_string_type, {.m_string=(value)}} + {(name), _PyModuleConst_string_type, {.m_str=(value)}} #define PyModuleConst_Call(name, value) \ - {(name), PyModuleConst_call_type, {.m_call=(value)}} + {(name), _PyModuleConst_call_type, {.m_call=(value)}} #define PyModuleConst_LongMacro(m) PyModuleConst_Long(#m, m) #define PyModuleConst_StringMacro(m) PyModuleConst_String(#m, m) diff --git a/Modules/mathmodule.c b/Modules/mathmodule.c index d1186b4ef6cac5..d00adc6fb7333e 100644 --- a/Modules/mathmodule.c +++ b/Modules/mathmodule.c @@ -271,7 +271,7 @@ m_inf(void) } static PyObject* -m_inf_o(void) +m_inf_o(PyObject *module) { return PyFloat_FromDouble(m_inf()); } @@ -292,7 +292,7 @@ m_nan(void) } static PyObject* -m_nan_o(void) +m_nan_o(PyObject *module) { return PyFloat_FromDouble(m_nan()); } diff --git a/Objects/moduleobject.c b/Objects/moduleobject.c index e44d34d3529c21..a2f9b30e381999 100644 --- a/Objects/moduleobject.c +++ b/Objects/moduleobject.c @@ -190,24 +190,27 @@ PyModule_AddConstants(PyObject *module, PyModuleConst_Def *def) for (cur_def = def; cur_def && cur_def->name; cur_def++) { switch(cur_def->type) { - case PyModuleConst_none_type: + case _PyModuleConst_none_type: v = Py_None; Py_INCREF(v); break; - case PyModuleConst_long_type: + case _PyModuleConst_long_type: v = PyLong_FromLong(cur_def->value.m_long); break; - case PyModuleConst_bool_type: + case _PyModuleConst_ulong_type: + v = PyLong_FromUnsignedLong(cur_def->value.m_ulong); + break; + case _PyModuleConst_bool_type: v = PyBool_FromLong(cur_def->value.m_long); break; - case PyModuleConst_double_type: + case _PyModuleConst_double_type: v = PyFloat_FromDouble(cur_def->value.m_double); break; - case PyModuleConst_string_type: + case _PyModuleConst_string_type: v = PyUnicode_FromString(cur_def->value.m_str); break; - case PyModuleConst_call_type: - v = cur_def->value.m_call(); + case _PyModuleConst_call_type: + v = cur_def->value.m_call(module); break; default: v = NULL; From c34a4dfc4d56f947c7ae363df1df268988cb941b Mon Sep 17 00:00:00 2001 From: Christian Heimes Date: Wed, 18 Nov 2020 18:18:03 +0100 Subject: [PATCH 10/13] Add CAPI tests --- Lib/test/test_capi.py | 14 ++++++++++++++ Modules/_testcapimodule.c | 28 ++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/Lib/test/test_capi.py b/Lib/test/test_capi.py index 1b18bfad553007..cc62549d28df46 100644 --- a/Lib/test/test_capi.py +++ b/Lib/test/test_capi.py @@ -971,5 +971,19 @@ def test_state_access(self): increment_count(1, 2, 3) +class Test_PyModuleConst_Def(unittest.TestCase): + def test_constants(self): + self.assertIs(_testcapi.const_none, None) + self.assertEqual(_testcapi.const_int, 42) + self.assertEqual(_testcapi.const_uint, _testcapi.ULONG_MAX) + self.assertIs(_testcapi.const_true, True) + self.assertIs(_testcapi.const_false, False) + self.assertEqual(_testcapi.const_almost_tau, 6.2831) + self.assertEqual(_testcapi.const_str, "Hello") + self.assertEqual(_testcapi.const_call, b"23") + self.assertEqual(_testcapi.CONST_INT, 7) + self.assertEqual(_testcapi.CONST_STRING, "world") + + if __name__ == "__main__": unittest.main() diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c index db62aea421c806..8a47d76e72d8f8 100644 --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -7010,6 +7010,29 @@ static PyTypeObject ContainerNoGC_type = { .tp_new = ContainerNoGC_new, }; +static PyObject * +_testcapimodule_const_call(PyObject *module) +{ + return PyBytes_FromString("23"); +} + +#define CONST_INT 7 +#define CONST_STRING "world" + +static PyModuleConst_Def _testcapimodule_consts[] = { + PyModuleConst_None("const_none"), + PyModuleConst_Long("const_int", 42), + PyModuleConst_ULong("const_uint", ULONG_MAX), + PyModuleConst_Bool("const_false", 0), + PyModuleConst_Bool("const_true", 1), + PyModuleConst_Double("const_almost_tau", 6.2831), + PyModuleConst_String("const_str", "Hello"), + PyModuleConst_Call("const_call", _testcapimodule_const_call), + PyModuleConst_LongMacro(CONST_INT), + PyModuleConst_StringMacro(CONST_STRING), + {NULL}, +}; + static struct PyModuleDef _testcapimodule = { PyModuleDef_HEAD_INIT, @@ -7035,6 +7058,11 @@ PyInit__testcapi(void) if (m == NULL) return NULL; + if (PyModule_AddConstants(m, _testcapimodule_consts) < 0) { + Py_DECREF(m); + return NULL; + } + Py_SET_TYPE(&_HashInheritanceTester_Type, &PyType_Type); Py_SET_TYPE(&test_structmembersType, &PyType_Type); From 3e50f4489ea870c8be4a313852002c64257cc95e Mon Sep 17 00:00:00 2001 From: Christian Heimes Date: Wed, 18 Nov 2020 18:30:27 +0100 Subject: [PATCH 11/13] Typo --- Doc/c-api/module.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/c-api/module.rst b/Doc/c-api/module.rst index 194765812c1f5d..7b5cdf71f801a8 100644 --- a/Doc/c-api/module.rst +++ b/Doc/c-api/module.rst @@ -672,7 +672,7 @@ state: .. versionadded:: 3.10 -.. c:macro:: PyModuleConst_Long(name, value) +.. c:macro:: PyModuleConst_ULong(name, value) Add an entry for an unsigned integer constant. From 00236fed5d810d37397378510a3413c4541a822d Mon Sep 17 00:00:00 2001 From: Christian Heimes Date: Sun, 22 Nov 2020 14:27:06 +0100 Subject: [PATCH 12/13] Use single base class feature from bpo-42423 --- Modules/_ssl.c | 17 ++++------------- Python/modsupport.c | 17 +---------------- 2 files changed, 5 insertions(+), 29 deletions(-) diff --git a/Modules/_ssl.c b/Modules/_ssl.c index f441a16625bc76..c5eb0a4a7353a9 100644 --- a/Modules/_ssl.c +++ b/Modules/_ssl.c @@ -5459,39 +5459,30 @@ static PyMethodDef PySSL_methods[] = { static int sslmodule_init_types(PyObject *module) { - PySSLContext_Type = (PyTypeObject *)PyType_FromModuleAndSpec( + PySSLContext_Type = PyModule_AddNewTypeFromSpec( module, &PySSLContext_spec, NULL ); if (PySSLContext_Type == NULL) return -1; - PySSLSocket_Type = (PyTypeObject *)PyType_FromModuleAndSpec( + PySSLSocket_Type = PyModule_AddNewTypeFromSpec( module, &PySSLSocket_spec, NULL ); if (PySSLSocket_Type == NULL) return -1; - PySSLMemoryBIO_Type = (PyTypeObject *)PyType_FromModuleAndSpec( + PySSLMemoryBIO_Type = PyModule_AddNewTypeFromSpec( module, &PySSLMemoryBIO_spec, NULL ); if (PySSLMemoryBIO_Type == NULL) return -1; - PySSLSession_Type = (PyTypeObject *)PyType_FromModuleAndSpec( + PySSLSession_Type = PyModule_AddNewTypeFromSpec( module, &PySSLSession_spec, NULL ); if (PySSLSession_Type == NULL) return -1; - if (PyModule_AddType(module, PySSLContext_Type)) - return -1; - if (PyModule_AddType(module, PySSLSocket_Type)) - return -1; - if (PyModule_AddType(module, PySSLMemoryBIO_Type)) - return -1; - if (PyModule_AddType(module, PySSLSession_Type)) - return -1; - return 0; } diff --git a/Python/modsupport.c b/Python/modsupport.c index 22f281440287d1..0254055ed08a34 100644 --- a/Python/modsupport.c +++ b/Python/modsupport.c @@ -715,26 +715,11 @@ PyModule_AddType(PyObject *module, PyTypeObject *type) PyTypeObject * PyModule_AddNewTypeFromSpec(PyObject *module, PyType_Spec *spec, - PyObject *base) + PyObject *bases) { PyTypeObject *type; - PyObject *bases; - - /* Support single, optional type like PyErr_NewException() */ - if (base == NULL) { - bases = NULL; - } - else if (PyTuple_Check(base)) { - bases = base; - Py_INCREF(bases); - } else { - bases = PyTuple_Pack(1, base); - if (bases == NULL) - return NULL; - } type = (PyTypeObject *)PyType_FromModuleAndSpec(module, spec, bases); - Py_XDECREF(bases); if (type == NULL) { return NULL; } From 8458120b1f78c275a1382a0103698bbbc0d6f159 Mon Sep 17 00:00:00 2001 From: Christian Heimes Date: Sun, 22 Nov 2020 15:45:06 +0100 Subject: [PATCH 13/13] It's a strong ref --- Doc/c-api/module.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Doc/c-api/module.rst b/Doc/c-api/module.rst index 7b5cdf71f801a8..d43aa7f858be0c 100644 --- a/Doc/c-api/module.rst +++ b/Doc/c-api/module.rst @@ -577,8 +577,8 @@ state: The function is equivalent to :c:func:`PyType_FromModuleAndSpec` followed by :c:func:`PyModule_AddType`. *base* must be either ``NULL``, a single type object, or a tuple of types. - Return ``NULL`` on error; otherwise a borrowed reference to a - ``PyTypeObject *``, which can be assigned to a module state object. + Return ``NULL`` on error; otherwise a ``PyTypeObject *``, which can + be assigned to a module state object. .. versionadded:: 3.10 @@ -588,8 +588,8 @@ state: The function is equivalent to :c:func:`PyErr_NewExceptionWithDoc` followed by :c:func:`PyModule_AddObjectRef`. The name of the exception object is taken from the last component of *name* after dot. - Return ``NULL`` on error; otherwise a borrowed reference to a - ``PyObject *``, which can be assigned to a module state object. + Return ``NULL`` on error; otherwise ``PyObject *``, which can be assigned + to a module state object. .. versionadded:: 3.10