]> granicus.if.org Git - python/commitdiff
[3.5] bpo-29532: Altering a kwarg dictionary passed to functools.partial() no longer...
authorSerhiy Storchaka <storchaka@gmail.com>
Wed, 22 Feb 2017 09:46:32 +0000 (11:46 +0200)
committerGitHub <noreply@github.com>
Wed, 22 Feb 2017 09:46:32 +0000 (11:46 +0200)
Lib/test/test_functools.py
Misc/NEWS
Modules/_functoolsmodule.c

index 9ccd0cafc489cf1a7fce5ecf1043727137f944ec..a82ca7ab88c38fea4a475897ce87c2a8d3fb9005 100644 (file)
@@ -80,6 +80,15 @@ class TestPartial:
         p(b=7)
         self.assertEqual(d, {'a':3})
 
+    def test_kwargs_copy(self):
+        # Issue #29532: Altering a kwarg dictionary passed to a constructor
+        # should not affect a partial object after creation
+        d = {'a': 3}
+        p = self.partial(capture, **d)
+        self.assertEqual(p(), ((), {'a': 3}))
+        d['a'] = 5
+        self.assertEqual(p(), ((), {'a': 3}))
+
     def test_arg_combinations(self):
         # exercise special code paths for zero args in either partial
         # object or the caller
index 038233735f6c1351b1d9db08019813db257fe496..a01d454ab78f7dee8fc6ef96c3334d380c806521 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -32,6 +32,9 @@ Extension Modules
 Library
 -------
 
+- bpo-29532: Altering a kwarg dictionary passed to functools.partial()
+  no longer affects a partial object after creation.
+
 - Issue #28556: Various updates to typing module: typing.Counter, typing.ChainMap,
   improved ABC caching, etc. Original PRs by Jelle Zijlstra, Ivan Levkivskyi,
   Manuel Krebber, and Ćukasz Langa.
index be0f5f9e652abc10d193bb9e99a5e60f87e96b3f..0471d665e65a58e5f1ea7adf1eea404796fdce67 100644 (file)
@@ -88,10 +88,13 @@ partial_new(PyTypeObject *type, PyObject *args, PyObject *kw)
         if (kw == NULL) {
             pto->kw = PyDict_New();
         }
-        else {
+        else if (Py_REFCNT(kw) == 1) {
             Py_INCREF(kw);
             pto->kw = kw;
         }
+        else {
+            pto->kw = PyDict_Copy(kw);
+        }
     }
     else {
         pto->kw = PyDict_Copy(pkw);