Skip to content

Commit 05e4a29

Browse files
authored
bpo-40024: Add PyModule_AddType() helper function (GH-19088)
1 parent b33e525 commit 05e4a29

File tree

10 files changed

+52
-42
lines changed

10 files changed

+52
-42
lines changed

Doc/c-api/module.rst

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -441,7 +441,7 @@ state:
441441
442442
Add an object to *module* as *name*. This is a convenience function which can
443443
be used from the module's initialization function. This steals a reference to
444-
*value* on success. Return ``-1`` on error, ``0`` on success.
444+
*value* on success. Return ``-1`` on error, ``0`` on success.
445445
446446
.. note::
447447
@@ -484,6 +484,16 @@ state:
484484
485485
Add a string constant to *module*.
486486
487+
.. c:function:: int PyModule_AddType(PyObject *module, PyTypeObject *type)
488+
489+
Add a type object to *module*.
490+
The type object is finalized by calling internally :c:func:`PyType_Ready`.
491+
The name of the type object is taken from the last component of
492+
:c:member:`~PyTypeObject.tp_name` after dot.
493+
Return ``-1`` on error, ``0`` on success.
494+
495+
.. versionadded:: 3.9
496+
487497
488498
Module lookup
489499
^^^^^^^^^^^^^

Doc/whatsnew/3.9.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -538,6 +538,9 @@ Build and C API Changes
538538
by the internal C API. Remove also ``PyThreadFrameGetter`` type.
539539
(Contributed by Victor Stinner in :issue:`39946`.)
540540

541+
* The :c:func:`PyModule_AddType` function is added to help adding a type to a module.
542+
(Contributed by Dong-hee Na in :issue:`40024`.)
543+
541544
Deprecated
542545
==========
543546

Include/modsupport.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,10 @@ void _PyArg_Fini(void);
139139
PyAPI_FUNC(int) PyModule_AddObject(PyObject *, const char *, PyObject *);
140140
PyAPI_FUNC(int) PyModule_AddIntConstant(PyObject *, const char *, long);
141141
PyAPI_FUNC(int) PyModule_AddStringConstant(PyObject *, const char *, const char *);
142+
#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03090000
143+
/* New in 3.9 */
144+
PyAPI_FUNC(int) PyModule_AddType(PyObject *module, PyTypeObject *type);
145+
#endif /* Py_LIMITED_API */
142146
#define PyModule_AddIntMacro(m, c) PyModule_AddIntConstant(m, #c, c)
143147
#define PyModule_AddStringMacro(m, c) PyModule_AddStringConstant(m, #c, c)
144148

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Add :c:func:`PyModule_AddType` helper function: add a type to a module. Patch by Dong-hee Na.

Modules/_collectionsmodule.c

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2565,21 +2565,13 @@ collections_exec(PyObject *module) {
25652565
&PyODict_Type,
25662566
&dequeiter_type,
25672567
&dequereviter_type,
2568-
&tuplegetter_type,
2569-
NULL,
2568+
&tuplegetter_type
25702569
};
25712570

25722571
defdict_type.tp_base = &PyDict_Type;
25732572

