[Python-checkins] bpo-38006: Avoid closure in weakref.WeakValueDictionary (GH-15641) (GH-15789)

Victor Stinner webhook-mailer at python.org
Mon Sep 9 18:31:25 EDT 2019


https://github.com/python/cpython/commit/23669330b7d0d5ad1a9aac40315ba4c2e765f9dd
commit: 23669330b7d0d5ad1a9aac40315ba4c2e765f9dd
branch: 3.7
author: Victor Stinner <vstinner at python.org>
committer: GitHub <noreply at github.com>
date: 2019-09-10T00:31:20+02:00
summary:

bpo-38006: Avoid closure in weakref.WeakValueDictionary (GH-15641) (GH-15789)

weakref.WeakValueDictionary defines a local remove() function used as
callback for weak references. This function was created with a
closure.  Modify the implementation to avoid the closure.

(cherry picked from commit a2af05a0d3f0da06b8d432f52efa3ecf29038532)

files:
A Misc/NEWS.d/next/Library/2019-09-02-13-37-27.bpo-38006.Y7vA0Q.rst
M Lib/test/test_weakref.py
M Lib/weakref.py

diff --git a/Lib/test/test_weakref.py b/Lib/test/test_weakref.py
index ad7a6acfcc7d..d3396fc9cf90 100644
--- a/Lib/test/test_weakref.py
+++ b/Lib/test/test_weakref.py
@@ -1770,6 +1770,11 @@ def test_threaded_weak_value_dict_deepcopy(self):
         # copying should not result in a crash.
         self.check_threaded_weak_dict_copy(weakref.WeakValueDictionary, True)
 
+    @support.cpython_only
+    def test_remove_closure(self):
+        d = weakref.WeakValueDictionary()
+        self.assertIsNone(d._remove.__closure__)
+
 
 from test import mapping_tests
 
diff --git a/Lib/weakref.py b/Lib/weakref.py
index 59b3aa5621a3..461c997a1293 100644
--- a/Lib/weakref.py
+++ b/Lib/weakref.py
@@ -114,12 +114,12 @@ def remove(wr, selfref=ref(self), _atomic_removal=_remove_dead_weakref):
                 else:
                     # Atomic removal is necessary since this function
                     # can be called asynchronously by the GC
-                    _atomic_removal(d, wr.key)
+                    _atomic_removal(self.data, wr.key)
         self._remove = remove
         # A list of keys to be removed
         self._pending_removals = []
         self._iterating = set()
-        self.data = d = {}
+        self.data = {}
         self.update(*args, **kw)
 
     def _commit_removals(self):
diff --git a/Misc/NEWS.d/next/Library/2019-09-02-13-37-27.bpo-38006.Y7vA0Q.rst b/Misc/NEWS.d/next/Library/2019-09-02-13-37-27.bpo-38006.Y7vA0Q.rst
new file mode 100644
index 000000000000..ff064ad3f1a4
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2019-09-02-13-37-27.bpo-38006.Y7vA0Q.rst
@@ -0,0 +1,3 @@
+weakref.WeakValueDictionary defines a local remove() function used as
+callback for weak references. This function was created with a closure.
+Modify the implementation to avoid the closure.



More information about the Python-checkins mailing list