Skip to content

Commit

Permalink
Add PyDict_PopString() function
Browse files Browse the repository at this point in the history
  • Loading branch information
vstinner committed Nov 13, 2023
1 parent 4dd668c commit 533e15c
Show file tree
Hide file tree
Showing 7 changed files with 43 additions and 27 deletions.
10 changes: 10 additions & 0 deletions Doc/c-api/dict.rst
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,16 @@ Dictionary Objects
.. versionadded:: 3.13
.. c:function:: int PyDict_PopString(PyObject *p, const char *key, PyObject **result)
Similar to :c:func:`PyDict_Pop`, but *key* is specified as a
:c:expr:`const char*` UTF-8 encoded bytes string, rather than a
:c:expr:`PyObject*`.
.. versionadded:: 3.13
.. c:function:: PyObject* PyDict_Items(PyObject *p)
Return a :c:type:`PyListObject` containing all the items from the dictionary.
Expand Down
8 changes: 4 additions & 4 deletions Doc/whatsnew/3.13.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1164,10 +1164,10 @@ New Features
:c:func:`PyErr_WriteUnraisable`, but allow to customize the warning mesage.
(Contributed by Serhiy Storchaka in :gh:`108082`.)

* Add :c:func:`PyDict_Pop` function: remove a key from a dictionary and
optionally return the removed value. This is the similar to :meth:`dict.pop`,
but without the default value and do not raise :exc:`KeyError` if the key
missing.
* Add :c:func:`PyDict_Pop` and :c:func:`PyDict_PopString` functions: remove a
key from a dictionary and optionally return the removed value. This is the
similar to :meth:`dict.pop`, but without the default value and do not raise
:exc:`KeyError` if the key missing.
(Contributed by Stefan Behnel and Victor Stinner in :gh:`111262`.)


Expand Down
1 change: 1 addition & 0 deletions Include/cpython/dictobject.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ static inline Py_ssize_t PyDict_GET_SIZE(PyObject *op) {
PyAPI_FUNC(int) PyDict_ContainsString(PyObject *mp, const char *key);

PyAPI_FUNC(int) PyDict_Pop(PyObject *dict, PyObject *key, PyObject **result);
PyAPI_FUNC(int) PyDict_PopString(PyObject *dict, const char *key, PyObject **result);
PyAPI_FUNC(PyObject *) _PyDict_Pop(PyObject *dict, PyObject *key, PyObject *default_value);

/* Dictionary watchers */
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Add :c:func:`PyDict_Pop` function: remove a key from a dictionary and
optionally return the removed value. This is the similar to :meth:`dict.pop`,
but without the default value and do not raise :exc:`KeyError` if the key
missing. Patch by Stefan Behnel and Victor Stinner.
Add :c:func:`PyDict_Pop` and :c:func:`PyDict_PopString` functions: remove a key
from a dictionary and optionally return the removed value. This is the similar
to :meth:`dict.pop`, but without the default value and do not raise
:exc:`KeyError` if the key missing. Patch by Stefan Behnel and Victor Stinner.
9 changes: 2 additions & 7 deletions Modules/socketmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -392,15 +392,10 @@ remove_unusable_flags(PyObject *m)
break;
}
else {
PyObject *flag_name = PyUnicode_FromString(win_runtime_flags[i].flag_name);
if (flag_name == NULL) {
if (PyDict_PopString(dict, win_runtime_flags[i].flag_name,
NULL) < 0) {
return -1;
}
if (PyDict_Pop(dict, flag_name, NULL) < 0) {
Py_DECREF(flag_name);
return -1;
}
Py_DECREF(flag_name);
}
}
return 0;
Expand Down
17 changes: 17 additions & 0 deletions Objects/dictobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -2307,6 +2307,23 @@ PyDict_Pop(PyObject *op, PyObject *key, PyObject **result)
}


int
PyDict_PopString(PyObject *op, const char *key, PyObject **result)
{
PyObject *key_obj = PyUnicode_FromString(key);
if (key_obj == NULL) {
if (result != NULL) {
*result = NULL;
}
return -1;
}

int res = PyDict_Pop(op, key_obj, result);
Py_DECREF(key_obj);
return res;
}


PyObject *
_PyDict_Pop(PyObject *dict, PyObject *key, PyObject *default_value)
{
Expand Down
17 changes: 5 additions & 12 deletions Objects/structseq.c
Original file line number Diff line number Diff line change
Expand Up @@ -416,22 +416,15 @@ structseq_replace(PyStructSequence *self, PyObject *args, PyObject *kwargs)
// We do not support types with unnamed fields, so we can iterate over
// i >= n_visible_fields case without slicing with (i - n_unnamed_fields).
for (i = 0; i < n_fields; ++i) {
PyObject *key = PyUnicode_FromString(Py_TYPE(self)->tp_members[i].name);
if (!key) {
goto error;
}
PyObject *ob;
if (PyDict_Pop(kwargs, key, &ob) < 0) {
Py_DECREF(key);
if (PyDict_PopString(kwargs, Py_TYPE(self)->tp_members[i].name,
&ob) < 0) {
goto error;
}
Py_DECREF(key);
if (ob != NULL) {
result->ob_item[i] = ob;
}
else {
result->ob_item[i] = Py_NewRef(self->ob_item[i]);
if (ob == NULL) {
ob = Py_NewRef(self->ob_item[i]);
}
result->ob_item[i] = ob;
}
// Check if there are any unexpected fields.
if (PyDict_GET_SIZE(kwargs) > 0) {
Expand Down

0 comments on commit 533e15c

Please sign in to comment.