diff --git a/Doc/c-api/module.rst b/Doc/c-api/module.rst index 8d1a0fbeb76..8cf26fbe9e4 100644 --- a/Doc/c-api/module.rst +++ b/Doc/c-api/module.rst @@ -441,7 +441,7 @@ state: Add an object to *module* as *name*. This is a convenience function which can be used from the module's initialization function. This steals a reference to - *value* on success. Return ``-1`` on error, ``0`` on success. + *value* on success. Return ``-1`` on error, ``0`` on success. .. note:: @@ -484,6 +484,16 @@ state: Add a string constant to *module*. +.. c:function:: int PyModule_AddType(PyObject *module, PyTypeObject *type) + + Add a type object to *module*. + The type object is finalized by calling internally :c:func:`PyType_Ready`. + The name of the type object is taken from the last component of + :c:member:`~PyTypeObject.tp_name` after dot. + Return ``-1`` on error, ``0`` on success. + + .. versionadded:: 3.9 + Module lookup ^^^^^^^^^^^^^ diff --git a/Doc/whatsnew/3.9.rst b/Doc/whatsnew/3.9.rst index 5c84ca10e20..9f9e8951f52 100644 --- a/Doc/whatsnew/3.9.rst +++ b/Doc/whatsnew/3.9.rst @@ -538,6 +538,9 @@ Build and C API Changes by the internal C API. Remove also ``PyThreadFrameGetter`` type. (Contributed by Victor Stinner in :issue:`39946`.) +* The :c:func:`PyModule_AddType` function is added to help adding a type to a module. + (Contributed by Dong-hee Na in :issue:`40024`.) + Deprecated ========== diff --git a/Include/modsupport.h b/Include/modsupport.h index f2dc812df2b..4c4aab65bac 100644 --- a/Include/modsupport.h +++ b/Include/modsupport.h @@ -139,6 +139,10 @@ void _PyArg_Fini(void); PyAPI_FUNC(int) PyModule_AddObject(PyObject *, const char *, PyObject *); PyAPI_FUNC(int) PyModule_AddIntConstant(PyObject *, const char *, long); PyAPI_FUNC(int) PyModule_AddStringConstant(PyObject *, const char *, const char *); +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03090000 +/* New in 3.9 */ +PyAPI_FUNC(int) PyModule_AddType(PyObject *module, PyTypeObject *type); +#endif /* Py_LIMITED_API */ #define PyModule_AddIntMacro(m, c) PyModule_AddIntConstant(m, #c, c) #define PyModule_AddStringMacro(m, c) PyModule_AddStringConstant(m, #c, c) diff --git a/Misc/NEWS.d/next/C API/2020-03-20-18-41-33.bpo-40024.9zHpve.rst b/Misc/NEWS.d/next/C API/2020-03-20-18-41-33.bpo-40024.9zHpve.rst new file mode 100644 index 00000000000..a0b33dd9f13 --- /dev/null +++ b/Misc/NEWS.d/next/C API/2020-03-20-18-41-33.bpo-40024.9zHpve.rst @@ -0,0 +1 @@ +Add :c:func:`PyModule_AddType` helper function: add a type to a module. Patch by Dong-hee Na. diff --git a/Modules/_collectionsmodule.c b/Modules/_collectionsmodule.c index a595e5b5ea3..11342a35179 100644 --- a/Modules/_collectionsmodule.c +++ b/Modules/_collectionsmodule.c @@ -2565,21 +2565,13 @@ collections_exec(PyObject *module) { &PyODict_Type, &dequeiter_type, &dequereviter_type, - &tuplegetter_type, - NULL, + &tuplegetter_type }; defdict_type.tp_base = &PyDict_Type; - for (int i = 0; typelist[i] != NULL; i++) { - PyTypeObject *type = typelist[i]; - if (PyType_Ready(type) < 0) { - return -1; - } - const char *name = _PyType_Name(type); - Py_INCREF(type); - if (PyModule_AddObject(module, name, (PyObject *)type) < 0) { - Py_DECREF(type); + for (size_t i = 0; i < Py_ARRAY_LENGTH(typelist); i++) { + if (PyModule_AddType(module, typelist[i]) < 0) { return -1; } } diff --git a/Modules/_functoolsmodule.c b/Modules/_functoolsmodule.c index 0c0fae1a979..ff733b8d45a 100644 --- a/Modules/_functoolsmodule.c +++ b/Modules/_functoolsmodule.c @@ -1431,13 +1431,10 @@ static struct PyModuleDef _functoolsmodule = { PyMODINIT_FUNC PyInit__functools(void) { - int i; PyObject *m; - const char *name; PyTypeObject *typelist[] = { &partial_type, - &lru_cache_type, - NULL + &lru_cache_type }; m = PyModule_Create(&_functoolsmodule); @@ -1450,14 +1447,11 @@ PyInit__functools(void) return NULL; } - for (i=0 ; typelist[i] != NULL ; i++) { - if (PyType_Ready(typelist[i]) < 0) { + for (size_t i = 0; i < Py_ARRAY_LENGTH(typelist); i++) { + if (PyModule_AddType(m, typelist[i]) < 0) { Py_DECREF(m); return NULL; } - name = _PyType_Name(typelist[i]); - Py_INCREF(typelist[i]); - PyModule_AddObject(m, name, (PyObject *)typelist[i]); } return m; } diff --git a/Modules/_lzmamodule.c b/Modules/_lzmamodule.c index 1ab67f306b7..a2027be2e98 100644 --- a/Modules/_lzmamodule.c +++ b/Modules/_lzmamodule.c @@ -1486,19 +1486,13 @@ PyInit__lzma(void) if (PyModule_AddObject(m, "LZMAError", Error) == -1) return NULL; - if (PyType_Ready(&Compressor_type) == -1) - return NULL; - Py_INCREF(&Compressor_type); - if (PyModule_AddObject(m, "LZMACompressor", - (PyObject *)&Compressor_type) == -1) + if (PyModule_AddType(m, &Compressor_type) < 0) { return NULL; + } - if (PyType_Ready(&Decompressor_type) == -1) - return NULL; - Py_INCREF(&Decompressor_type); - if (PyModule_AddObject(m, "LZMADecompressor", - (PyObject *)&Decompressor_type) == -1) + if (PyModule_AddType(m, &Decompressor_type) < 0) { return NULL; + } return m; } diff --git a/Modules/itertoolsmodule.c b/Modules/itertoolsmodule.c index 72fd3d7c551..83d1bb12724 100644 --- a/Modules/itertoolsmodule.c +++ b/Modules/itertoolsmodule.c @@ -4724,21 +4724,13 @@ itertoolsmodule_exec(PyObject *m) &groupby_type, &_grouper_type, &tee_type, - &teedataobject_type, - NULL + &teedataobject_type }; Py_SET_TYPE(&teedataobject_type, &PyType_Type); - for (int i = 0; typelist[i] != NULL; i++) { - PyTypeObject *type = typelist[i]; - if (PyType_Ready(type) < 0) { - return -1; - } - const char *name = _PyType_Name(type); - Py_INCREF(type); - if (PyModule_AddObject(m, name, (PyObject *)type) < 0) { - Py_DECREF(type); + for (size_t i = 0; i < Py_ARRAY_LENGTH(typelist); i++) { + if (PyModule_AddType(m, typelist[i]) < 0) { return -1; } } diff --git a/Objects/typeobject.c b/Objects/typeobject.c index e27c4b2c40a..bed50d1e7f2 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -431,6 +431,7 @@ check_set_special_type_attr(PyTypeObject *type, PyObject *value, const char *nam const char * _PyType_Name(PyTypeObject *type) { + assert(type->tp_name != NULL); const char *s = strrchr(type->tp_name, '.'); if (s == NULL) { s = type->tp_name; diff --git a/Python/modsupport.c b/Python/modsupport.c index 7271af3ac53..a8e78c3cec8 100644 --- a/Python/modsupport.c +++ b/Python/modsupport.c @@ -678,3 +678,22 @@ PyModule_AddStringConstant(PyObject *m, const char *name, const char *value) Py_DECREF(o); return -1; } + +int +PyModule_AddType(PyObject *module, PyTypeObject *type) +{ + if (PyType_Ready(type) < 0) { + return -1; + } + + const char *name = _PyType_Name(type); + assert(name != NULL); + + Py_INCREF(type); + if (PyModule_AddObject(module, name, (PyObject *)type) < 0) { + Py_DECREF(type); + return -1; + } + + return 0; +}