summaryrefslogtreecommitdiff
path: root/Modules/_functoolsmodule.c
diff options
context:
space:
mode:
authorAlexander Belopolsky <alexander.belopolsky@gmail.com>2015-03-01 15:08:17 -0500
committerAlexander Belopolsky <alexander.belopolsky@gmail.com>2015-03-01 15:08:17 -0500
commit09f948b478144e25154abb7c0f163d200fc57a84 (patch)
tree4b24495dae0e88937d9001cb1900a61a6be23d2e /Modules/_functoolsmodule.c
parent19bc01c2e5808108db8940f405fc6a7f117c39cb (diff)
downloadcpython-09f948b478144e25154abb7c0f163d200fc57a84.tar.gz
Issue #7830: Flatten nested functools.partial.
Diffstat (limited to 'Modules/_functoolsmodule.c')
-rw-r--r--Modules/_functoolsmodule.c55
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;