* Add a note to the PyModule_AddObject docs.
* Correct example usages of PyModule_AddObject.
* Whitespace.
* Clean up wording.
* 📜🤖 Added by blurb_it.
* First code review.
* Add < 0 in the tests with PyModule_AddObject
Add an object to *module* as *name*. This is a convenience function which can
be used from the module's initialization function. This steals a reference to
- *value*. Return ``-1`` on error, ``0`` on success.
+ *value* on success. Return ``-1`` on error, ``0`` on success.
+
+ .. note::
+
+ Unlike other functions that steal references, ``PyModule_AddObject()`` 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. Example usage::
+
+ Py_INCREF(spam);
+ if (PyModule_AddObject(module, "spam", spam) < 0) {
+ Py_DECREF(module);
+ Py_DECREF(spam);
+ return NULL;
+ }
.. c:function:: int PyModule_AddIntConstant(PyObject *module, const char *name, long value)
static PyObject *SpamError;
and initialize it in your module's initialization function (:c:func:`PyInit_spam`)
-with an exception object (leaving out the error checking for now)::
+with an exception object::
PyMODINIT_FUNC
PyInit_spam(void)
return NULL;
SpamError = PyErr_NewException("spam.error", NULL, NULL);
- Py_INCREF(SpamError);
- PyModule_AddObject(m, "error", SpamError);
+ Py_XINCREF(SpamError);
+ if (PyModule_AddObject(m, "error", SpamError) < 0) {
+ Py_XDECREF(SpamError);
+ Py_CLEAR(SpamError);
+ Py_DECREF(m);
+ return NULL;
+ }
+
return m;
}
/* Create a Capsule containing the API pointer array's address */
c_api_object = PyCapsule_New((void *)PySpam_API, "spam._C_API", NULL);
- if (c_api_object != NULL)
- PyModule_AddObject(m, "_C_API", c_api_object);
+ if (PyModule_AddObject(m, "_C_API", c_api_object) < 0) {
+ Py_XDECREF(c_api_object);
+ Py_DECREF(m);
+ return NULL;
+ }
+
return m;
}
to the appropriate default values, including :attr:`ob_type` that we initially
set to *NULL*. ::
- PyModule_AddObject(m, "Custom", (PyObject *) &CustomType);
+ Py_INCREF(&CustomType);
+ if (PyModule_AddObject(m, "Custom", (PyObject *) &CustomType) < 0) {
+ Py_DECREF(&CustomType);
+ PY_DECREF(m);
+ return NULL;
+ }
This adds the type to the module dictionary. This allows us to create
:class:`Custom` instances by calling the :class:`Custom` class:
return NULL;
Py_INCREF(&SubListType);
- PyModule_AddObject(m, "SubList", (PyObject *) &SubListType);
+ if (PyModule_AddObject(m, "SubList", (PyObject *) &SubListType) < 0) {
+ Py_DECREF(&SubListType);
+ Py_DECREF(m);
+ return NULL;
+ }
+
return m;
}
return NULL;
Py_INCREF(&CustomType);
- PyModule_AddObject(m, "Custom", (PyObject *) &CustomType);
+ if (PyModule_AddObject(m, "Custom", (PyObject *) &CustomType) < 0) {
+ Py_DECREF(&CustomType);
+ PY_DECREF(m);
+ return NULL;
+ }
+
return m;
}
return NULL;
Py_INCREF(&CustomType);
- PyModule_AddObject(m, "Custom", (PyObject *) &CustomType);
+ if (PyModule_AddObject(m, "Custom", (PyObject *) &CustomType) < 0) {
+ Py_DECREF(&CustomType);
+ Py_DECREF(m);
+ return NULL;
+ }
+
return m;
}
return NULL;
Py_INCREF(&CustomType);
- PyModule_AddObject(m, "Custom", (PyObject *) &CustomType);
+ if (PyModule_AddObject(m, "Custom", (PyObject *) &CustomType) < 0) {
+ Py_DECREF(&CustomType);
+ Py_DECREF(m);
+ return NULL;
+ }
+
return m;
}
return NULL;
Py_INCREF(&CustomType);
- PyModule_AddObject(m, "Custom", (PyObject *) &CustomType);
+ if (PyModule_AddObject(m, "Custom", (PyObject *) &CustomType) < 0) {
+ Py_DECREF(&CustomType);
+ Py_DECREF(m);
+ return NULL;
+ }
+
return m;
}
return NULL;
Py_INCREF(&SubListType);
- PyModule_AddObject(m, "SubList", (PyObject *) &SubListType);
+ if (PyModule_AddObject(m, "SubList", (PyObject *) &SubListType) < 0) {
+ Py_DECREF(&SubListType);
+ Py_DECREF(m);
+ return NULL;
+ }
+
return m;
}
--- /dev/null
+Fix example usage of :c:func:`PyModule_AddObject` to properly handle errors.
\ No newline at end of file