bpo-29532: Altering a kwarg dictionary passed to functools.partial() no longer affects a partial object after creation. (#209)

This commit is contained in:
Serhiy Storchaka 2017-02-21 18:18:27 +02:00 committed by GitHub
parent 51a477c0d5
commit e48fd93bbb
3 changed files with 26 additions and 1 deletions

View file

@ -89,6 +89,15 @@ class TestPartial:
p(b=7) p(b=7)
self.assertEqual(d, {'a':3}) 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): def test_arg_combinations(self):
# exercise special code paths for zero args in either partial # exercise special code paths for zero args in either partial
# object or the caller # object or the caller

View file

@ -66,6 +66,19 @@ Extension Modules
Library Library
------- -------
- bpo-29532: Altering a kwarg dictionary passed to functools.partial()
no longer affects a partial object after creation.
- bpo-22807: Add uuid.SafeUUID and uuid.UUID.is_safe to relay information from
the platform about whether generated UUIDs are generated with a
multiprocessing safe method.
- bpo-29576: Improve some deprecations in importlib. Some deprecated methods
now emit DeprecationWarnings and have better descriptive messages.
- bpo-29534: Fixed different behaviour of Decimal.from_float()
for _decimal and _pydecimal. Thanks Andrew Nester.
- Issue #28556: Various updates to typing module: typing.Counter, typing.ChainMap, - Issue #28556: Various updates to typing module: typing.Counter, typing.ChainMap,
improved ABC caching, etc. Original PRs by Jelle Zijlstra, Ivan Levkivskyi, improved ABC caching, etc. Original PRs by Jelle Zijlstra, Ivan Levkivskyi,
Manuel Krebber, and Łukasz Langa. Manuel Krebber, and Łukasz Langa.

View file

@ -88,10 +88,13 @@ partial_new(PyTypeObject *type, PyObject *args, PyObject *kw)
if (kw == NULL) { if (kw == NULL) {
pto->kw = PyDict_New(); pto->kw = PyDict_New();
} }
else { else if (Py_REFCNT(kw) == 1) {
Py_INCREF(kw); Py_INCREF(kw);
pto->kw = kw; pto->kw = kw;
} }
else {
pto->kw = PyDict_Copy(kw);
}
} }
else { else {
pto->kw = PyDict_Copy(pkw); pto->kw = PyDict_Copy(pkw);