diff options
author | Curtis Bucher <cpbucher5@gmail.com> | 2020-03-23 13:49:46 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-03-23 13:49:46 -0700 |
commit | 25e580a73c163f472fdeb5489bebef85da21655c (patch) | |
tree | ae7ee5d6817eb0efd91e6fd2db0237071fb05b06 | |
parent | 8dd1792c680caaf94a00cead82b238238f419172 (diff) | |
download | cpython-git-25e580a73c163f472fdeb5489bebef85da21655c.tar.gz |
bpo-36144: Add union operators to WeakKeyDictionary (#19106)
-rw-r--r-- | Doc/library/weakref.rst | 3 | ||||
-rw-r--r-- | Lib/test/test_weakref.py | 37 | ||||
-rw-r--r-- | Lib/weakref.py | 19 | ||||
-rw-r--r-- | Misc/NEWS.d/next/Library/2020-03-18-14-02-58.bpo-36144.ooyn6Z.rst | 1 |
4 files changed, 60 insertions, 0 deletions
diff --git a/Doc/library/weakref.rst b/Doc/library/weakref.rst index 8636e76c52..c10f436bea 100644 --- a/Doc/library/weakref.rst +++ b/Doc/library/weakref.rst @@ -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 diff --git a/Lib/test/test_weakref.py b/Lib/test/test_weakref.py index 63c725527d..250ed40b20 100644 --- a/Lib/test/test_weakref.py +++ b/Lib/test/test_weakref.py @@ -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') diff --git a/Lib/weakref.py b/Lib/weakref.py index e3c2ce2d9b..759ad6dfa3 100644 --- a/Lib/weakref.py +++ b/Lib/weakref.py @@ -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 index 0000000000..262653a01b --- /dev/null +++ b/Misc/NEWS.d/next/Library/2020-03-18-14-02-58.bpo-36144.ooyn6Z.rst @@ -0,0 +1 @@ +Added :pep:`584` operators to :class:`weakref.WeakKeyDictionary`. |