Index: Modules/_functoolsmodule.c =================================================================== --- Modules/_functoolsmodule.c (revision 54922) +++ Modules/_functoolsmodule.c (working copy) @@ -21,6 +21,7 @@ } partialobject; static PyTypeObject partial_type; +static PyObject *partial_skip; static PyObject * partial_new(PyTypeObject *type, PyObject *args, PyObject *kw) @@ -89,6 +90,10 @@ { PyObject *ret; PyObject *argappl = NULL, *kwappl = NULL; + PyObject *ptoargscopy, *arg; + Py_ssize_t skip_index = 0; + Py_ssize_t pull_index = 0; + Py_ssize_t i; assert (PyCallable_Check(pto->fn)); assert (PyTuple_Check(pto->args)); @@ -101,7 +106,25 @@ argappl = pto->args; Py_INCREF(pto->args); } else { - argappl = PySequence_Concat(pto->args, args); + + // For each partial_skip in the pto args, replace it with a new arg + ptoargscopy = PyTuple_New(PyTuple_GET_SIZE(pto->args)); + for (i = 0; iargs); ++i) { + arg = PyTuple_GetItem(pto->args, i); + Py_XINCREF(arg); + PyTuple_SetItem(ptoargscopy, i, arg); + if (arg == NULL) { + break; + } else if (arg == partial_skip) { + arg = PyTuple_GetItem(args, pull_index); + Py_XINCREF(arg); + PyTuple_SetItem(ptoargscopy, i, arg); + pull_index += 1; + } + } + + arg = PyTuple_GetSlice(args, pull_index, PySequence_Length(args)); + argappl = PySequence_Concat(ptoargscopy, arg); if (argappl == NULL) return NULL; } @@ -142,7 +165,8 @@ PyDoc_STRVAR(partial_doc, "partial(func, *args, **keywords) - new function with partial application\n\ - of the given arguments and keywords.\n"); + of the given arguments and keywords. Pass partial.skip to any positional\n\ + argument to be bound to later."); #define OFF(x) offsetof(partialobject, x) static PyMemberDef partial_memberlist[] = { @@ -242,6 +266,7 @@ }; + /* module level code ********************************************************/ PyDoc_STRVAR(module_doc, @@ -255,7 +280,7 @@ init_functools(void) { int i; - PyObject *m; + PyObject *m, *builtins, *skip, *object; char *name; PyTypeObject *typelist[] = { &partial_type, @@ -274,4 +299,16 @@ Py_INCREF(typelist[i]); PyModule_AddObject(m, name+1, (PyObject *)typelist[i]); } + + builtins = PyImport_ImportModule("__builtin__"); + object = PyObject_GetAttrString(builtins, "object"); + Py_DECREF(builtins); + skip = PyObject_CallObject(object, NULL, NULL); + Py_DECREF(object); + + partial_type.tp_dict = PyDict_New(); + PyDict_SetItemString(partial_type.tp_dict, "skip", skip); + partial_skip = skip; + + // skip is not decref'ed because a reference is always held by the static pointer. }