Skip to content

Commit 3387f58

Browse files
bpo-42327: Add PyModule_Add().
1 parent ba2958e commit 3387f58

37 files changed

+427
-347
lines changed

Doc/c-api/module.rst

Lines changed: 31 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -479,12 +479,35 @@ state:
479479
.. versionadded:: 3.10
480480
481481
482+
.. c:function:: int PyModule_Add(PyObject *module, const char *name, PyObject *value)
483+
484+
Add an object to *module* as *name*. This is a convenience function which
485+
can be used from the module's initialization function.
486+
487+
On success, return ``0``. On error, raise an exception and return ``-1``.
488+
489+
Return ``-1`` if *value* is ``NULL``. It must be called with an exception
490+
raised in this case.
491+
492+
This function "steals" a reference to *value*. It can be called with
493+
a result of function that returns a new reference without bothering to
494+
check its result or even saving it to a variable.
495+
496+
Example usage::
497+
498+
if (PyModule_Add(module, "spam", PyBytes_FromString(value)) < 0) {
499+
goto error;
500+
}
501+
502+
.. versionadded:: 3.10
503+
504+
482505
.. c:function:: int PyModule_AddObject(PyObject *module, const char *name, PyObject *value)
483506
484-
Similar to :c:func:`PyModule_AddObjectRef`, but steals a reference to
507+
Similar to :c:func:`PyModule_Add`, but only steals a reference to
485508
*value* on success (if it returns ``0``).
486509
487-
The new :c:func:`PyModule_AddObjectRef` function is recommended, since it is
510+
The new :c:func:`PyModule_Add` function is recommended, since it is
488511
easy to introduce reference leaks by misusing the
489512
:c:func:`PyModule_AddObject` function.
490513
@@ -494,41 +517,15 @@ state:
494517
only decrements the reference count of *value* **on success**.
495518
496519
This means that its return value must be checked, and calling code must
497-
:c:func:`Py_DECREF` *value* manually on error.
520+
:c:func:`Py_XDECREF` *value* manually on error.
498521
499522
Example usage::
500523
501-
static int
502-
add_spam(PyObject *module, int value)
503-
{
504-
PyObject *obj = PyLong_FromLong(value);
505-
if (obj == NULL) {
506-
return -1;
507-
}
508-
if (PyModule_AddObject(module, "spam", obj) < 0) {
509-
Py_DECREF(obj);
510-
return -1;
511-
}
512-
// PyModule_AddObject() stole a reference to obj:
513-
// Py_DECREF(obj) is not needed here
514-
return 0;
515-
}
516-
517-
The example can also be written without checking explicitly if *obj* is
518-
``NULL``::
519-
520-
static int
521-
add_spam(PyObject *module, int value)
522-
{
523-
PyObject *obj = PyLong_FromLong(value);
524-
if (PyModule_AddObject(module, "spam", obj) < 0) {
525-
Py_XDECREF(obj);
526-
return -1;
527-
}
528-
// PyModule_AddObject() stole a reference to obj:
529-
// Py_DECREF(obj) is not needed here
530-
return 0;
531-
}
524+
PyObject *obj = PyBytes_FromString(value);
525+
if (PyModule_AddObject(module, "spam", obj) < 0) {
526+
Py_XDECREF(obj);
527+
goto error;
528+
}
532529
533530
Note that ``Py_XDECREF()`` should be used instead of ``Py_DECREF()`` in
534531
this case, since *obj* can be ``NULL``.

Doc/whatsnew/3.10.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -428,6 +428,10 @@ New Features
428428
success.
429429
(Contributed by Victor Stinner in :issue:`1635741`.)
430430

431+
* Added :c:func:`PyModule_Add` function: similar to
432+
:c:func:`PyModule_AddObject` but always steals a reference to the value.
433+
(Contributed by Serhiy Storchaka in :issue:`42327`.)
434+
431435
* Added :c:func:`Py_NewRef` and :c:func:`Py_XNewRef` functions to increment the
432436
reference count of an object and return the object.
433437
(Contributed by Victor Stinner in :issue:`42262`.)

Include/modsupport.h

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -136,13 +136,20 @@ PyAPI_FUNC(PyObject * const *) _PyArg_UnpackKeywords(
136136
void _PyArg_Fini(void);
137137
#endif /* Py_LIMITED_API */
138138

139+
#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x030A0000
140+
// Add an attribute with name 'name' and value 'value' to the module 'mod'.
141+
// Steal a reference to 'value'.
142+
// On success, return 0.
143+
// On error, raise an exception and return -1.
144+
PyAPI_FUNC(int) PyModule_Add(PyObject *mod, const char *name, PyObject *value);
145+
#endif /* Py_LIMITED_API */
146+
139147
// Add an attribute with name 'name' and value 'obj' to the module 'mod.
140148
// On success, return 0 on success.
141149
// On error, raise an exception and return -1.
142150
PyAPI_FUNC(int) PyModule_AddObjectRef(PyObject *mod, const char *name, PyObject *value);
143151

144-
// Similar to PyModule_AddObjectRef() but steal a reference to 'obj'
145-
// (Py_DECREF(obj)) on success (if it returns 0).
152+
// Similar to PyModule_Add() but steal a reference to 'value' only on success.
146153
PyAPI_FUNC(int) PyModule_AddObject(PyObject *mod, const char *, PyObject *value);
147154

148155
PyAPI_FUNC(int) PyModule_AddIntConstant(PyObject *, const char *, long);
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Added :func:`PyModule_Add`.

Modules/_csv.c

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1650,10 +1650,8 @@ PyInit__csv(void)
16501650

16511651
/* Add _dialects dictionary */
16521652
get_csv_state(module)->dialects = PyDict_New();
1653-
if (get_csv_state(module)->dialects == NULL)
1654-
return NULL;
1655-
Py_INCREF(get_csv_state(module)->dialects);
1656-
if (PyModule_AddObject(module, "_dialects", get_csv_state(module)->dialects))
1653+
Py_XINCREF(get_csv_state(module)->dialects);
1654+
if (PyModule_Add(module, "_dialects", get_csv_state(module)->dialects))
16571655
return NULL;
16581656

16591657
/* Add quote styles into dictionary */
@@ -1669,9 +1667,9 @@ PyInit__csv(void)
16691667

16701668
/* Add the CSV exception object to the module. */
16711669
get_csv_state(module)->error_obj = PyErr_NewException("_csv.Error", NULL, NULL);
1672-
if (get_csv_state(module)->error_obj == NULL)
1670+
Py_XINCREF(get_csv_state(module)->error_obj);
1671+
if (PyModule_Add(module, "Error", get_csv_state(module)->error_obj) < 0) {
16731672
return NULL;
1674-
Py_INCREF(get_csv_state(module)->error_obj);
1675-
PyModule_AddObject(module, "Error", get_csv_state(module)->error_obj);
1673+
}
16761674
return module;
16771675
}

0 commit comments

Comments
 (0)