blob: 3413b12dfe9078368616f31d94c207976468f990 [file] [log] [blame]
Raymond Hettinger9c323f82005-02-28 19:39:44 +00001
2#include "Python.h"
3#include "structmember.h"
4
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00005/* _functools module written and maintained
Raymond Hettinger9c323f82005-02-28 19:39:44 +00006 by Hye-Shik Chang <perky@FreeBSD.org>
7 with adaptations by Raymond Hettinger <python@rcn.com>
Thomas Wouters4d70c3d2006-06-08 14:42:34 +00008 Copyright (c) 2004, 2005, 2006 Python Software Foundation.
Raymond Hettinger9c323f82005-02-28 19:39:44 +00009 All rights reserved.
10*/
11
12/* partial object **********************************************************/
13
14typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000015 PyObject_HEAD
16 PyObject *fn;
17 PyObject *args;
18 PyObject *kw;
19 PyObject *dict;
20 PyObject *weakreflist; /* List of weak references */
Raymond Hettinger9c323f82005-02-28 19:39:44 +000021} partialobject;
22
23static PyTypeObject partial_type;
24
25static PyObject *
26partial_new(PyTypeObject *type, PyObject *args, PyObject *kw)
27{
Alexander Belopolskye49af342015-03-01 15:08:17 -050028 PyObject *func, *pargs, *nargs, *pkw;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000029 partialobject *pto;
Raymond Hettinger9c323f82005-02-28 19:39:44 +000030
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000031 if (PyTuple_GET_SIZE(args) < 1) {
32 PyErr_SetString(PyExc_TypeError,
33 "type 'partial' takes at least one argument");
34 return NULL;
35 }
Raymond Hettinger9c323f82005-02-28 19:39:44 +000036
Alexander Belopolskye49af342015-03-01 15:08:17 -050037 pargs = pkw = Py_None;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000038 func = PyTuple_GET_ITEM(args, 0);
Alexander Belopolskye49af342015-03-01 15:08:17 -050039 if (Py_TYPE(func) == &partial_type && type == &partial_type) {
40 partialobject *part = (partialobject *)func;
41 if (part->dict == NULL) {
42 pargs = part->args;
43 pkw = part->kw;
44 func = part->fn;
45 }
46 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000047 if (!PyCallable_Check(func)) {
48 PyErr_SetString(PyExc_TypeError,
49 "the first argument must be callable");
50 return NULL;
51 }
Raymond Hettinger9c323f82005-02-28 19:39:44 +000052
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000053 /* create partialobject structure */
54 pto = (partialobject *)type->tp_alloc(type, 0);
55 if (pto == NULL)
56 return NULL;
Raymond Hettinger9c323f82005-02-28 19:39:44 +000057
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000058 pto->fn = func;
59 Py_INCREF(func);
Alexander Belopolskye49af342015-03-01 15:08:17 -050060
61 nargs = PyTuple_GetSlice(args, 1, PY_SSIZE_T_MAX);
62 if (nargs == NULL) {
63 pto->args = NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000064 pto->kw = NULL;
65 Py_DECREF(pto);
66 return NULL;
67 }
Alexander Belopolskye49af342015-03-01 15:08:17 -050068 if (pargs == Py_None || PyTuple_GET_SIZE(pargs) == 0) {
69 pto->args = nargs;
70 Py_INCREF(nargs);
71 }
72 else if (PyTuple_GET_SIZE(nargs) == 0) {
73 pto->args = pargs;
74 Py_INCREF(pargs);
75 }
76 else {
77 pto->args = PySequence_Concat(pargs, nargs);
78 if (pto->args == NULL) {
79 pto->kw = NULL;
80 Py_DECREF(pto);
81 return NULL;
82 }
83 }
84 Py_DECREF(nargs);
85
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000086 if (kw != NULL) {
Alexander Belopolskye49af342015-03-01 15:08:17 -050087 if (pkw == Py_None) {
88 pto->kw = PyDict_Copy(kw);
89 }
90 else {
91 pto->kw = PyDict_Copy(pkw);
92 if (pto->kw != NULL) {
93 if (PyDict_Merge(pto->kw, kw, 1) != 0) {
94 Py_DECREF(pto);
95 return NULL;
96 }
97 }
98 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000099 if (pto->kw == NULL) {
100 Py_DECREF(pto);
101 return NULL;
102 }
Alexander Belopolskye49af342015-03-01 15:08:17 -0500103 }
104 else {
105 pto->kw = pkw;
106 Py_INCREF(pkw);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000107 }
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000108
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000109 pto->weakreflist = NULL;
110 pto->dict = NULL;
Raymond Hettingerc8b6d1b2005-03-08 06:14:50 +0000111
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000112 return (PyObject *)pto;
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000113}
114
115static void
116partial_dealloc(partialobject *pto)
117{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000118 PyObject_GC_UnTrack(pto);
119 if (pto->weakreflist != NULL)
120 PyObject_ClearWeakRefs((PyObject *) pto);
121 Py_XDECREF(pto->fn);
122 Py_XDECREF(pto->args);
123 Py_XDECREF(pto->kw);
124 Py_XDECREF(pto->dict);
125 Py_TYPE(pto)->tp_free(pto);
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000126}
127
128static PyObject *
129partial_call(partialobject *pto, PyObject *args, PyObject *kw)
130{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000131 PyObject *ret;
132 PyObject *argappl = NULL, *kwappl = NULL;
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000133
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000134 assert (PyCallable_Check(pto->fn));
135 assert (PyTuple_Check(pto->args));
136 assert (pto->kw == Py_None || PyDict_Check(pto->kw));
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000137
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000138 if (PyTuple_GET_SIZE(pto->args) == 0) {
139 argappl = args;
140 Py_INCREF(args);
141 } else if (PyTuple_GET_SIZE(args) == 0) {
142 argappl = pto->args;
143 Py_INCREF(pto->args);
144 } else {
145 argappl = PySequence_Concat(pto->args, args);
146 if (argappl == NULL)
147 return NULL;
148 }
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000149
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000150 if (pto->kw == Py_None) {
151 kwappl = kw;
152 Py_XINCREF(kw);
153 } else {
154 kwappl = PyDict_Copy(pto->kw);
155 if (kwappl == NULL) {
156 Py_DECREF(argappl);
157 return NULL;
158 }
159 if (kw != NULL) {
160 if (PyDict_Merge(kwappl, kw, 1) != 0) {
161 Py_DECREF(argappl);
162 Py_DECREF(kwappl);
163 return NULL;
164 }
165 }
166 }
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000167
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000168 ret = PyObject_Call(pto->fn, argappl, kwappl);
169 Py_DECREF(argappl);
170 Py_XDECREF(kwappl);
171 return ret;
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000172}
173
174static int
175partial_traverse(partialobject *pto, visitproc visit, void *arg)
176{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000177 Py_VISIT(pto->fn);
178 Py_VISIT(pto->args);
179 Py_VISIT(pto->kw);
180 Py_VISIT(pto->dict);
181 return 0;
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000182}
183
184PyDoc_STRVAR(partial_doc,
185"partial(func, *args, **keywords) - new function with partial application\n\
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000186 of the given arguments and keywords.\n");
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000187
188#define OFF(x) offsetof(partialobject, x)
189static PyMemberDef partial_memberlist[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000190 {"func", T_OBJECT, OFF(fn), READONLY,
191 "function object to use in future partial calls"},
192 {"args", T_OBJECT, OFF(args), READONLY,
193 "tuple of arguments to future partial calls"},
194 {"keywords", T_OBJECT, OFF(kw), READONLY,
195 "dictionary of keyword arguments to future partial calls"},
196 {NULL} /* Sentinel */
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000197};
198
Georg Brandlc2fb6c72006-02-21 17:49:57 +0000199static PyGetSetDef partial_getsetlist[] = {
Benjamin Peterson23d7f122012-02-19 20:02:57 -0500200 {"__dict__", PyObject_GenericGetDict, PyObject_GenericSetDict},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000201 {NULL} /* Sentinel */
Raymond Hettingerc8b6d1b2005-03-08 06:14:50 +0000202};
203
Alexander Belopolsky41e422a2010-12-01 20:05:49 +0000204static PyObject *
205partial_repr(partialobject *pto)
206{
207 PyObject *result;
208 PyObject *arglist;
209 PyObject *tmp;
210 Py_ssize_t i, n;
211
212 arglist = PyUnicode_FromString("");
213 if (arglist == NULL) {
214 return NULL;
215 }
216 /* Pack positional arguments */
217 assert (PyTuple_Check(pto->args));
218 n = PyTuple_GET_SIZE(pto->args);
219 for (i = 0; i < n; i++) {
220 tmp = PyUnicode_FromFormat("%U, %R", arglist,
221 PyTuple_GET_ITEM(pto->args, i));
222 Py_DECREF(arglist);
223 if (tmp == NULL)
224 return NULL;
225 arglist = tmp;
226 }
227 /* Pack keyword arguments */
228 assert (pto->kw == Py_None || PyDict_Check(pto->kw));
229 if (pto->kw != Py_None) {
230 PyObject *key, *value;
231 for (i = 0; PyDict_Next(pto->kw, &i, &key, &value);) {
232 tmp = PyUnicode_FromFormat("%U, %U=%R", arglist,
233 key, value);
234 Py_DECREF(arglist);
235 if (tmp == NULL)
236 return NULL;
237 arglist = tmp;
238 }
239 }
240 result = PyUnicode_FromFormat("%s(%R%U)", Py_TYPE(pto)->tp_name,
241 pto->fn, arglist);
242 Py_DECREF(arglist);
243 return result;
244}
245
Jack Diederiche0cbd692009-04-01 04:27:09 +0000246/* Pickle strategy:
247 __reduce__ by itself doesn't support getting kwargs in the unpickle
248 operation so we define a __setstate__ that replaces all the information
249 about the partial. If we only replaced part of it someone would use
Ezio Melotti13925002011-03-16 11:05:33 +0200250 it as a hook to do strange things.
Jack Diederiche0cbd692009-04-01 04:27:09 +0000251 */
252
Antoine Pitrou69f71142009-05-24 21:25:49 +0000253static PyObject *
Jack Diederiche0cbd692009-04-01 04:27:09 +0000254partial_reduce(partialobject *pto, PyObject *unused)
255{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000256 return Py_BuildValue("O(O)(OOOO)", Py_TYPE(pto), pto->fn, pto->fn,
257 pto->args, pto->kw,
258 pto->dict ? pto->dict : Py_None);
Jack Diederiche0cbd692009-04-01 04:27:09 +0000259}
260
Antoine Pitrou69f71142009-05-24 21:25:49 +0000261static PyObject *
Serhiy Storchaka19c4e0d2013-02-04 12:47:24 +0200262partial_setstate(partialobject *pto, PyObject *state)
Jack Diederiche0cbd692009-04-01 04:27:09 +0000263{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000264 PyObject *fn, *fnargs, *kw, *dict;
Serhiy Storchaka19c4e0d2013-02-04 12:47:24 +0200265 if (!PyArg_ParseTuple(state, "OOOO",
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000266 &fn, &fnargs, &kw, &dict))
267 return NULL;
268 Py_XDECREF(pto->fn);
269 Py_XDECREF(pto->args);
270 Py_XDECREF(pto->kw);
271 Py_XDECREF(pto->dict);
272 pto->fn = fn;
273 pto->args = fnargs;
274 pto->kw = kw;
275 if (dict != Py_None) {
276 pto->dict = dict;
277 Py_INCREF(dict);
278 } else {
279 pto->dict = NULL;
280 }
281 Py_INCREF(fn);
282 Py_INCREF(fnargs);
283 Py_INCREF(kw);
284 Py_RETURN_NONE;
Jack Diederiche0cbd692009-04-01 04:27:09 +0000285}
286
287static PyMethodDef partial_methods[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000288 {"__reduce__", (PyCFunction)partial_reduce, METH_NOARGS},
Serhiy Storchaka19c4e0d2013-02-04 12:47:24 +0200289 {"__setstate__", (PyCFunction)partial_setstate, METH_O},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000290 {NULL, NULL} /* sentinel */
Jack Diederiche0cbd692009-04-01 04:27:09 +0000291};
292
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000293static PyTypeObject partial_type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000294 PyVarObject_HEAD_INIT(NULL, 0)
295 "functools.partial", /* tp_name */
296 sizeof(partialobject), /* tp_basicsize */
297 0, /* tp_itemsize */
298 /* methods */
299 (destructor)partial_dealloc, /* tp_dealloc */
300 0, /* tp_print */
301 0, /* tp_getattr */
302 0, /* tp_setattr */
303 0, /* tp_reserved */
Alexander Belopolsky41e422a2010-12-01 20:05:49 +0000304 (reprfunc)partial_repr, /* tp_repr */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000305 0, /* tp_as_number */
306 0, /* tp_as_sequence */
307 0, /* tp_as_mapping */
308 0, /* tp_hash */
309 (ternaryfunc)partial_call, /* tp_call */
310 0, /* tp_str */
311 PyObject_GenericGetAttr, /* tp_getattro */
312 PyObject_GenericSetAttr, /* tp_setattro */
313 0, /* tp_as_buffer */
314 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
315 Py_TPFLAGS_BASETYPE, /* tp_flags */
316 partial_doc, /* tp_doc */
317 (traverseproc)partial_traverse, /* tp_traverse */
318 0, /* tp_clear */
319 0, /* tp_richcompare */
320 offsetof(partialobject, weakreflist), /* tp_weaklistoffset */
321 0, /* tp_iter */
322 0, /* tp_iternext */
323 partial_methods, /* tp_methods */
324 partial_memberlist, /* tp_members */
325 partial_getsetlist, /* tp_getset */
326 0, /* tp_base */
327 0, /* tp_dict */
328 0, /* tp_descr_get */
329 0, /* tp_descr_set */
330 offsetof(partialobject, dict), /* tp_dictoffset */
331 0, /* tp_init */
332 0, /* tp_alloc */
333 partial_new, /* tp_new */
334 PyObject_GC_Del, /* tp_free */
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000335};
336
337
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700338/* cmp_to_key ***************************************************************/
339
340typedef struct {
Victor Stinner446c8d52011-04-05 12:21:35 +0200341 PyObject_HEAD
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700342 PyObject *cmp;
343 PyObject *object;
344} keyobject;
345
346static void
347keyobject_dealloc(keyobject *ko)
348{
349 Py_DECREF(ko->cmp);
350 Py_XDECREF(ko->object);
351 PyObject_FREE(ko);
352}
353
354static int
355keyobject_traverse(keyobject *ko, visitproc visit, void *arg)
356{
357 Py_VISIT(ko->cmp);
358 if (ko->object)
359 Py_VISIT(ko->object);
360 return 0;
361}
362
Benjamin Peterson3bd97292011-04-05 17:25:14 -0500363static int
364keyobject_clear(keyobject *ko)
365{
366 Py_CLEAR(ko->cmp);
367 if (ko->object)
368 Py_CLEAR(ko->object);
369 return 0;
370}
371
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700372static PyMemberDef keyobject_members[] = {
373 {"obj", T_OBJECT,
374 offsetof(keyobject, object), 0,
375 PyDoc_STR("Value wrapped by a key function.")},
376 {NULL}
377};
378
379static PyObject *
Raymond Hettingera5632862011-04-09 12:57:00 -0700380keyobject_call(keyobject *ko, PyObject *args, PyObject *kwds);
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700381
382static PyObject *
383keyobject_richcompare(PyObject *ko, PyObject *other, int op);
384
385static PyTypeObject keyobject_type = {
386 PyVarObject_HEAD_INIT(&PyType_Type, 0)
387 "functools.KeyWrapper", /* tp_name */
388 sizeof(keyobject), /* tp_basicsize */
389 0, /* tp_itemsize */
390 /* methods */
391 (destructor)keyobject_dealloc, /* tp_dealloc */
392 0, /* tp_print */
393 0, /* tp_getattr */
394 0, /* tp_setattr */
395 0, /* tp_reserved */
396 0, /* tp_repr */
397 0, /* tp_as_number */
398 0, /* tp_as_sequence */
399 0, /* tp_as_mapping */
400 0, /* tp_hash */
401 (ternaryfunc)keyobject_call, /* tp_call */
402 0, /* tp_str */
403 PyObject_GenericGetAttr, /* tp_getattro */
404 0, /* tp_setattro */
405 0, /* tp_as_buffer */
406 Py_TPFLAGS_DEFAULT, /* tp_flags */
407 0, /* tp_doc */
408 (traverseproc)keyobject_traverse, /* tp_traverse */
Benjamin Peterson3bd97292011-04-05 17:25:14 -0500409 (inquiry)keyobject_clear, /* tp_clear */
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700410 keyobject_richcompare, /* tp_richcompare */
411 0, /* tp_weaklistoffset */
412 0, /* tp_iter */
413 0, /* tp_iternext */
414 0, /* tp_methods */
415 keyobject_members, /* tp_members */
416 0, /* tp_getset */
417};
418
419static PyObject *
420keyobject_call(keyobject *ko, PyObject *args, PyObject *kwds)
421{
422 PyObject *object;
423 keyobject *result;
424 static char *kwargs[] = {"obj", NULL};
425
426 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:K", kwargs, &object))
427 return NULL;
428 result = PyObject_New(keyobject, &keyobject_type);
429 if (!result)
430 return NULL;
431 Py_INCREF(ko->cmp);
432 result->cmp = ko->cmp;
433 Py_INCREF(object);
434 result->object = object;
435 return (PyObject *)result;
436}
437
438static PyObject *
439keyobject_richcompare(PyObject *ko, PyObject *other, int op)
440{
441 PyObject *res;
442 PyObject *args;
443 PyObject *x;
444 PyObject *y;
445 PyObject *compare;
446 PyObject *answer;
447 static PyObject *zero;
448
449 if (zero == NULL) {
450 zero = PyLong_FromLong(0);
451 if (!zero)
452 return NULL;
453 }
454
455 if (Py_TYPE(other) != &keyobject_type){
456 PyErr_Format(PyExc_TypeError, "other argument must be K instance");
457 return NULL;
458 }
459 compare = ((keyobject *) ko)->cmp;
460 assert(compare != NULL);
461 x = ((keyobject *) ko)->object;
462 y = ((keyobject *) other)->object;
463 if (!x || !y){
464 PyErr_Format(PyExc_AttributeError, "object");
465 return NULL;
466 }
467
468 /* Call the user's comparison function and translate the 3-way
469 * result into true or false (or error).
470 */
471 args = PyTuple_New(2);
472 if (args == NULL)
473 return NULL;
474 Py_INCREF(x);
475 Py_INCREF(y);
476 PyTuple_SET_ITEM(args, 0, x);
477 PyTuple_SET_ITEM(args, 1, y);
478 res = PyObject_Call(compare, args, NULL);
479 Py_DECREF(args);
480 if (res == NULL)
481 return NULL;
482 answer = PyObject_RichCompare(res, zero, op);
483 Py_DECREF(res);
484 return answer;
485}
486
487static PyObject *
Victor Stinner446c8d52011-04-05 12:21:35 +0200488functools_cmp_to_key(PyObject *self, PyObject *args, PyObject *kwds)
489{
490 PyObject *cmp;
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700491 static char *kwargs[] = {"mycmp", NULL};
Victor Stinner446c8d52011-04-05 12:21:35 +0200492 keyobject *object;
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700493
494 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:cmp_to_key", kwargs, &cmp))
495 return NULL;
Victor Stinner446c8d52011-04-05 12:21:35 +0200496 object = PyObject_New(keyobject, &keyobject_type);
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700497 if (!object)
498 return NULL;
499 Py_INCREF(cmp);
500 object->cmp = cmp;
501 object->object = NULL;
502 return (PyObject *)object;
503}
504
505PyDoc_STRVAR(functools_cmp_to_key_doc,
506"Convert a cmp= function into a key= function.");
507
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000508/* reduce (used to be a builtin) ********************************************/
509
510static PyObject *
511functools_reduce(PyObject *self, PyObject *args)
512{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000513 PyObject *seq, *func, *result = NULL, *it;
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000514
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000515 if (!PyArg_UnpackTuple(args, "reduce", 2, 3, &func, &seq, &result))
516 return NULL;
517 if (result != NULL)
518 Py_INCREF(result);
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000519
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000520 it = PyObject_GetIter(seq);
521 if (it == NULL) {
Alexander Belopolskye29e6bf2010-08-16 18:55:46 +0000522 if (PyErr_ExceptionMatches(PyExc_TypeError))
523 PyErr_SetString(PyExc_TypeError,
524 "reduce() arg 2 must support iteration");
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000525 Py_XDECREF(result);
526 return NULL;
527 }
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000528
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000529 if ((args = PyTuple_New(2)) == NULL)
530 goto Fail;
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000531
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000532 for (;;) {
533 PyObject *op2;
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000534
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000535 if (args->ob_refcnt > 1) {
536 Py_DECREF(args);
537 if ((args = PyTuple_New(2)) == NULL)
538 goto Fail;
539 }
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000540
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000541 op2 = PyIter_Next(it);
542 if (op2 == NULL) {
543 if (PyErr_Occurred())
544 goto Fail;
545 break;
546 }
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000547
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000548 if (result == NULL)
549 result = op2;
550 else {
551 PyTuple_SetItem(args, 0, result);
552 PyTuple_SetItem(args, 1, op2);
553 if ((result = PyEval_CallObject(func, args)) == NULL)
554 goto Fail;
555 }
556 }
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000557
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000558 Py_DECREF(args);
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000559
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000560 if (result == NULL)
561 PyErr_SetString(PyExc_TypeError,
562 "reduce() of empty sequence with no initial value");
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000563
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000564 Py_DECREF(it);
565 return result;
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000566
567Fail:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000568 Py_XDECREF(args);
569 Py_XDECREF(result);
570 Py_DECREF(it);
571 return NULL;
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000572}
573
574PyDoc_STRVAR(functools_reduce_doc,
575"reduce(function, sequence[, initial]) -> value\n\
576\n\
577Apply a function of two arguments cumulatively to the items of a sequence,\n\
578from left to right, so as to reduce the sequence to a single value.\n\
579For example, reduce(lambda x, y: x+y, [1, 2, 3, 4, 5]) calculates\n\
580((((1+2)+3)+4)+5). If initial is present, it is placed before the items\n\
581of the sequence in the calculation, and serves as a default when the\n\
582sequence is empty.");
583
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000584/* module level code ********************************************************/
585
586PyDoc_STRVAR(module_doc,
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000587"Tools that operate on functions.");
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000588
589static PyMethodDef module_methods[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000590 {"reduce", functools_reduce, METH_VARARGS, functools_reduce_doc},
Victor Stinner446c8d52011-04-05 12:21:35 +0200591 {"cmp_to_key", (PyCFunction)functools_cmp_to_key,
592 METH_VARARGS | METH_KEYWORDS, functools_cmp_to_key_doc},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000593 {NULL, NULL} /* sentinel */
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000594};
595
Martin v. Löwis1a214512008-06-11 05:26:20 +0000596
597static struct PyModuleDef _functoolsmodule = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000598 PyModuleDef_HEAD_INIT,
599 "_functools",
600 module_doc,
601 -1,
602 module_methods,
603 NULL,
604 NULL,
605 NULL,
606 NULL
Martin v. Löwis1a214512008-06-11 05:26:20 +0000607};
608
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000609PyMODINIT_FUNC
Martin v. Löwis1a214512008-06-11 05:26:20 +0000610PyInit__functools(void)
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000611{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000612 int i;
613 PyObject *m;
614 char *name;
615 PyTypeObject *typelist[] = {
616 &partial_type,
617 NULL
618 };
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000619
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000620 m = PyModule_Create(&_functoolsmodule);
621 if (m == NULL)
622 return NULL;
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000623
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000624 for (i=0 ; typelist[i] != NULL ; i++) {
625 if (PyType_Ready(typelist[i]) < 0) {
626 Py_DECREF(m);
627 return NULL;
628 }
629 name = strchr(typelist[i]->tp_name, '.');
630 assert (name != NULL);
631 Py_INCREF(typelist[i]);
632 PyModule_AddObject(m, name+1, (PyObject *)typelist[i]);
633 }
634 return m;
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000635}