Skip to content

Commit 8021875

Browse files
authored
bpo-1635741: Add PyModule_AddObjectRef() function (GH-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

Lines changed: 90 additions & 14 deletions
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

Lines changed: 5 additions & 0 deletions
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

Lines changed: 9 additions & 1 deletion
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
Lines changed: 3 additions & 0 deletions
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

Lines changed: 39 additions & 31 deletions
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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy