bpo-36144: Dictionary Union (PEP 584) (#12088)

This commit is contained in:
Brandt Bucher 2020-02-24 19:47:34 -08:00 committed by GitHub
parent ba22e8f174
commit eb8ac57af2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 107 additions and 18 deletions

View file

@ -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 */