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 pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy