Skip to content

Commit 8021875

Browse files
authored
bpo-1635741: Add PyModule_AddObjectRef() function (pythonGH-23122)
Added PyModule_AddObjectRef() function: similar to PyModule_AddObjectRef() but don't steal a reference to the value on success.
1 parent 3529718 commit 8021875

File tree

5 files changed

+146
-46
lines changed

5 files changed

+146
-46
lines changed

Doc/c-api/module.rst

+90-14
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,7 @@ of the following two module creation functions:
264264
instead; only use this if you are sure you need it.
265265
266266
Before it is returned from in the initialization function, the resulting module
267-
object is typically populated using functions like :c:func:`PyModule_AddObject`.
267+
object is typically populated using functions like :c:func:`PyModule_AddObjectRef`.
268268
269269
.. _multi-phase-initialization:
270270
@@ -437,26 +437,102 @@ a function called from a module execution slot (if using multi-phase
437437
initialization), can use the following functions to help initialize the module
438438
state:
439439
440+
.. c:function:: int PyModule_AddObjectRef(PyObject *module, const char *name, PyObject *value)
441+
442+
Add an object to *module* as *name*. This is a convenience function which
443+
can be used from the module's initialization function.
444+
445+
On success, return ``0``. On error, raise an exception and return ``-1``.
446+
447+
Return ``NULL`` if *value* is ``NULL``. It must be called with an exception
448+
raised in this case.
449+
450+
Example usage::
451+
452+
static int
453+
add_spam(PyObject *module, int value)
454+
{
455+
PyObject *obj = PyLong_FromLong(value);
456+
if (obj == NULL) {
457+
return -1;
458+
}
459+
int res = PyModule_AddObjectRef(module, "spam", obj);
460+
Py_DECREF(obj);
461+
return res;
462+
}
463+
464+
The example can also be written without checking explicitly if *obj* is
465+
``NULL``::
466+
467+
static int
468+
add_spam(PyObject *module, int value)
469+
{
470+
PyObject *obj = PyLong_FromLong(value);
471+
int res = PyModule_AddObjectRef(module, "spam", obj);
472+
Py_XDECREF(obj);
473+
return res;
474+
}
475+
476+
Note that ``Py_XDECREF()`` should be used instead of ``Py_DECREF()`` in
477+
this case, since *obj* can be ``NULL``.
478+
479+
.. versionadded:: 3.10
480+
481+
440482
.. c:function:: int PyModule_AddObject(PyObject *module, const char *name, PyObject *value)
441483
442-
Add an object to *module* as *name*. This is a convenience function which can
443-
be used from the module's initialization function. This steals a reference to
444-
*value* on success. Return ``-1`` on error, ``0`` on success.
484+
Similar to :c:func:`PyModule_AddObjectRef`, but steals a reference to
485+
*value* on success (if it returns ``0``).
486+
487+
The new :c:func:`PyModule_AddObjectRef` function is recommended, since it is
488+
easy to introduce reference leaks by misusing the
489+
:c:func:`PyModule_AddObject` function.
445490
446491
.. note::
447492
448-
Unlike other functions that steal references, ``PyModule_AddObject()`` only
449-
decrements the reference count of *value* **on success**.
493+
Unlike other functions that steal references, ``PyModule_AddObject()``
494+
only decrements the reference count of *value* **on success**.
450495
451496
This means that its return value must be checked, and calling code must
452-
:c:func:`Py_DECREF` *value* manually on error. Example usage::
453-
454-
Py_INCREF(spam);
455-
if (PyModule_AddObject(module, "spam", spam) < 0) {
456-
Py_DECREF(module);
457-
Py_DECREF(spam);
458-
return NULL;
459-
}
497+
:c:func:`Py_DECREF` *value* manually on error.
498+
499+
Example usage::
500+
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+
}
532+
533+
Note that ``Py_XDECREF()`` should be used instead of ``Py_DECREF()`` in
534+
this case, since *obj* can be ``NULL``.
535+
460536
461537
.. c:function:: int PyModule_AddIntConstant(PyObject *module, const char *name, long value)
462538

Doc/whatsnew/3.10.rst

+5
Original file line numberDiff line numberDiff line change
@@ -374,6 +374,11 @@ New Features
374374
* Added :c:func:`PyUnicode_AsUTF8AndSize` to the limited C API.
375375
(Contributed by Alex Gaynor in :issue:`41784`.)
376376

377+
* Added :c:func:`PyModule_AddObjectRef` function: similar to
378+
:c:func:`PyModule_AddObjectRef` but don't steal a reference to the value on
379+
success.
380+
(Contributed by Victor Stinner in :issue:`1635741`.)
381+
377382

378383
Porting to Python 3.10
379384
----------------------

Include/modsupport.h

+9-1
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,15 @@ PyAPI_FUNC(PyObject * const *) _PyArg_UnpackKeywords(
136136
void _PyArg_Fini(void);
137137
#endif /* Py_LIMITED_API */
138138

139-
PyAPI_FUNC(int) PyModule_AddObject(PyObject *, const char *, PyObject *);
139+
// Add an attribute with name 'name' and value 'obj' to the module 'mod.
140+
// On success, return 0 on success.
141+
// On error, raise an exception and return -1.
142+
PyAPI_FUNC(int) PyModule_AddObjectRef(PyObject *mod, const char *name, PyObject *value);
143+
144+
// Similar to PyModule_AddObjectRef() but steal a reference to 'obj'
145+
// (Py_DECREF(obj)) on success (if it returns 0).
146+
PyAPI_FUNC(int) PyModule_AddObject(PyObject *mod, const char *, PyObject *value);
147+
140148
PyAPI_FUNC(int) PyModule_AddIntConstant(PyObject *, const char *, long);
141149
PyAPI_FUNC(int) PyModule_AddStringConstant(PyObject *, const char *, const char *);
142150
#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03090000
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Added :c:func:`PyModule_AddObjectRef` function: similar to
2+
:c:func:`PyModule_AddObjectRef` but don't steal a reference to the value on
3+
success. Patch by Victor Stinner.

Python/modsupport.c

+39-31
Original file line numberDiff line numberDiff line change
@@ -634,56 +634,70 @@ va_build_stack(PyObject **small_stack, Py_ssize_t small_stack_len,
634634

635635

636636
int
637-
PyModule_AddObject(PyObject *m, const char *name, PyObject *o)
637+
PyModule_AddObjectRef(PyObject *mod, const char *name, PyObject *value)
638638
{
639-
PyObject *dict;
640-
if (!PyModule_Check(m)) {
639+
if (!PyModule_Check(mod)) {
641640
PyErr_SetString(PyExc_TypeError,
642-
"PyModule_AddObject() needs module as first arg");
641+
"PyModule_AddObjectRef() first argument "
642+
"must be a module");
643643
return -1;
644644
}
645-
if (!o) {
646-
if (!PyErr_Occurred())
647-
PyErr_SetString(PyExc_TypeError,
648-
"PyModule_AddObject() needs non-NULL value");
645+
if (!value) {
646+
if (!PyErr_Occurred()) {
647+
PyErr_SetString(PyExc_SystemError,
648+
"PyModule_AddObjectRef() must be called "
649+
"with an exception raised if value is NULL");
650+
}
649651
return -1;
650652
}
651653

652-
dict = PyModule_GetDict(m);
654+
PyObject *dict = PyModule_GetDict(mod);
653655
if (dict == NULL) {
654656
/* Internal error -- modules must have a dict! */
655657
PyErr_Format(PyExc_SystemError, "module '%s' has no __dict__",
656-
PyModule_GetName(m));
658+
PyModule_GetName(mod));
657659
return -1;
658660
}
659-
if (PyDict_SetItemString(dict, name, o))
661+
662+
if (PyDict_SetItemString(dict, name, value)) {
660663
return -1;
661-
Py_DECREF(o);
664+
}
662665
return 0;
663666
}
664667

668+
669+
int
670+
PyModule_AddObject(PyObject *mod, const char *name, PyObject *value)
671+
{
672+
int res = PyModule_AddObjectRef(mod, name, value);
673+
if (res == 0) {
674+
Py_DECREF(value);
675+
}
676+
return res;
677+
}
678+
665679
int
666680
PyModule_AddIntConstant(PyObject *m, const char *name, long value)
667681
{
668-
PyObject *o = PyLong_FromLong(value);
669-
if (!o)
682+
PyObject *obj = PyLong_FromLong(value);
683+
if (!obj) {
670684
return -1;
671-
if (PyModule_AddObject(m, name, o) == 0)
672-
return 0;
673-
Py_DECREF(o);
674-
return -1;
685+
}
686+
int res = PyModule_AddObjectRef(m, name, obj);
687+
Py_DECREF(obj);
688+
return res;
675689
}
676690

677691
int
678692
PyModule_AddStringConstant(PyObject *m, const char *name, const char *value)
679693
{
680-
PyObject *o = PyUnicode_FromString(value);
681-
if (!o)
694+
PyObject *obj = PyUnicode_FromString(value);
695+
if (!obj) {
682696
return -1;
683-
if (PyModule_AddObject(m, name, o) == 0)
684-
return 0;
685-
Py_DECREF(o);
686-
return -1;
697+
}
698+
int res = PyModule_AddObjectRef(m, name, obj);
699+
Py_DECREF(obj);
700+
return res;
687701
}
688702

689703
int
@@ -696,11 +710,5 @@ PyModule_AddType(PyObject *module, PyTypeObject *type)
696710
const char *name = _PyType_Name(type);
697711
assert(name != NULL);
698712

699-
Py_INCREF(type);
700-
if (PyModule_AddObject(module, name, (PyObject *)type) < 0) {
701-
Py_DECREF(type);
702-
return -1;
703-
}
704-
705-
return 0;
713+
return PyModule_AddObjectRef(module, name, (PyObject *)type);
706714
}

0 commit comments

Comments
 (0)