diff --git a/Lib/test/test_functools.py b/Lib/test/test_functools.py index 0375601c518..36f154a7f56 100644 --- a/Lib/test/test_functools.py +++ b/Lib/test/test_functools.py @@ -77,9 +77,11 @@ class TestPartial: # exercise special code paths for no keyword args in # either the partial object or the caller p = self.partial(capture) + self.assertEqual(p.keywords, {}) self.assertEqual(p(), ((), {})) self.assertEqual(p(a=1), ((), {'a':1})) p = self.partial(capture, a=1) + self.assertEqual(p.keywords, {'a':1}) self.assertEqual(p(), ((), {'a':1})) self.assertEqual(p(b=2), ((), {'a':1, 'b':2})) # keyword args in the call override those in the partial object diff --git a/Misc/NEWS b/Misc/NEWS index d01f52533f0..e2f749c42c2 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -57,6 +57,8 @@ Library - Issue #9246: On POSIX, os.getcwd() now supports paths longer than 1025 bytes. Patch written by William Orr. +- The keywords attribute of functools.partial is now always a dictionary. + - Issues #24099, #24100, and #24101: Fix free-after-use bug in heapq's siftup and siftdown functions. diff --git a/Modules/_functoolsmodule.c b/Modules/_functoolsmodule.c index 57dfba04101..24da67741b8 100644 --- a/Modules/_functoolsmodule.c +++ b/Modules/_functoolsmodule.c @@ -54,17 +54,13 @@ partial_new(PyTypeObject *type, PyObject *args, PyObject *kw) Py_DECREF(pto); return NULL; } - if (kw != NULL) { - pto->kw = PyDict_Copy(kw); - if (pto->kw == NULL) { - Py_DECREF(pto); - return NULL; - } - } else { - pto->kw = Py_None; - Py_INCREF(Py_None); + pto->kw = (kw != NULL) ? PyDict_Copy(kw) : PyDict_New(); + if (pto->kw == NULL) { + Py_DECREF(pto); + return NULL; } + pto->weakreflist = NULL; pto->dict = NULL;