mirror of https://github.com/python/cpython
bpo-36144: Update MappingProxyType with PEP 584's operators (#18814)
We make `|=` raise TypeError, since it would be surprising if `C.__dict__ |= {'x': 0}` silently did nothing, while `C.__dict__.update({'x': 0})` is an error.
This commit is contained in:
parent
8f13053692
commit
4663f66f35
|
@ -282,6 +282,11 @@ Standard names are defined for the following types:
|
|||
|
||||
.. versionadded:: 3.3
|
||||
|
||||
.. versionchanged:: 3.9
|
||||
|
||||
Updated to support the new union (``|``) operator from :pep:`584`, which
|
||||
simply delegates to the underlying mapping.
|
||||
|
||||
.. describe:: key in proxy
|
||||
|
||||
Return ``True`` if the underlying mapping has a key *key*, else
|
||||
|
|
|
@ -622,8 +622,11 @@ class MappingProxyTests(unittest.TestCase):
|
|||
self.assertEqual(attrs, {
|
||||
'__contains__',
|
||||
'__getitem__',
|
||||
'__ior__',
|
||||
'__iter__',
|
||||
'__len__',
|
||||
'__or__',
|
||||
'__ror__',
|
||||
'copy',
|
||||
'get',
|
||||
'items',
|
||||
|
@ -774,6 +777,22 @@ class MappingProxyTests(unittest.TestCase):
|
|||
self.assertEqual(view['key1'], 70)
|
||||
self.assertEqual(copy['key1'], 27)
|
||||
|
||||
def test_union(self):
|
||||
mapping = {'a': 0, 'b': 1, 'c': 2}
|
||||
view = self.mappingproxy(mapping)
|
||||
with self.assertRaises(TypeError):
|
||||
view | [('r', 2), ('d', 2)]
|
||||
with self.assertRaises(TypeError):
|
||||
[('r', 2), ('d', 2)] | view
|
||||
with self.assertRaises(TypeError):
|
||||
view |= [('r', 2), ('d', 2)]
|
||||
other = {'c': 3, 'p': 0}
|
||||
self.assertDictEqual(view | other, {'a': 0, 'b': 1, 'c': 3, 'p': 0})
|
||||
self.assertDictEqual(other | view, {'c': 2, 'p': 0, 'a': 0, 'b': 1})
|
||||
self.assertEqual(view, {'a': 0, 'b': 1, 'c': 2})
|
||||
self.assertDictEqual(mapping, {'a': 0, 'b': 1, 'c': 2})
|
||||
self.assertDictEqual(other, {'c': 3, 'p': 0})
|
||||
|
||||
|
||||
class ClassCreationTests(unittest.TestCase):
|
||||
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
:class:`types.MappingProxyType` objects now support the merge (``|``) operator
|
||||
from :pep:`584`.
|
|
@ -982,6 +982,30 @@ static PyMappingMethods mappingproxy_as_mapping = {
|
|||
0, /* mp_ass_subscript */
|
||||
};
|
||||
|
||||
static PyObject *
|
||||
mappingproxy_or(PyObject *left, PyObject *right)
|
||||
{
|
||||
if (PyObject_TypeCheck(left, &PyDictProxy_Type)) {
|
||||
left = ((mappingproxyobject*)left)->mapping;
|
||||
}
|
||||
if (PyObject_TypeCheck(right, &PyDictProxy_Type)) {
|
||||
right = ((mappingproxyobject*)right)->mapping;
|
||||
}
|
||||
return PyNumber_Or(left, right);
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
mappingproxy_ior(PyObject *self, PyObject *Py_UNUSED(other))
|
||||
{
|
||||
return PyErr_Format(PyExc_TypeError,
|
||||
"'|=' is not supported by %s; use '|' instead", Py_TYPE(self)->tp_name);
|
||||
}
|
||||
|
||||
static PyNumberMethods mappingproxy_as_number = {
|
||||
.nb_or = mappingproxy_or,
|
||||
.nb_inplace_or = mappingproxy_ior,
|
||||
};
|
||||
|
||||
static int
|
||||
mappingproxy_contains(mappingproxyobject *pp, PyObject *key)
|
||||
{
|
||||
|
@ -1717,7 +1741,7 @@ PyTypeObject PyDictProxy_Type = {
|
|||
0, /* tp_setattr */
|
||||
0, /* tp_as_async */
|
||||
(reprfunc)mappingproxy_repr, /* tp_repr */
|
||||
0, /* tp_as_number */
|
||||
&mappingproxy_as_number, /* tp_as_number */
|
||||
&mappingproxy_as_sequence, /* tp_as_sequence */
|
||||
&mappingproxy_as_mapping, /* tp_as_mapping */
|
||||
0, /* tp_hash */
|
||||
|
|
Loading…
Reference in New Issue