summaryrefslogtreecommitdiffstats
path: root/Lib
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 /Lib
parentba22e8f174309979d90047c5dc64fcb63bc2c32e (diff)
downloadcpython-eb8ac57af26c4eb96a8230eba7492ce5ceef7886.zip
cpython-eb8ac57af26c4eb96a8230eba7492ce5ceef7886.tar.gz
cpython-eb8ac57af26c4eb96a8230eba7492ce5ceef7886.tar.bz2
bpo-36144: Dictionary Union (PEP 584) (#12088)
Diffstat (limited to 'Lib')
-rw-r--r--Lib/collections/__init__.py20
-rw-r--r--Lib/test/test_dict.py32
2 files changed, 52 insertions, 0 deletions
diff --git a/Lib/collections/__init__.py b/Lib/collections/__init__.py
index 178cdb1..1aa7d10 100644
--- a/Lib/collections/__init__.py
+++ b/Lib/collections/__init__.py
@@ -994,6 +994,26 @@ class UserDict(_collections_abc.MutableMapping):
# Now, add the methods in dicts but not in MutableMapping
def __repr__(self): return repr(self.data)
+
+ def __or__(self, other):
+ if isinstance(other, UserDict):
+ return self.__class__(self.data | other.data)
+ if isinstance(other, dict):
+ return self.__class__(self.data | other)
+ return NotImplemented
+ def __ror__(self, other):
+ if isinstance(other, UserDict):
+ return self.__class__(other.data | self.data)
+ if isinstance(other, dict):
+ return self.__class__(other | self.data)
+ return NotImplemented
+ def __ior__(self, other):
+ if isinstance(other, UserDict):
+ self.data |= other.data
+ else:
+ self.data |= other
+ return self
+
def __copy__(self):
inst = self.__class__.__new__(self.__class__)
inst.__dict__.update(self.__dict__)
diff --git a/Lib/test/test_dict.py b/Lib/test/test_dict.py
index de483ab..d5a3d9e 100644
--- a/Lib/test/test_dict.py
+++ b/Lib/test/test_dict.py
@@ -37,6 +37,38 @@ class DictTest(unittest.TestCase):
dictliteral = '{' + ', '.join(formatted_items) + '}'
self.assertEqual(eval(dictliteral), dict(items))
+ def test_merge_operator(self):
+
+ a = {0: 0, 1: 1, 2: 1}
+ b = {1: 1, 2: 2, 3: 3}
+
+ c = a.copy()
+ c |= b
+
+ self.assertEqual(a | b, {0: 0, 1: 1, 2: 2, 3: 3})
+ self.assertEqual(c, {0: 0, 1: 1, 2: 2, 3: 3})
+
+ c = b.copy()
+ c |= a
+
+ self.assertEqual(b | a, {1: 1, 2: 1, 3: 3, 0: 0})
+ self.assertEqual(c, {1: 1, 2: 1, 3: 3, 0: 0})
+
+ c = a.copy()
+ c |= [(1, 1), (2, 2), (3, 3)]
+
+ self.assertEqual(c, {0: 0, 1: 1, 2: 2, 3: 3})
+
+ self.assertIs(a.__or__(None), NotImplemented)
+ self.assertIs(a.__or__(()), NotImplemented)
+ self.assertIs(a.__or__("BAD"), NotImplemented)
+ self.assertIs(a.__or__(""), NotImplemented)
+
+ self.assertRaises(TypeError, a.__ior__, None)
+ self.assertEqual(a.__ior__(()), {0: 0, 1: 1, 2: 1})
+ self.assertRaises(ValueError, a.__ior__, "BAD")
+ self.assertEqual(a.__ior__(""), {0: 0, 1: 1, 2: 1})
+
def test_bool(self):
self.assertIs(not {}, True)
self.assertTrue({1: 2})