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; +}