diff options
author | Brandt Bucher <brandtbucher@gmail.com> | 2020-02-25 03:47:34 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-02-25 03:47:34 (GMT) |
commit | eb8ac57af26c4eb96a8230eba7492ce5ceef7886 (patch) | |
tree | a19866e216c6c7ef6c75de0f653bf653cc55ac67 /Objects | |
parent | ba22e8f174309979d90047c5dc64fcb63bc2c32e (diff) | |
download | cpython-eb8ac57af26c4eb96a8230eba7492ce5ceef7886.zip cpython-eb8ac57af26c4eb96a8230eba7492ce5ceef7886.tar.gz cpython-eb8ac57af26c4eb96a8230eba7492ce5ceef7886.tar.bz2 |
bpo-36144: Dictionary Union (PEP 584) (#12088)
Diffstat (limited to 'Objects')
-rw-r--r-- | Objects/dictobject.c | 71 |
1 files changed, 53 insertions, 18 deletions
diff --git a/Objects/dictobject.c b/Objects/dictobject.c index 86ac4ef..4aa927a 100644 --- a/Objects/dictobject.c +++ b/Objects/dictobject.c @@ -2320,6 +2320,25 @@ dict_fromkeys_impl(PyTypeObject *type, PyObject *iterable, PyObject *value) return _PyDict_FromKeys((PyObject *)type, iterable, value); } +/* Single-arg dict update; used by dict_update_common and operators. */ +static int +dict_update_arg(PyObject *self, PyObject *arg) +{ + if (PyDict_CheckExact(arg)) { + return PyDict_Merge(self, arg, 1); + } + _Py_IDENTIFIER(keys); + PyObject *func; + if (_PyObject_LookupAttrId(arg, &PyId_keys, &func) < 0) { + return -1; + } + if (func != NULL) { + Py_DECREF(func); + return PyDict_Merge(self, arg, 1); + } + return PyDict_MergeFromSeq2(self, arg, 1); +} + static int dict_update_common(PyObject *self, PyObject *args, PyObject *kwds, const char *methname) @@ -2331,23 +2350,7 @@ dict_update_common(PyObject *self, PyObject *args, PyObject *kwds, result = -1; } else if (arg != NULL) { - if (PyDict_CheckExact(arg)) { - result = PyDict_Merge(self, arg, 1); - } - else { - _Py_IDENTIFIER(keys); - PyObject *func; - if (_PyObject_LookupAttrId(arg, &PyId_keys, &func) < 0) { - result = -1; - } - else if (func != NULL) { - Py_DECREF(func); - result = PyDict_Merge(self, arg, 1); - } - else { - result = PyDict_MergeFromSeq2(self, arg, 1); - } - } + result = dict_update_arg(self, arg); } if (result == 0 && kwds != NULL) { @@ -3169,6 +3172,33 @@ dict_sizeof(PyDictObject *mp, PyObject *Py_UNUSED(ignored)) return PyLong_FromSsize_t(_PyDict_SizeOf(mp)); } +static PyObject * +dict_or(PyObject *self, PyObject *other) +{ + if (!PyDict_Check(self) || !PyDict_Check(other)) { + Py_RETURN_NOTIMPLEMENTED; + } + PyObject *new = PyDict_Copy(self); + if (new == NULL) { + return NULL; + } + if (dict_update_arg(new, other)) { + Py_DECREF(new); + return NULL; + } + return new; +} + +static PyObject * +dict_ior(PyObject *self, PyObject *other) +{ + if (dict_update_arg(self, other)) { + return NULL; + } + Py_INCREF(self); + return self; +} + PyDoc_STRVAR(getitem__doc__, "x.__getitem__(y) <==> x[y]"); PyDoc_STRVAR(sizeof__doc__, @@ -3274,6 +3304,11 @@ static PySequenceMethods dict_as_sequence = { 0, /* sq_inplace_repeat */ }; +static PyNumberMethods dict_as_number = { + .nb_or = dict_or, + .nb_inplace_or = dict_ior, +}; + static PyObject * dict_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { @@ -3335,7 +3370,7 @@ PyTypeObject PyDict_Type = { 0, /* tp_setattr */ 0, /* tp_as_async */ (reprfunc)dict_repr, /* tp_repr */ - 0, /* tp_as_number */ + &dict_as_number, /* tp_as_number */ &dict_as_sequence, /* tp_as_sequence */ &dict_as_mapping, /* tp_as_mapping */ PyObject_HashNotImplemented, /* tp_hash */ |