Repository navigation
Provide a variant of PyDict_SetDefault that returns a new reference (instead of a borrowed reference) #112066
Copy link
Copy link
Closed
Labels
3.13only security fixesonly security fixestopic-C-APItopic-free-threadingtype-featureA feature request or enhancementA feature request or enhancement
Description
Activity
- addedtype-featureA feature request or enhancementA feature request or enhancement3.13only security fixesonly security fixes
on Nov 14, 2023 Following previous API such as
PyDict_GetItemRef()andPyDict_Pop(), I propose the following API:int PyDict_SetDefaultRef(PyObject *dict, PyObject *key, PyObject *default_value, **value)- If key is present in dict, set
*valueto a new reference to the current value if value is not NULL, and return 1. - If key is missing in dict, set key to default_value in dict, set
*valueto a new reference to the default_value if value is not NULL, and return 0. - On error, set
*valueto NULL if value is not NULL, and return -1.
So value can be NULL if the value is not used.
See also API evolution: Return value conventions.
Reacted by Serhiy Storchaka, Sam Gross, Erlend E. Aasland and Kirill Podoprigora- If key is present in dict, set
@vstinner - sounds good. I updated the issue description with your proposal.
Do you want to propose a PR?
Reacted by Sam Gross- added a commit that references this issue
on Nov 15, 2023
Metadata
Metadata
Assignees
Labels
3.13only security fixesonly security fixestopic-C-APItopic-free-threadingtype-featureA feature request or enhancementA feature request or enhancement
The
PyDict_SetDefault(mp, key, defaultobj)function returns a borrowed reference to the value corresponding to key. This poses a thread-safety issue particularly for the case wherekeyis already in the dict. In the--disable-gilbuilds, the returned value may no longer be valid if another thread concurrently modifies the dict.Proposal (from Victor)
int PyDict_SetDefaultRef(PyObject *dict, PyObject *key, PyObject *default_value, PyObject **value);The
**valuepointer is optional. If it is NULL, it is not used.*valueto a new reference to the current value (ifvalueis not NULL), and return 1.*valueto a new reference todefault_value(if value is not NULL), and return 0.*valuetoNULLifvalueis notNULL, and return -1.Ideally, this new function would be public and part of the stable ABI so that it could be used by all extensions, but even an internal-only function would unblock some of the nogil changes.
EDIT: Updated with @vstinner's proposal
Linked PRs
PyDict_SetDefaultReffunction. #112123PyDict_SetDefaultRefin place ofPyDict_SetDefault. #112211