Skip to content

Commit 533e15c

Browse files
committed
Add PyDict_PopString() function
1 parent 4dd668c commit 533e15c

File tree

7 files changed

+43
-27
lines changed

7 files changed

+43
-27
lines changed

Doc/c-api/dict.rst

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,16 @@ Dictionary Objects
190190
191191
.. versionadded:: 3.13
192192
193+
194+
.. c:function:: int PyDict_PopString(PyObject *p, const char *key, PyObject **result)
195+
196+
Similar to :c:func:`PyDict_Pop`, but *key* is specified as a
197+
:c:expr:`const char*` UTF-8 encoded bytes string, rather than a
198+
:c:expr:`PyObject*`.
199+
200+
.. versionadded:: 3.13
201+
202+
193203
.. c:function:: PyObject* PyDict_Items(PyObject *p)
194204
195205
Return a :c:type:`PyListObject` containing all the items from the dictionary.

Doc/whatsnew/3.13.rst

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1164,10 +1164,10 @@ New Features
11641164
:c:func:`PyErr_WriteUnraisable`, but allow to customize the warning mesage.
11651165
(Contributed by Serhiy Storchaka in :gh:`108082`.)
11661166

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

11731173

Include/cpython/dictobject.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ static inline Py_ssize_t PyDict_GET_SIZE(PyObject *op) {
4747
PyAPI_FUNC(int) PyDict_ContainsString(PyObject *mp, const char *key);
4848

4949
PyAPI_FUNC(int) PyDict_Pop(PyObject *dict, PyObject *key, PyObject **result);
50+
PyAPI_FUNC(int) PyDict_PopString(PyObject *dict, const char *key, PyObject **result);
5051
PyAPI_FUNC(PyObject *) _PyDict_Pop(PyObject *dict, PyObject *key, PyObject *default_value);
5152

5253
/* Dictionary watchers */
Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
Add :c:func:`PyDict_Pop` function: remove a key from a dictionary and
2-
optionally return the removed value. This is the similar to :meth:`dict.pop`,
3-
but without the default value and do not raise :exc:`KeyError` if the key
4-
missing. Patch by Stefan Behnel and Victor Stinner.
1+
Add :c:func:`PyDict_Pop` and :c:func:`PyDict_PopString` functions: remove a key
2+
from a dictionary and optionally return the removed value. This is the similar
3+
to :meth:`dict.pop`, but without the default value and do not raise
4+
:exc:`KeyError` if the key missing. Patch by Stefan Behnel and Victor Stinner.

Modules/socketmodule.c

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -392,15 +392,10 @@ remove_unusable_flags(PyObject *m)
392392
break;
393393
}
394394
else {
395-
PyObject *flag_name = PyUnicode_FromString(win_runtime_flags[i].flag_name);
396-
if (flag_name == NULL) {
395+
if (PyDict_PopString(dict, win_runtime_flags[i].flag_name,
396+
NULL) < 0) {
397397
return -1;
398398
}
399-
if (PyDict_Pop(dict, flag_name, NULL) < 0) {
400-
Py_DECREF(flag_name);
401-
return -1;
402-
}
403-
Py_DECREF(flag_name);
404399
}
405400
}
406401
return 0;

Objects/dictobject.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2307,6 +2307,23 @@ PyDict_Pop(PyObject *op, PyObject *key, PyObject **result)
23072307
}
23082308

23092309

2310+
int
2311+
PyDict_PopString(PyObject *op, const char *key, PyObject **result)
2312+
{
2313+
PyObject *key_obj = PyUnicode_FromString(key);
2314+
if (key_obj == NULL) {
2315+
if (result != NULL) {
2316+
*result = NULL;
2317+
}
2318+
return -1;
2319+
}
2320+
2321+
int res = PyDict_Pop(op, key_obj, result);
2322+
Py_DECREF(key_obj);
2323+
return res;
2324+
}
2325+
2326+
23102327
PyObject *
23112328
_PyDict_Pop(PyObject *dict, PyObject *key, PyObject *default_value)
23122329
{

Objects/structseq.c

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -416,22 +416,15 @@ structseq_replace(PyStructSequence *self, PyObject *args, PyObject *kwargs)
416416
// We do not support types with unnamed fields, so we can iterate over
417417
// i >= n_visible_fields case without slicing with (i - n_unnamed_fields).
418418
for (i = 0; i < n_fields; ++i) {
419-
PyObject *key = PyUnicode_FromString(Py_TYPE(self)->tp_members[i].name);
420-
if (!key) {
421-
goto error;
422-
}
423419
PyObject *ob;
424-
if (PyDict_Pop(kwargs, key, &ob) < 0) {
425-
Py_DECREF(key);
420+
if (PyDict_PopString(kwargs, Py_TYPE(self)->tp_members[i].name,
421+
&ob) < 0) {
426422
goto error;
427423
}
428-
Py_DECREF(key);
429-
if (ob != NULL) {
430-
result->ob_item[i] = ob;
431-
}
432-
else {
433-
result->ob_item[i] = Py_NewRef(self->ob_item[i]);
424+
if (ob == NULL) {
425+
ob = Py_NewRef(self->ob_item[i]);
434426
}
427+
result->ob_item[i] = ob;
435428
}
436429
// Check if there are any unexpected fields.
437430
if (PyDict_GET_SIZE(kwargs) > 0) {

0 commit comments

Comments
 (0)