Closed vstinner closed 2 months ago
I feel that promoting good hygiene is not a sufficient reason to add a new API, especially one that can already be expressed as PySequence_GetItem
.
I feel that promoting good hygiene is not a sufficient reason to add a new API, especially one that can already be expressed as PySequence_GetItem.
Does it look useful to add a sentence to such functions to clearly mention that they return borrowed references, and suggest an alternative returning strong references?
For example, for PyTuple_GetItem:
Return a borrowed reference. Use Py_NewRef() or PySequence_GetItem()
to get a strong reference.
IMO it would be useful to say what the reference is borrowed from, something like:
Return a borrowed reference. The reference is borrowed from *p* (that is: it is only valid
as long as you hold a reference to *p*).
To get a strong reference, use `PySequence_GetItem(...)` or `Py_NewRef(PyTuple_GetItem(...))`.
IMO it would be useful to say what the reference is borrowed from, something like:
Good idea. I created https://github.com/python/cpython/pull/117920 for the doc.
Let's (gradually) start using this kind of wording for borrowed references throughout the docs.
@encukou: I think that is a good idea. Let's make sure we get the first doc amendment right, so it will be a good example to follow.
I feel that promoting good hygiene is not a sufficient reason to add a new API, especially one that can already be expressed as PySequence_GetItem.
It's not the first time that I propose adding PyTuple_GetItemRef(). The consensus is against adding such function.
I will continue the road of better documentation, it cannot hurt :-) I close this issue.
API:
PyObject* PyTuple_GetItemRef(PyObject *p, Py_ssize_t pos)
.While Free Threading (PEP 703) doesn't need this function, I propose to add functions which return strong references to proactively promote the usage of strong references.
Borrowed references have a long history of bugs and crashes. Usually, it's hard to trigger them, but if you're affected, it's hard to workaround them. The fix is usually to use a strong reference.
Example from
_asyncio.Future.remove_done_callback
holding explicitly a strong reference to prevent a possible crash:The code explicitly holds a strong reference to the
item
tuple while callingPyObject_RichCompareBool()
, sincePyObject_RichCompareBool()
can call arbitrary Python code in__eq__()
methods.These INCREF/DECREF were added by https://github.com/python/cpython/commit/bca4939d806170c3ca5d05f23710d11a8f1669cf "Fixed miscellaneous errors in asyncio speedup module".