diff options
author | Alexander Belopolsky <alexander.belopolsky@gmail.com> | 2015-03-01 15:08:17 -0500 |
---|---|---|
committer | Alexander Belopolsky <alexander.belopolsky@gmail.com> | 2015-03-01 15:08:17 -0500 |
commit | 09f948b478144e25154abb7c0f163d200fc57a84 (patch) | |
tree | 4b24495dae0e88937d9001cb1900a61a6be23d2e /Modules/_functoolsmodule.c | |
parent | 19bc01c2e5808108db8940f405fc6a7f117c39cb (diff) | |
download | cpython-09f948b478144e25154abb7c0f163d200fc57a84.tar.gz |
Issue #7830: Flatten nested functools.partial.
Diffstat (limited to 'Modules/_functoolsmodule.c')
-rw-r--r-- | Modules/_functoolsmodule.c | 55 |
1 files changed, 48 insertions, 7 deletions
diff --git a/Modules/_functoolsmodule.c b/Modules/_functoolsmodule.c index 57dfba0410..3413b12dfe 100644 --- a/Modules/_functoolsmodule.c +++ b/Modules/_functoolsmodule.c @@ -25,7 +25,7 @@ static PyTypeObject partial_type; static PyObject * partial_new(PyTypeObject *type, PyObject *args, PyObject *kw) { - PyObject *func; + PyObject *func, *pargs, *nargs, *pkw; partialobject *pto; if (PyTuple_GET_SIZE(args) < 1) { @@ -34,7 +34,16 @@ partial_new(PyTypeObject *type, PyObject *args, PyObject *kw) return NULL; } + pargs = pkw = Py_None; func = PyTuple_GET_ITEM(args, 0); + if (Py_TYPE(func) == &partial_type && type == &partial_type) { + partialobject *part = (partialobject *)func; + if (part->dict == NULL) { + pargs = part->args; + pkw = part->kw; + func = part->fn; + } + } if (!PyCallable_Check(func)) { PyErr_SetString(PyExc_TypeError, "the first argument must be callable"); @@ -48,21 +57,53 @@ partial_new(PyTypeObject *type, PyObject *args, PyObject *kw) pto->fn = func; Py_INCREF(func); - pto->args = PyTuple_GetSlice(args, 1, PY_SSIZE_T_MAX); - if (pto->args == NULL) { + + nargs = PyTuple_GetSlice(args, 1, PY_SSIZE_T_MAX); + if (nargs == NULL) { + pto->args = NULL; pto->kw = NULL; Py_DECREF(pto); return NULL; } + if (pargs == Py_None || PyTuple_GET_SIZE(pargs) == 0) { + pto->args = nargs; + Py_INCREF(nargs); + } + else if (PyTuple_GET_SIZE(nargs) == 0) { + pto->args = pargs; + Py_INCREF(pargs); + } + else { + pto->args = PySequence_Concat(pargs, nargs); + if (pto->args == NULL) { + pto->kw = NULL; + Py_DECREF(pto); + return NULL; + } + } + Py_DECREF(nargs); + if (kw != NULL) { - pto->kw = PyDict_Copy(kw); + if (pkw == Py_None) { + pto->kw = PyDict_Copy(kw); + } + else { + pto->kw = PyDict_Copy(pkw); + if (pto->kw != NULL) { + if (PyDict_Merge(pto->kw, kw, 1) != 0) { + Py_DECREF(pto); + return NULL; + } + } + } if (pto->kw == NULL) { Py_DECREF(pto); return NULL; } - } else { - pto->kw = Py_None; - Py_INCREF(Py_None); + } + else { + pto->kw = pkw; + Py_INCREF(pkw); } pto->weakreflist = NULL; |