[Python-Dev] Patch to skip positional arguments with partials (original) (raw)
Calvin Spealman ironfroggy at gmail.com
Tue Apr 24 05:51:45 CEST 2007
- Previous message: [Python-Dev] Attachment Policy?
- Next message: [Python-Dev] Automatic Scope Macros
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
I posted about this on python-ideas, and didn't get any objections about the idea itself, so I took the opportunity to dive into the C API and get my hands dirty. I posted the idea and patch as a report on SF (1706256). For anyone interested at least to look over, I'm also just including the small patch at the end of this email. Everything is passing for me with these changes, except the inability to subclass the partial type. I've found the current end of my abilities in understanding how I broke that, so I'd appreciate any reaction to the situation.
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; i<PyTuple_GET_SIZE(pto->args); ++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[] = { @@ -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. }
-- Read my blog! I depend on your acceptance of my opinion! I am interesting! http://ironfroggy-code.blogspot.com/
- Previous message: [Python-Dev] Attachment Policy?
- Next message: [Python-Dev] Automatic Scope Macros
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]