From c3f52088834df0e8135bccd0c69c746bb81b24ae Mon Sep 17 00:00:00 2001 From: Dong-hee Na Date: Fri, 20 Mar 2020 18:41:36 +0900 Subject: [PATCH 1/6] bpo-40024: Add _PyModule_AddType helper function. --- Include/modsupport.h | 3 +++ .../2020-03-20-18-41-33.bpo-40024.9zHpve.rst | 1 + Modules/_collectionsmodule.c | 9 +-------- Modules/_functoolsmodule.c | 6 +----- Modules/itertoolsmodule.c | 9 +-------- Python/modsupport.c | 17 +++++++++++++++++ 6 files changed, 24 insertions(+), 21 deletions(-) create mode 100644 Misc/NEWS.d/next/C API/2020-03-20-18-41-33.bpo-40024.9zHpve.rst diff --git a/Include/modsupport.h b/Include/modsupport.h index f2dc812df2ba8b..422dc917a1541a 100644 --- a/Include/modsupport.h +++ b/Include/modsupport.h @@ -139,6 +139,9 @@ 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 *); +#ifndef Py_LIMITED_API +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 00000000000000..0edefb1a808706 --- /dev/null +++ b/Misc/NEWS.d/next/C API/2020-03-20-18-41-33.bpo-40024.9zHpve.rst @@ -0,0 +1 @@ +Add _PyModule_AddType helper function. Patch by Dong-hee Na. diff --git a/Modules/_collectionsmodule.c b/Modules/_collectionsmodule.c index a595e5b5ea341c..c89b5ed874326e 100644 --- a/Modules/_collectionsmodule.c +++ b/Modules/_collectionsmodule.c @@ -2572,14 +2572,7 @@ collections_exec(PyObject *module) { 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); + if (_PyModule_AddType(module, typelist[i]) < 0) { return -1; } } diff --git a/Modules/_functoolsmodule.c b/Modules/_functoolsmodule.c index 0c0fae1a979a4f..6ec1eb7f55d757 100644 --- a/Modules/_functoolsmodule.c +++ b/Modules/_functoolsmodule.c @@ -1433,7 +1433,6 @@ PyInit__functools(void) { int i; PyObject *m; - const char *name; PyTypeObject *typelist[] = { &partial_type, &lru_cache_type, @@ -1451,13 +1450,10 @@ PyInit__functools(void) } for (i=0 ; typelist[i] != NULL ; i++) { - if (PyType_Ready(typelist[i]) < 0) { + 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/itertoolsmodule.c b/Modules/itertoolsmodule.c index 72fd3d7c551caa..8f0ca459906c62 100644 --- a/Modules/itertoolsmodule.c +++ b/Modules/itertoolsmodule.c @@ -4731,14 +4731,7 @@ itertoolsmodule_exec(PyObject *m) 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); + if (_PyModule_AddType(m, typelist[i]) < 0) { return -1; } } diff --git a/Python/modsupport.c b/Python/modsupport.c index 7271af3ac5332f..a30bf12e32a347 100644 --- a/Python/modsupport.c +++ b/Python/modsupport.c @@ -678,3 +678,20 @@ 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); + Py_INCREF(type); + if (PyModule_AddObject(module, name, (PyObject *)type) < 0) { + Py_DECREF(type); + return -1; + } + + return 0; +} From fc67f660cef902d7502847f86999aee86bf39c4c Mon Sep 17 00:00:00 2001 From: Dong-hee Na Date: Sat, 21 Mar 2020 23:12:47 +0900 Subject: [PATCH 2/6] bpo-40024: Update docs and apply to _lzmamodule.c --- Doc/c-api/module.rst | 8 +++++++- Include/modsupport.h | 3 ++- Modules/_lzmamodule.c | 14 ++++---------- 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/Doc/c-api/module.rst b/Doc/c-api/module.rst index 8d1a0fbeb76584..135540f68ad090 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,12 @@ state: Add a string constant to *module*. +.. c:function:: int _PyModule_AddType(PyObject *module, PyTypeObject *type) + + Add an type object to *module*. 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. + Module lookup ^^^^^^^^^^^^^ diff --git a/Include/modsupport.h b/Include/modsupport.h index 422dc917a1541a..9b71c382c534e7 100644 --- a/Include/modsupport.h +++ b/Include/modsupport.h @@ -139,7 +139,8 @@ 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 *); -#ifndef Py_LIMITED_API +#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) diff --git a/Modules/_lzmamodule.c b/Modules/_lzmamodule.c index 1ab67f306b73a0..a1992da83fea78 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; } From ca82a2dc61647dcb70065d83c98a83b2f6178682 Mon Sep 17 00:00:00 2001 From: Dong-hee Na Date: Sun, 22 Mar 2020 02:03:40 +0900 Subject: [PATCH 3/6] Update Misc/NEWS.d/next/C API/2020-03-20-18-41-33.bpo-40024.9zHpve.rst Co-Authored-By: Victor Stinner --- Misc/NEWS.d/next/C API/2020-03-20-18-41-33.bpo-40024.9zHpve.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 index 0edefb1a808706..a0b33dd9f1352c 100644 --- 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 @@ -1 +1 @@ -Add _PyModule_AddType helper function. Patch by Dong-hee Na. +Add :c:func:`PyModule_AddType` helper function: add a type to a module. Patch by Dong-hee Na. From 9866355e13c389bd4c21e71869658f3ec886c24f Mon Sep 17 00:00:00 2001 From: Dong-hee Na Date: Sun, 22 Mar 2020 02:19:02 +0900 Subject: [PATCH 4/6] bpo-40024: Apply code review --- Doc/c-api/module.rst | 10 +++++++--- Doc/whatsnew/3.9.rst | 3 +++ Include/modsupport.h | 2 +- Modules/_collectionsmodule.c | 2 +- Modules/_functoolsmodule.c | 2 +- Modules/_lzmamodule.c | 4 ++-- Modules/itertoolsmodule.c | 2 +- Python/modsupport.c | 2 +- 8 files changed, 17 insertions(+), 10 deletions(-) diff --git a/Doc/c-api/module.rst b/Doc/c-api/module.rst index 135540f68ad090..f5d329f8902db3 100644 --- a/Doc/c-api/module.rst +++ b/Doc/c-api/module.rst @@ -484,12 +484,16 @@ state: Add a string constant to *module*. -.. c:function:: int _PyModule_AddType(PyObject *module, PyTypeObject *type) +.. c:function:: int PyModule_AddType(PyObject *module, PyTypeObject *type) - Add an type object to *module*. The name of the type object is taken from - the last component of :c:member:`~PyTypeObject.tp_name` after dot. + Add an type object to *module*. This function calls :c:func:`PyType_Ready`, + :c:func:`_PyType_Name()` and :c:func:`PyModule_AddObject()` internally. + 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 5c84ca10e20378..9f9e8951f52d4f 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 9b71c382c534e7..4c4aab65bac103 100644 --- a/Include/modsupport.h +++ b/Include/modsupport.h @@ -141,7 +141,7 @@ 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); +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/Modules/_collectionsmodule.c b/Modules/_collectionsmodule.c index c89b5ed874326e..7d01096913605a 100644 --- a/Modules/_collectionsmodule.c +++ b/Modules/_collectionsmodule.c @@ -2572,7 +2572,7 @@ collections_exec(PyObject *module) { defdict_type.tp_base = &PyDict_Type; for (int i = 0; typelist[i] != NULL; i++) { - if (_PyModule_AddType(module, typelist[i]) < 0) { + if (PyModule_AddType(module, typelist[i]) < 0) { return -1; } } diff --git a/Modules/_functoolsmodule.c b/Modules/_functoolsmodule.c index 6ec1eb7f55d757..100858db73668f 100644 --- a/Modules/_functoolsmodule.c +++ b/Modules/_functoolsmodule.c @@ -1450,7 +1450,7 @@ PyInit__functools(void) } for (i=0 ; typelist[i] != NULL ; i++) { - if (_PyModule_AddType(m, typelist[i]) < 0) { + if (PyModule_AddType(m, typelist[i]) < 0) { Py_DECREF(m); return NULL; } diff --git a/Modules/_lzmamodule.c b/Modules/_lzmamodule.c index a1992da83fea78..a2027be2e98fb9 100644 --- a/Modules/_lzmamodule.c +++ b/Modules/_lzmamodule.c @@ -1486,11 +1486,11 @@ PyInit__lzma(void) if (PyModule_AddObject(m, "LZMAError", Error) == -1) return NULL; - if (_PyModule_AddType(m, &Compressor_type) < 0) { + if (PyModule_AddType(m, &Compressor_type) < 0) { return NULL; } - if (_PyModule_AddType(m, &Decompressor_type) < 0) { + if (PyModule_AddType(m, &Decompressor_type) < 0) { return NULL; } diff --git a/Modules/itertoolsmodule.c b/Modules/itertoolsmodule.c index 8f0ca459906c62..708fccfc12975e 100644 --- a/Modules/itertoolsmodule.c +++ b/Modules/itertoolsmodule.c @@ -4731,7 +4731,7 @@ itertoolsmodule_exec(PyObject *m) Py_SET_TYPE(&teedataobject_type, &PyType_Type); for (int i = 0; typelist[i] != NULL; i++) { - if (_PyModule_AddType(m, typelist[i]) < 0) { + if (PyModule_AddType(m, typelist[i]) < 0) { return -1; } } diff --git a/Python/modsupport.c b/Python/modsupport.c index a30bf12e32a347..0230ab39c9bc07 100644 --- a/Python/modsupport.c +++ b/Python/modsupport.c @@ -680,7 +680,7 @@ PyModule_AddStringConstant(PyObject *m, const char *name, const char *value) } int -_PyModule_AddType(PyObject *module, PyTypeObject *type) +PyModule_AddType(PyObject *module, PyTypeObject *type) { if (PyType_Ready(type) < 0) { return -1; From 2df2a546a09ebe86226390263055b11eacaeeafc Mon Sep 17 00:00:00 2001 From: Dong-hee Na Date: Sun, 22 Mar 2020 14:02:41 +0900 Subject: [PATCH 5/6] bpo-40024: Apply Victor's code review. --- Modules/_collectionsmodule.c | 5 ++--- Modules/_functoolsmodule.c | 6 ++---- Modules/itertoolsmodule.c | 5 ++--- Objects/typeobject.c | 1 + Python/modsupport.c | 2 ++ 5 files changed, 9 insertions(+), 10 deletions(-) diff --git a/Modules/_collectionsmodule.c b/Modules/_collectionsmodule.c index 7d01096913605a..11342a35179ef6 100644 --- a/Modules/_collectionsmodule.c +++ b/Modules/_collectionsmodule.c @@ -2565,13 +2565,12 @@ 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++) { + 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 100858db73668f..ff733b8d45a308 100644 --- a/Modules/_functoolsmodule.c +++ b/Modules/_functoolsmodule.c @@ -1431,12 +1431,10 @@ static struct PyModuleDef _functoolsmodule = { PyMODINIT_FUNC PyInit__functools(void) { - int i; PyObject *m; PyTypeObject *typelist[] = { &partial_type, - &lru_cache_type, - NULL + &lru_cache_type }; m = PyModule_Create(&_functoolsmodule); @@ -1449,7 +1447,7 @@ PyInit__functools(void) return NULL; } - for (i=0 ; typelist[i] != NULL ; i++) { + for (size_t i = 0; i < Py_ARRAY_LENGTH(typelist); i++) { if (PyModule_AddType(m, typelist[i]) < 0) { Py_DECREF(m); return NULL; diff --git a/Modules/itertoolsmodule.c b/Modules/itertoolsmodule.c index 708fccfc12975e..83d1bb12724800 100644 --- a/Modules/itertoolsmodule.c +++ b/Modules/itertoolsmodule.c @@ -4724,13 +4724,12 @@ 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++) { + 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 e27c4b2c40a2c0..bed50d1e7f2d3c 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 0230ab39c9bc07..a8e78c3cec88bb 100644 --- a/Python/modsupport.c +++ b/Python/modsupport.c @@ -687,6 +687,8 @@ PyModule_AddType(PyObject *module, PyTypeObject *type) } const char *name = _PyType_Name(type); + assert(name != NULL); + Py_INCREF(type); if (PyModule_AddObject(module, name, (PyObject *)type) < 0) { Py_DECREF(type); From 0a29720f4946aad55401adaec7ed73fe26bb4a9e Mon Sep 17 00:00:00 2001 From: Dong-hee Na Date: Mon, 23 Mar 2020 00:38:01 +0900 Subject: [PATCH 6/6] Update Doc/c-api/module.rst Co-Authored-By: Victor Stinner --- Doc/c-api/module.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/c-api/module.rst b/Doc/c-api/module.rst index f5d329f8902db3..8cf26fbe9e4af5 100644 --- a/Doc/c-api/module.rst +++ b/Doc/c-api/module.rst @@ -486,8 +486,8 @@ state: .. c:function:: int PyModule_AddType(PyObject *module, PyTypeObject *type) - Add an type object to *module*. This function calls :c:func:`PyType_Ready`, - :c:func:`_PyType_Name()` and :c:func:`PyModule_AddObject()` internally. + 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.