Skip to content

Commit 05ac6de

Browse files
committed
Add PyDict_Merge(a, b, override):
PyDict_Merge(a, b, 1) is the same as PyDict_Update(a, b). PyDict_Merge(a, b, 0) does something similar but leaves existing items unchanged.
1 parent f4aa684 commit 05ac6de

File tree

2 files changed

+19
-2
lines changed

2 files changed

+19
-2
lines changed

Include/dictobject.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ extern DL_IMPORT(PyObject *) PyDict_Items(PyObject *mp);
9898
extern DL_IMPORT(int) PyDict_Size(PyObject *mp);
9999
extern DL_IMPORT(PyObject *) PyDict_Copy(PyObject *mp);
100100
extern DL_IMPORT(int) PyDict_Update(PyObject *mp, PyObject *other);
101+
extern DL_IMPORT(int) PyDict_Merge(PyObject *mp, PyObject *other, int override);
101102

102103

103104
extern DL_IMPORT(PyObject *) PyDict_GetItemString(PyObject *dp, char *key);

Objects/dictobject.c

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -999,8 +999,18 @@ dict_update(PyObject *mp, PyObject *args)
999999
return Py_None;
10001000
}
10011001

1002+
/* Update unconditionally replaces existing items.
1003+
Merge has a 3rd argument 'override'; if set, it acts like Update,
1004+
otherwise it leaves existing items unchanged. */
1005+
10021006
int
10031007
PyDict_Update(PyObject *a, PyObject *b)
1008+
{
1009+
return PyDict_Merge(a, b, 1);
1010+
}
1011+
1012+
int
1013+
PyDict_Merge(PyObject *a, PyObject *b, int override)
10041014
{
10051015
register PyDictObject *mp, *other;
10061016
register int i;
@@ -1031,7 +1041,9 @@ PyDict_Update(PyObject *a, PyObject *b)
10311041
}
10321042
for (i = 0; i <= other->ma_mask; i++) {
10331043
entry = &other->ma_table[i];
1034-
if (entry->me_value != NULL) {
1044+
if (entry->me_value != NULL &&
1045+
(override ||
1046+
PyDict_GetItem(a, entry->me_key) == NULL)) {
10351047
Py_INCREF(entry->me_key);
10361048
Py_INCREF(entry->me_value);
10371049
insertdict(mp, entry->me_key, entry->me_hash,
@@ -1060,13 +1072,17 @@ PyDict_Update(PyObject *a, PyObject *b)
10601072
return -1;
10611073

10621074
for (key = PyIter_Next(iter); key; key = PyIter_Next(iter)) {
1075+
if (!override && PyDict_GetItem(a, key) != NULL) {
1076+
Py_DECREF(key);
1077+
continue;
1078+
}
10631079
value = PyObject_GetItem(b, key);
10641080
if (value == NULL) {
10651081
Py_DECREF(iter);
10661082
Py_DECREF(key);
10671083
return -1;
10681084
}
1069-
status = PyDict_SetItem((PyObject*)mp, key, value);
1085+
status = PyDict_SetItem(a, key, value);
10701086
Py_DECREF(key);
10711087
Py_DECREF(value);
10721088
if (status < 0) {

0 commit comments

Comments
 (0)