diff --git a/Doc/c-api/module.rst b/Doc/c-api/module.rst index a2541afb685c30..d43aa7f858be0c 100644 --- a/Doc/c-api/module.rst +++ b/Doc/c-api/module.rst @@ -571,6 +571,151 @@ state: .. versionadded:: 3.9 +.. 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 + 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 ``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 ``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(PyObject *module) + { + 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_ULong("unsigned", 42UL), + 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, example_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:: void *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 integer constant. + + .. versionadded:: 3.10 + +.. c:macro:: PyModuleConst_ULong(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. ``0`` is false, ``1`` is true. + + .. 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, func) + + Add an entry for a constant as returned by callback with signature + ``PyObject* (*func)(PyObject *module)``. + + .. 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/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/Include/modsupport.h b/Include/modsupport.h index f009d586bf6202..67a48d4e93b0de 100644 --- a/Include/modsupport.h +++ b/Include/modsupport.h @@ -154,6 +154,15 @@ 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(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 /* New in 3.5 */ PyAPI_FUNC(int) PyModule_SetDocString(PyObject *, const char *); diff --git a/Include/moduleobject.h b/Include/moduleobject.h index 49b116ca1c3587..cbb04770eebc90 100644 --- a/Include/moduleobject.h +++ b/Include/moduleobject.h @@ -72,6 +72,53 @@ typedef struct PyModuleDef_Slot{ #endif /* New in 3.5 */ +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_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; + union { + const char *m_str; + long m_long; + unsigned long m_ulong; + double m_double; + 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}} +#define PyModuleConst_Long(name, 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)}} +#define PyModuleConst_Double(name, value) \ + {(name), _PyModuleConst_double_type, {.m_double=(value)}} +#define PyModuleConst_String(name, value) \ + {(name), _PyModuleConst_string_type, {.m_str=(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 */ + typedef struct PyModuleDef{ PyModuleDef_Base m_base; const char* m_name; 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/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. diff --git a/Modules/_hashopenssl.c b/Modules/_hashopenssl.c index 870ee89fdafc63..c98fa82b2901b6 100644 --- a/Modules/_hashopenssl.c +++ b/Modules/_hashopenssl.c @@ -2025,14 +2025,9 @@ 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; + state->EVPtype = PyModule_AddNewTypeFromSpec( + module, &EVPtype_spec, NULL); + return state->EVPtype == NULL ? -1 : 0; } static int @@ -2044,16 +2039,9 @@ 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) { - return -1; - } + state->EVPXOFtype = PyModule_AddNewTypeFromSpec( + module, &EVPXOFtype_spec, (PyObject *)state->EVPtype); + return state->EVPXOFtype == NULL ? -1 : 0; #endif return 0; } @@ -2061,16 +2049,11 @@ hashlib_init_evpxoftype(PyObject *module) static int hashlib_init_hmactype(PyObject *module) { - _hashlibstate *state = get_hashlib_state(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; + state->HMACtype = PyModule_AddNewTypeFromSpec( + module, &HMACtype_spec, NULL); + return state->HMACtype == NULL ? -1 : 0; } static int 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/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); diff --git a/Modules/mathmodule.c b/Modules/mathmodule.c index d0dd12d25966a1..d00adc6fb7333e 100644 --- a/Modules/mathmodule.c +++ b/Modules/mathmodule.c @@ -270,6 +270,12 @@ m_inf(void) #endif } +static PyObject* +m_inf_o(PyObject *module) +{ + 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(PyObject *module) +{ + 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,8 +3583,26 @@ static PyMethodDef math_methods[] = { {NULL, NULL} /* sentinel */ }; +static PyModuleConst_Def math_constants[] = { + PyModuleConst_Double("pi", Py_MATH_PI), + PyModuleConst_Double("e", Py_MATH_E), + // 2pi + PyModuleConst_Double("tau", Py_MATH_TAU), + PyModuleConst_Call("inf", m_inf_o), +#if !defined(PY_NO_SHORT_FLOAT_REPR) || defined(Py_NAN) + PyModuleConst_Call("nan", m_nan_o), +#endif + {NULL, 0}, +}; + +static int +math_init_constants(PyObject *module) +{ + return PyModule_AddConstants(module, math_constants); +} + static PyModuleDef_Slot math_slots[] = { - {Py_mod_exec, math_exec}, + {Py_mod_exec, math_init_constants}, {0, NULL} }; diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index 65e8d5e7bd984d..bd17c9fccb97c5 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,9 +15687,98 @@ posixmodule_exec(PyObject *m) return 0; } +static PyModuleConst_Def posix_constants[] = { +#ifdef F_OK + PyModuleConst_LongMacro(F_OK), +#endif +#ifdef R_OK + PyModuleConst_LongMacro(R_OK), +#endif +#ifdef W_OK + PyModuleConst_LongMacro(W_OK), +#endif +#ifdef X_OK + PyModuleConst_LongMacro(X_OK), +#endif +#ifdef NGROUPS_MAX + PyModuleConst_LongMacro(NGROUPS_MAX), +#endif +#ifdef TMP_MAX + PyModuleConst_LongMacro(TMP_MAX), +#endif +#ifdef WCONTINUED + PyModuleConst_LongMacro(WCONTINUED), +#endif +#ifdef WNOHANG + PyModuleConst_LongMacro(WNOHANG), +#endif +#ifdef WUNTRACED + PyModuleConst_LongMacro(WUNTRACED), +#endif +#ifdef O_RDONLY + PyModuleConst_LongMacro(O_RDONLY), +#endif +#ifdef O_WRONLY + PyModuleConst_LongMacro(O_WRONLY), +#endif +#ifdef O_RDWR + PyModuleConst_LongMacro(O_RDWR), +#endif +#ifdef O_NDELAY + PyModuleConst_LongMacro(O_NDELAY), +#endif +#ifdef O_NONBLOCK + PyModuleConst_LongMacro(O_NONBLOCK), +#endif +#ifdef O_APPEND + PyModuleConst_LongMacro(O_APPEND), +#endif +#ifdef O_DSYNC + PyModuleConst_LongMacro(O_DSYNC), +#endif +#ifdef O_RSYNC + PyModuleConst_LongMacro(O_RSYNC), +#endif +#ifdef O_SYNC + PyModuleConst_LongMacro(O_SYNC), +#endif +#ifdef O_NOCTTY + PyModuleConst_LongMacro(O_NOCTTY), +#endif +#ifdef O_CREAT + PyModuleConst_LongMacro(O_CREAT), +#endif +#ifdef O_EXCL + PyModuleConst_LongMacro(O_EXCL), +#endif +#ifdef O_TRUNC + PyModuleConst_LongMacro(O_TRUNC), +#endif +#ifdef O_BINARY + PyModuleConst_LongMacro(O_BINARY), +#endif +#ifdef O_TEXT + PyModuleConst_LongMacro(O_TEXT), +#endif +#ifdef O_XATTR + PyModuleConst_LongMacro(O_XATTR), +#endif +#ifdef O_LARGEFILE + PyModuleConst_LongMacro(O_LARGEFILE), +#endif + {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} }; diff --git a/Objects/moduleobject.c b/Objects/moduleobject.c index e57ea86e7694ce..a2f9b30e381999 100644 --- a/Objects/moduleobject.c +++ b/Objects/moduleobject.c @@ -175,6 +175,63 @@ _add_methods_to_object(PyObject *module, PyObject *name, PyMethodDef *functions) return 0; } +int +PyModule_AddConstants(PyObject *module, PyModuleConst_Def *def) +{ + PyObject *dict; + PyModuleConst_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 _PyModuleConst_none_type: + v = Py_None; + Py_INCREF(v); + break; + case _PyModuleConst_long_type: + v = PyLong_FromLong(cur_def->value.m_long); + break; + 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: + v = PyFloat_FromDouble(cur_def->value.m_double); + break; + case _PyModuleConst_string_type: + v = PyUnicode_FromString(cur_def->value.m_str); + break; + case _PyModuleConst_call_type: + v = cur_def->value.m_call(module); + 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) { diff --git a/Python/modsupport.c b/Python/modsupport.c index 8655daa1fc5e0e..0254055ed08a34 100644 --- a/Python/modsupport.c +++ b/Python/modsupport.c @@ -712,3 +712,44 @@ PyModule_AddType(PyObject *module, PyTypeObject *type) return PyModule_AddObjectRef(module, name, (PyObject *)type); } + +PyTypeObject * +PyModule_AddNewTypeFromSpec(PyObject *module, PyType_Spec *spec, + PyObject *bases) +{ + PyTypeObject *type; + + type = (PyTypeObject *)PyType_FromModuleAndSpec(module, spec, bases); + if (type == NULL) { + return NULL; + } + + if (PyModule_AddType(module, type) < 0) { + Py_DECREF(type); + return NULL; + } + 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; + } + + 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; +}
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: