mirror of
https://github.com/python/cpython.git
synced 2025-08-04 00:48:58 +00:00
gh-111262: Add PyDict_Pop() function (#112028)
_PyDict_Pop_KnownHash(): remove the default value and the return type becomes an int. Co-authored-by: Stefan Behnel <stefan_ml@behnel.de> Co-authored-by: Antoine Pitrou <pitrou@free.fr>
This commit is contained in:
parent
f44d6ff6e0
commit
4f04172c92
15 changed files with 338 additions and 76 deletions
|
@ -2226,64 +2226,119 @@ PyDict_Next(PyObject *op, Py_ssize_t *ppos, PyObject **pkey, PyObject **pvalue)
|
|||
return _PyDict_Next(op, ppos, pkey, pvalue, NULL);
|
||||
}
|
||||
|
||||
/* Internal version of dict.pop(). */
|
||||
PyObject *
|
||||
_PyDict_Pop_KnownHash(PyObject *dict, PyObject *key, Py_hash_t hash, PyObject *deflt)
|
||||
{
|
||||
Py_ssize_t ix;
|
||||
PyObject *old_value;
|
||||
PyDictObject *mp;
|
||||
PyInterpreterState *interp = _PyInterpreterState_GET();
|
||||
|
||||
assert(PyDict_Check(dict));
|
||||
mp = (PyDictObject *)dict;
|
||||
/* Internal version of dict.pop(). */
|
||||
int
|
||||
_PyDict_Pop_KnownHash(PyDictObject *mp, PyObject *key, Py_hash_t hash,
|
||||
PyObject **result)
|
||||
{
|
||||
assert(PyDict_Check(mp));
|
||||
|
||||
if (mp->ma_used == 0) {
|
||||
if (deflt) {
|
||||
return Py_NewRef(deflt);
|
||||
if (result) {
|
||||
*result = NULL;
|
||||
}
|
||||
_PyErr_SetKeyError(key);
|
||||
return NULL;
|
||||
return 0;
|
||||
}
|
||||
ix = _Py_dict_lookup(mp, key, hash, &old_value);
|
||||
if (ix == DKIX_ERROR)
|
||||
return NULL;
|
||||
|
||||
PyObject *old_value;
|
||||
Py_ssize_t ix = _Py_dict_lookup(mp, key, hash, &old_value);
|
||||
if (ix == DKIX_ERROR) {
|
||||
if (result) {
|
||||
*result = NULL;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ix == DKIX_EMPTY || old_value == NULL) {
|
||||
if (deflt) {
|
||||
return Py_NewRef(deflt);
|
||||
if (result) {
|
||||
*result = NULL;
|
||||
}
|
||||
_PyErr_SetKeyError(key);
|
||||
return NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
assert(old_value != NULL);
|
||||
PyInterpreterState *interp = _PyInterpreterState_GET();
|
||||
uint64_t new_version = _PyDict_NotifyEvent(
|
||||
interp, PyDict_EVENT_DELETED, mp, key, NULL);
|
||||
delitem_common(mp, hash, ix, Py_NewRef(old_value), new_version);
|
||||
|
||||
ASSERT_CONSISTENT(mp);
|
||||
return old_value;
|
||||
if (result) {
|
||||
*result = old_value;
|
||||
}
|
||||
else {
|
||||
Py_DECREF(old_value);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
PyObject *
|
||||
_PyDict_Pop(PyObject *dict, PyObject *key, PyObject *deflt)
|
||||
{
|
||||
Py_hash_t hash;
|
||||
|
||||
if (((PyDictObject *)dict)->ma_used == 0) {
|
||||
if (deflt) {
|
||||
return Py_NewRef(deflt);
|
||||
int
|
||||
PyDict_Pop(PyObject *op, PyObject *key, PyObject **result)
|
||||
{
|
||||
if (!PyDict_Check(op)) {
|
||||
if (result) {
|
||||
*result = NULL;
|
||||
}
|
||||
PyErr_BadInternalCall();
|
||||
return -1;
|
||||
}
|
||||
PyDictObject *dict = (PyDictObject *)op;
|
||||
|
||||
if (dict->ma_used == 0) {
|
||||
if (result) {
|
||||
*result = NULL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
Py_hash_t hash;
|
||||
if (!PyUnicode_CheckExact(key) || (hash = unicode_get_hash(key)) == -1) {
|
||||
hash = PyObject_Hash(key);
|
||||
if (hash == -1) {
|
||||
if (result) {
|
||||
*result = NULL;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return _PyDict_Pop_KnownHash(dict, key, hash, 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)
|
||||
{
|
||||
PyObject *result;
|
||||
if (PyDict_Pop(dict, key, &result) == 0) {
|
||||
if (default_value != NULL) {
|
||||
return Py_NewRef(default_value);
|
||||
}
|
||||
_PyErr_SetKeyError(key);
|
||||
return NULL;
|
||||
}
|
||||
if (!PyUnicode_CheckExact(key) || (hash = unicode_get_hash(key)) == -1) {
|
||||
hash = PyObject_Hash(key);
|
||||
if (hash == -1)
|
||||
return NULL;
|
||||
}
|
||||
return _PyDict_Pop_KnownHash(dict, key, hash, deflt);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/* Internal version of dict.from_keys(). It is subclass-friendly. */
|
||||
PyObject *
|
||||
_PyDict_FromKeys(PyObject *cls, PyObject *iterable, PyObject *value)
|
||||
|
|
|
@ -1049,7 +1049,10 @@ _odict_popkey_hash(PyObject *od, PyObject *key, PyObject *failobj,
|
|||
return NULL;
|
||||
}
|
||||
/* Now delete the value from the dict. */
|
||||
value = _PyDict_Pop_KnownHash(od, key, hash, failobj);
|
||||
if (_PyDict_Pop_KnownHash((PyDictObject *)od, key, hash,
|
||||
&value) == 0) {
|
||||
value = Py_NewRef(failobj);
|
||||
}
|
||||
}
|
||||
else if (value == NULL && !PyErr_Occurred()) {
|
||||
/* Apply the fallback value, if necessary. */
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
*/
|
||||
|
||||
#include "Python.h"
|
||||
#include "pycore_dict.h" // _PyDict_Pop()
|
||||
#include "pycore_initconfig.h" // _PyStatus_OK()
|
||||
#include "pycore_modsupport.h" // _PyArg_NoPositional()
|
||||
#include "pycore_object.h" // _PyObject_GC_TRACK()
|
||||
|
@ -417,14 +416,13 @@ 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) {
|
||||
PyObject *ob;
|
||||
if (PyDict_PopString(kwargs, Py_TYPE(self)->tp_members[i].name,
|
||||
&ob) < 0) {
|
||||
goto error;
|
||||
}
|
||||
PyObject *ob = _PyDict_Pop(kwargs, key, self->ob_item[i]);
|
||||
Py_DECREF(key);
|
||||
if (!ob) {
|
||||
goto error;
|
||||
if (ob == NULL) {
|
||||
ob = Py_NewRef(self->ob_item[i]);
|
||||
}
|
||||
result->ob_item[i] = ob;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue