]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
bpo-36144: Add union operators to WeakKeyDictionary (#19106)
authorCurtis Bucher <cpbucher5@gmail.com>
Mon, 23 Mar 2020 20:49:46 +0000 (13:49 -0700)
committerGitHub <noreply@github.com>
Mon, 23 Mar 2020 20:49:46 +0000 (13:49 -0700)
Doc/library/weakref.rst
Lib/test/test_weakref.py
Lib/weakref.py
Misc/NEWS.d/next/Library/2020-03-18-14-02-58.bpo-36144.ooyn6Z.rst [new file with mode: 0644]

index 8636e76c52a420e89536ab3d7793e6d73a753496..c10f436bea4c4e4e11862d7416b6b88b2d7590ae 100644 (file)
@@ -171,6 +171,9 @@ Extension types can easily be made to support weak references; see
       performed by the program during iteration may cause items in the
       dictionary to vanish "by magic" (as a side effect of garbage collection).
 
+   .. versionchanged:: 3.9
+      Added support for ``|`` and ``|=`` operators, specified in :pep:`584`.
+
 :class:`WeakKeyDictionary` objects have an additional method that
 exposes the internal references directly.  The references are not guaranteed to
 be "live" at the time they are used, so the result of calling the references
index 63c725527d5f25a5e70f46c840522a806f558da8..250ed40b20ca5c442338b310419f109fef1fb448 100644 (file)
@@ -1624,6 +1624,43 @@ class MappingTestCase(TestBase):
         self.assertEqual(len(d), 1)
         self.assertEqual(list(d.keys()), [o2])
 
+    def test_weak_keyed_union_operators(self):
+        o1 = C()
+        o2 = C()
+        o3 = C()
+        wkd1 = weakref.WeakKeyDictionary({o1: 1, o2: 2})
+        wkd2 = weakref.WeakKeyDictionary({o3: 3, o1: 4})
+        wkd3 = wkd1.copy()
+        d1 = {o2: '5', o3: '6'}
+        pairs = [(o2, 7), (o3, 8)]
+
+        tmp1 = wkd1 | wkd2 # Between two WeakKeyDictionaries
+        self.assertEqual(dict(tmp1), dict(wkd1) | dict(wkd2))
+        self.assertIs(type(tmp1), weakref.WeakKeyDictionary)
+        wkd1 |= wkd2
+        self.assertEqual(wkd1, tmp1)
+
+        tmp2 = wkd2 | d1 # Between WeakKeyDictionary and mapping
+        self.assertEqual(dict(tmp2), dict(wkd2) | d1)
+        self.assertIs(type(tmp2), weakref.WeakKeyDictionary)
+        wkd2 |= d1
+        self.assertEqual(wkd2, tmp2)
+
+        tmp3 = wkd3.copy() # Between WeakKeyDictionary and iterable key, value
+        tmp3 |= pairs
+        self.assertEqual(dict(tmp3), dict(wkd3) | dict(pairs))
+        self.assertIs(type(tmp3), weakref.WeakKeyDictionary)
+
+        tmp4 = d1 | wkd3 # Testing .__ror__
+        self.assertEqual(dict(tmp4), d1 | dict(wkd3))
+        self.assertIs(type(tmp4), weakref.WeakKeyDictionary)
+
+        del o1
+        self.assertNotIn(4, tmp1.values())
+        self.assertNotIn(4, tmp2.values())
+        self.assertNotIn(1, tmp3.values())
+        self.assertNotIn(1, tmp4.values())
+
     def test_weak_valued_delitem(self):
         d = weakref.WeakValueDictionary()
         o1 = Object('1')
index e3c2ce2d9b8b865d9e3a8183c4fcd42f49571fba..759ad6dfa39b4405674b2c21b6626c328f8422c9 100644 (file)
@@ -488,6 +488,25 @@ class WeakKeyDictionary(_collections_abc.MutableMapping):
         if len(kwargs):
             self.update(kwargs)
 
+    def __ior__(self, other):
+        self.update(other)
+        return self
+
+    def __or__(self, other):
+        if isinstance(other, _collections_abc.Mapping):
+            c = self.copy()
+            c.update(other)
+            return c
+        return NotImplemented
+
+    def __ror__(self, other):
+        if isinstance(other, _collections_abc.Mapping):
+            c = self.__class__()
+            c.update(other)
+            c.update(self)
+            return c
+        return NotImplemented
+
 
 class finalize:
     """Class for finalization of weakrefable objects
diff --git a/Misc/NEWS.d/next/Library/2020-03-18-14-02-58.bpo-36144.ooyn6Z.rst b/Misc/NEWS.d/next/Library/2020-03-18-14-02-58.bpo-36144.ooyn6Z.rst
new file mode 100644 (file)
index 0000000..262653a
--- /dev/null
@@ -0,0 +1 @@
+Added :pep:`584` operators to :class:`weakref.WeakKeyDictionary`.