mirror of
https://github.com/python/cpython.git
synced 2025-11-03 03:22:27 +00:00
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
4 changed files with 51 additions and 1 deletions
|
|
@ -282,6 +282,11 @@ Standard names are defined for the following types:
|
||||||
|
|
||||||
.. versionadded:: 3.3
|
.. 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
|
.. describe:: key in proxy
|
||||||
|
|
||||||
Return ``True`` if the underlying mapping has a key *key*, else
|
Return ``True`` if the underlying mapping has a key *key*, else
|
||||||
|
|
|
||||||
|
|
@ -622,8 +622,11 @@ class MappingProxyTests(unittest.TestCase):
|
||||||
self.assertEqual(attrs, {
|
self.assertEqual(attrs, {
|
||||||
'__contains__',
|
'__contains__',
|
||||||
'__getitem__',
|
'__getitem__',
|
||||||
|
'__ior__',
|
||||||
'__iter__',
|
'__iter__',
|
||||||
'__len__',
|
'__len__',
|
||||||
|
'__or__',
|
||||||
|
'__ror__',
|
||||||
'copy',
|
'copy',
|
||||||
'get',
|
'get',
|
||||||
'items',
|
'items',
|
||||||
|
|
@ -774,6 +777,22 @@ class MappingProxyTests(unittest.TestCase):
|
||||||
self.assertEqual(view['key1'], 70)
|
self.assertEqual(view['key1'], 70)
|
||||||
self.assertEqual(copy['key1'], 27)
|
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):
|
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 */
|
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
|
static int
|
||||||
mappingproxy_contains(mappingproxyobject *pp, PyObject *key)
|
mappingproxy_contains(mappingproxyobject *pp, PyObject *key)
|
||||||
{
|
{
|
||||||
|
|
@ -1717,7 +1741,7 @@ PyTypeObject PyDictProxy_Type = {
|
||||||
0, /* tp_setattr */
|
0, /* tp_setattr */
|
||||||
0, /* tp_as_async */
|
0, /* tp_as_async */
|
||||||
(reprfunc)mappingproxy_repr, /* tp_repr */
|
(reprfunc)mappingproxy_repr, /* tp_repr */
|
||||||
0, /* tp_as_number */
|
&mappingproxy_as_number, /* tp_as_number */
|
||||||
&mappingproxy_as_sequence, /* tp_as_sequence */
|
&mappingproxy_as_sequence, /* tp_as_sequence */
|
||||||
&mappingproxy_as_mapping, /* tp_as_mapping */
|
&mappingproxy_as_mapping, /* tp_as_mapping */
|
||||||
0, /* tp_hash */
|
0, /* tp_hash */
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue