Skip to content

Commit 5010a77

Browse files
[3.5] bpo-29532: Altering a kwarg dictionary passed to functools.partial() no longer affects a partial object after creation. (#222)
1 parent 8fa7e22 commit 5010a77

File tree

3 files changed

+16
-1
lines changed

3 files changed

+16
-1
lines changed

Lib/test/test_functools.py

+9
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,15 @@ def func(a=10, b=20):
8080
p(b=7)
8181
self.assertEqual(d, {'a':3})
8282

83+
def test_kwargs_copy(self):
84+
# Issue #29532: Altering a kwarg dictionary passed to a constructor
85+
# should not affect a partial object after creation
86+
d = {'a': 3}
87+
p = self.partial(capture, **d)
88+
self.assertEqual(p(), ((), {'a': 3}))
89+
d['a'] = 5
90+
self.assertEqual(p(), ((), {'a': 3}))
91+
8392
def test_arg_combinations(self):
8493
# exercise special code paths for zero args in either partial
8594
# object or the caller

Misc/NEWS

+3
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@ Extension Modules
3232
Library
3333
-------
3434

35+
- bpo-29532: Altering a kwarg dictionary passed to functools.partial()
36+
no longer affects a partial object after creation.
37+
3538
- Issue #28556: Various updates to typing module: typing.Counter, typing.ChainMap,
3639
improved ABC caching, etc. Original PRs by Jelle Zijlstra, Ivan Levkivskyi,
3740
Manuel Krebber, and Łukasz Langa.

Modules/_functoolsmodule.c

+4-1
Original file line numberDiff line numberDiff line change
@@ -88,10 +88,13 @@ partial_new(PyTypeObject *type, PyObject *args, PyObject *kw)
8888
if (kw == NULL) {
8989
pto->kw = PyDict_New();
9090
}
91-
else {
91+
else if (Py_REFCNT(kw) == 1) {
9292
Py_INCREF(kw);
9393
pto->kw = kw;
9494
}
95+
else {
96+
pto->kw = PyDict_Copy(kw);
97+
}
9598
}
9699
else {
97100
pto->kw = PyDict_Copy(pkw);

0 commit comments

Comments
 (0)