2574-
for (int i = 0; typelist[i] != NULL; i++) {
2575-
PyTypeObject *type = typelist[i];
2576-
if (PyType_Ready(type) < 0) {
2577-
return -1;
2578-
}
2579-
const char *name = _PyType_Name(type);
2580-
Py_INCREF(type);
2581-
if (PyModule_AddObject(module, name, (PyObject *)type) < 0) {
2582-
Py_DECREF(type);
2573+
for (size_t i = 0; i < Py_ARRAY_LENGTH(typelist); i++) {
2574+
if (PyModule_AddType(module, typelist[i]) < 0) {
25832575
return -1;
25842576
}
25852577
}

Modules/_functoolsmodule.c

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1431,13 +1431,10 @@ static struct PyModuleDef _functoolsmodule = {
14311431
PyMODINIT_FUNC
14321432
PyInit__functools(void)
14331433
{
1434-
int i;
14351434
PyObject *m;
1436-
const char *name;
14371435
PyTypeObject *typelist[] = {
14381436
&partial_type,
1439-
&lru_cache_type,
1440-
NULL
1437+
&lru_cache_type
14411438
};
14421439

14431440
m = PyModule_Create(&_functoolsmodule);
@@ -1450,14 +1447,11 @@ PyInit__functools(void)
14501447
return NULL;
14511448
}
14521449

1453-
for (i=0 ; typelist[i] != NULL ; i++) {
1454-
if (PyType_Ready(typelist[i]) < 0) {
1450+
for (size_t i = 0; i < Py_ARRAY_LENGTH(typelist); i++) {
1451+
if (PyModule_AddType(m, typelist[i]) < 0) {
14551452
Py_DECREF(m);
14561453
return NULL;
14571454
}
1458-
name = _PyType_Name(typelist[i]);
1459-
Py_INCREF(typelist[i]);
1460-
PyModule_AddObject(m, name, (PyObject *)typelist[i]);
14611455
}
14621456
return m;
14631457
}

Modules/_lzmamodule.c

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1486,19 +1486,13 @@ PyInit__lzma(void)
14861486
if (PyModule_AddObject(m, "LZMAError", Error) == -1)
14871487
return NULL;
14881488

1489-
if (PyType_Ready(&Compressor_type) == -1)
1490-
return NULL;
1491-
Py_INCREF(&Compressor_type);
1492-
if (PyModule_AddObject(m, "LZMACompressor",
1493-
(PyObject *)&Compressor_type) == -1)
1489+
if (PyModule_AddType(m, &Compressor_type) < 0) {
14941490
return NULL;
1491+
}
14951492

1496-
if (PyType_Ready(&Decompressor_type) == -1)
1497-
return NULL;
1498-
Py_INCREF(&Decompressor_type);
1499-
if (PyModule_AddObject(m, "LZMADecompressor",
1500-
(PyObject *)&Decompressor_type) == -1)
1493+
if (PyModule_AddType(m, &Decompressor_type) < 0) {
15011494
return NULL;
1495+
}
15021496

15031497
return m;
15041498
}

Modules/itertoolsmodule.c

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4724,21 +4724,13 @@ itertoolsmodule_exec(PyObject *m)
47244724
&groupby_type,
47254725
&_grouper_type,
47264726
&tee_type,
4727-
&teedataobject_type,
4728-
NULL
4727+
&teedataobject_type
47294728
};
47304729

47314730
Py_SET_TYPE(&teedataobject_type, &PyType_Type);
47324731

4733-
for (int i = 0; typelist[i] != NULL; i++) {
4734-
PyTypeObject *type = typelist[i];
4735-
if (PyType_Ready(type) < 0) {
4736-
return -1;
4737-
}
4738-
const char *name = _PyType_Name(type);
4739-
Py_INCREF(type);
4740-
if (PyModule_AddObject(m, name, (PyObject *)type) < 0) {
4741-
Py_DECREF(type);
4732+
for (size_t i = 0; i < Py_ARRAY_LENGTH(typelist); i++) {
4733+
if (PyModule_AddType(m, typelist[i]) < 0) {
47424734
return -1;
47434735
}
47444736
}

Objects/typeobject.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -431,6 +431,7 @@ check_set_special_type_attr(PyTypeObject *type, PyObject *value, const char *nam
431431
const char *
432432
_PyType_Name(PyTypeObject *type)
433433
{
434+
assert(type->tp_name != NULL);
434435
const char *s = strrchr(type->tp_name, '.');
435436
if (s == NULL) {
436437
s = type->tp_name;

Python/modsupport.c

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -678,3 +678,22 @@ PyModule_AddStringConstant(PyObject *m, const char *name, const char *value)
678678
Py_DECREF(o);
679679
return -1;
680680
}
681+
682+
int
683+
PyModule_AddType(PyObject *module, PyTypeObject *type)
684+
{
685+
if (PyType_Ready(type) < 0) {
686+
return -1;
687+
}
688+
689+
const char *name = _PyType_Name(type);
690+
assert(name != NULL);
691+
692+
Py_INCREF(type);
693+
if (PyModule_AddObject(module, name, (PyObject *)type) < 0) {
694+
Py_DECREF(type);
695+
return -1;
696+
}
697+
698+
return 0;
699+
}

0 commit comments

Comments
 (0)