mirror of https://github.com/python/cpython
bpo-42327: C API: Add PyModule_Add() function (GH-23443)
It is a fixed implementation of PyModule_AddObject() which consistently steals reference both on success and on failure.
This commit is contained in:
parent
745492355b
commit
83ac128490
|
@ -486,12 +486,29 @@ state:
|
|||
.. versionadded:: 3.10
|
||||
|
||||
|
||||
.. c:function:: int PyModule_Add(PyObject *module, const char *name, PyObject *value)
|
||||
|
||||
Similar to :c:func:`PyModule_AddObjectRef`, but "steals" a reference
|
||||
to *value*.
|
||||
It can be called with a result of function that returns a new reference
|
||||
without bothering to check its result or even saving it to a variable.
|
||||
|
||||
Example usage::
|
||||
|
||||
if (PyModule_Add(module, "spam", PyBytes_FromString(value)) < 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
.. versionadded:: 3.13
|
||||
|
||||
|
||||
.. c:function:: int PyModule_AddObject(PyObject *module, const char *name, PyObject *value)
|
||||
|
||||
Similar to :c:func:`PyModule_AddObjectRef`, but steals a reference to
|
||||
*value* on success (if it returns ``0``).
|
||||
|
||||
The new :c:func:`PyModule_AddObjectRef` function is recommended, since it is
|
||||
The new :c:func:`PyModule_Add` or :c:func:`PyModule_AddObjectRef`
|
||||
functions are recommended, since it is
|
||||
easy to introduce reference leaks by misusing the
|
||||
:c:func:`PyModule_AddObject` function.
|
||||
|
||||
|
@ -501,44 +518,24 @@ state:
|
|||
only decrements the reference count of *value* **on success**.
|
||||
|
||||
This means that its return value must be checked, and calling code must
|
||||
:c:func:`Py_DECREF` *value* manually on error.
|
||||
:c:func:`Py_XDECREF` *value* manually on error.
|
||||
|
||||
Example usage::
|
||||
|
||||
static int
|
||||
add_spam(PyObject *module, int value)
|
||||
{
|
||||
PyObject *obj = PyLong_FromLong(value);
|
||||
if (obj == NULL) {
|
||||
return -1;
|
||||
}
|
||||
if (PyModule_AddObject(module, "spam", obj) < 0) {
|
||||
Py_DECREF(obj);
|
||||
return -1;
|
||||
}
|
||||
// PyModule_AddObject() stole a reference to obj:
|
||||
// Py_DECREF(obj) is not needed here
|
||||
return 0;
|
||||
}
|
||||
PyObject *obj = PyBytes_FromString(value);
|
||||
if (PyModule_AddObject(module, "spam", obj) < 0) {
|
||||
// If 'obj' is not NULL and PyModule_AddObject() failed,
|
||||
// 'obj' strong reference must be deleted with Py_XDECREF().
|
||||
// If 'obj' is NULL, Py_XDECREF() does nothing.
|
||||
Py_XDECREF(obj);
|
||||
goto error;
|
||||
}
|
||||
// PyModule_AddObject() stole a reference to obj:
|
||||
// Py_XDECREF(obj) is not needed here.
|
||||
|
||||
The example can also be written without checking explicitly if *obj* is
|
||||
``NULL``::
|
||||
.. deprecated:: 3.13
|
||||
|
||||
static int
|
||||
add_spam(PyObject *module, int value)
|
||||
{
|
||||
PyObject *obj = PyLong_FromLong(value);
|
||||
if (PyModule_AddObject(module, "spam", obj) < 0) {
|
||||
Py_XDECREF(obj);
|
||||
return -1;
|
||||
}
|
||||
// PyModule_AddObject() stole a reference to obj:
|
||||
// Py_DECREF(obj) is not needed here
|
||||
return 0;
|
||||
}
|
||||
|
||||
Note that ``Py_XDECREF()`` should be used instead of ``Py_DECREF()`` in
|
||||
this case, since *obj* can be ``NULL``.
|
||||
:c:func:`PyModule_AddObject` is :term:`soft deprecated`.
|
||||
|
||||
|
||||
.. c:function:: int PyModule_AddIntConstant(PyObject *module, const char *name, long value)
|
||||
|
|
|
@ -399,6 +399,7 @@ type,PyModuleDef,3.2,,full-abi
|
|||
type,PyModuleDef_Base,3.2,,full-abi
|
||||
function,PyModuleDef_Init,3.5,,
|
||||
var,PyModuleDef_Type,3.5,,
|
||||
function,PyModule_Add,3.13,,
|
||||
function,PyModule_AddFunctions,3.7,,
|
||||
function,PyModule_AddIntConstant,3.2,,
|
||||
function,PyModule_AddObject,3.2,,
|
||||
|
|
|
@ -774,6 +774,11 @@ New Features
|
|||
If the assertion fails, make sure that the size is set before.
|
||||
(Contributed by Victor Stinner in :gh:`106168`.)
|
||||
|
||||
* Add :c:func:`PyModule_Add` function: similar to
|
||||
:c:func:`PyModule_AddObjectRef` and :c:func:`PyModule_AddObject` but
|
||||
always steals a reference to the value.
|
||||
(Contributed by Serhiy Storchaka in :gh:`86493`.)
|
||||
|
||||
Porting to Python 3.13
|
||||
----------------------
|
||||
|
||||
|
|
|
@ -23,12 +23,18 @@ PyAPI_FUNC(PyObject *) Py_BuildValue(const char *, ...);
|
|||
PyAPI_FUNC(PyObject *) Py_VaBuildValue(const char *, va_list);
|
||||
|
||||
// Add an attribute with name 'name' and value 'obj' to the module 'mod.
|
||||
// On success, return 0 on success.
|
||||
// On success, return 0.
|
||||
// On error, raise an exception and return -1.
|
||||
PyAPI_FUNC(int) PyModule_AddObjectRef(PyObject *mod, const char *name, PyObject *value);
|
||||
|
||||
// Similar to PyModule_AddObjectRef() but steal a reference to 'obj'
|
||||
// (Py_DECREF(obj)) on success (if it returns 0).
|
||||
#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x030d0000
|
||||
// Similar to PyModule_AddObjectRef() but steal a reference to 'value'.
|
||||
PyAPI_FUNC(int) PyModule_Add(PyObject *mod, const char *name, PyObject *value);
|
||||
#endif /* Py_LIMITED_API */
|
||||
|
||||
// Similar to PyModule_AddObjectRef() and PyModule_Add() but steal
|
||||
// a reference to 'value' on success and only on success.
|
||||
// Errorprone. Should not be used in new code.
|
||||
PyAPI_FUNC(int) PyModule_AddObject(PyObject *mod, const char *, PyObject *value);
|
||||
|
||||
PyAPI_FUNC(int) PyModule_AddIntConstant(PyObject *, const char *, long);
|
||||
|
|
|
@ -425,6 +425,7 @@ SYMBOL_NAMES = (
|
|||
"PyMethodDescr_Type",
|
||||
"PyModuleDef_Init",
|
||||
"PyModuleDef_Type",
|
||||
"PyModule_Add",
|
||||
"PyModule_AddFunctions",
|
||||
"PyModule_AddIntConstant",
|
||||
"PyModule_AddObject",
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
Add :func:`PyModule_Add` function: similar to :c:func:`PyModule_AddObjectRef` and :c:func:`PyModule_AddObject`, but always steals a reference to the value.
|
|
@ -2444,3 +2444,5 @@
|
|||
added = '3.13'
|
||||
[function.PyMapping_GetOptionalItemString]
|
||||
added = '3.13'
|
||||
[function.PyModule_Add]
|
||||
added = '3.13'
|
||||
|
|
|
@ -374,6 +374,7 @@ EXPORT_FUNC(PyMemoryView_FromBuffer)
|
|||
EXPORT_FUNC(PyMemoryView_FromMemory)
|
||||
EXPORT_FUNC(PyMemoryView_FromObject)
|
||||
EXPORT_FUNC(PyMemoryView_GetContiguous)
|
||||
EXPORT_FUNC(PyModule_Add)
|
||||
EXPORT_FUNC(PyModule_AddFunctions)
|
||||
EXPORT_FUNC(PyModule_AddIntConstant)
|
||||
EXPORT_FUNC(PyModule_AddObject)
|
||||
|
|
|
@ -606,13 +606,16 @@ PyModule_AddObjectRef(PyObject *mod, const char *name, PyObject *value)
|
|||
PyModule_GetName(mod));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (PyDict_SetItemString(dict, name, value)) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
return PyDict_SetItemString(dict, name, value);
|
||||
}
|
||||
|
||||
int
|
||||
PyModule_Add(PyObject *mod, const char *name, PyObject *value)
|
||||
{
|
||||
int res = PyModule_AddObjectRef(mod, name, value);
|
||||
Py_XDECREF(value);
|
||||
return res;
|
||||
}
|
||||
|
||||
int
|
||||
PyModule_AddObject(PyObject *mod, const char *name, PyObject *value)
|
||||
|
@ -627,25 +630,13 @@ PyModule_AddObject(PyObject *mod, const char *name, PyObject *value)
|
|||
int
|
||||
PyModule_AddIntConstant(PyObject *m, const char *name, long value)
|
||||
{
|
||||
PyObject *obj = PyLong_FromLong(value);
|
||||
if (!obj) {
|
||||
return -1;
|
||||
}
|
||||
int res = PyModule_AddObjectRef(m, name, obj);
|
||||
Py_DECREF(obj);
|
||||
return res;
|
||||
return PyModule_Add(m, name, PyLong_FromLong(value));
|
||||
}
|
||||
|
||||
int
|
||||
PyModule_AddStringConstant(PyObject *m, const char *name, const char *value)
|
||||
{
|
||||
PyObject *obj = PyUnicode_FromString(value);
|
||||
if (!obj) {
|
||||
return -1;
|
||||
}
|
||||
int res = PyModule_AddObjectRef(m, name, obj);
|
||||
Py_DECREF(obj);
|
||||
return res;
|
||||
return PyModule_Add(m, name, PyUnicode_FromString(value));
|
||||
}
|
||||
|
||||
int
|
||||
|
|
Loading…
Reference in New Issue