summaryrefslogtreecommitdiffstats
path: root/Objects
diff options
context:
space:
mode:
authorBrandt Bucher <brandtbucher@gmail.com>2020-02-25 03:47:34 (GMT)
committerGitHub <noreply@github.com>2020-02-25 03:47:34 (GMT)
commiteb8ac57af26c4eb96a8230eba7492ce5ceef7886 (patch)
treea19866e216c6c7ef6c75de0f653bf653cc55ac67 /Objects
parentba22e8f174309979d90047c5dc64fcb63bc2c32e (diff)
downloadcpython-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.c71
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 */