blob: 3c82e5134a492df7b34a9eb5c64299e5840f96ef [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 {
Benjamin Petersondae2ef12015-05-09 00:29:08 -0400105 if (pkw == Py_None) {
106 pto->kw = PyDict_New();
107 if (pto->kw == NULL) {
108 Py_DECREF(pto);
109 return NULL;
110 }
111 }
112 else {
113 pto->kw = pkw;
114 Py_INCREF(pkw);
115 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000116 }
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000117
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000118 pto->weakreflist = NULL;
119 pto->dict = NULL;
Raymond Hettingerc8b6d1b2005-03-08 06:14:50 +0000120
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000121 return (PyObject *)pto;
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000122}
123
124static void
125partial_dealloc(partialobject *pto)
126{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000127 PyObject_GC_UnTrack(pto);
128 if (pto->weakreflist != NULL)
129 PyObject_ClearWeakRefs((PyObject *) pto);
130 Py_XDECREF(pto->fn);
131 Py_XDECREF(pto->args);
132 Py_XDECREF(pto->kw);
133 Py_XDECREF(pto->dict);
134 Py_TYPE(pto)->tp_free(pto);
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000135}
136
137static PyObject *
138partial_call(partialobject *pto, PyObject *args, PyObject *kw)
139{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000140 PyObject *ret;
141 PyObject *argappl = NULL, *kwappl = NULL;
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000142
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000143 assert (PyCallable_Check(pto->fn));
144 assert (PyTuple_Check(pto->args));
145 assert (pto->kw == Py_None || PyDict_Check(pto->kw));
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000146
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000147 if (PyTuple_GET_SIZE(pto->args) == 0) {
148 argappl = args;
149 Py_INCREF(args);
150 } else if (PyTuple_GET_SIZE(args) == 0) {
151 argappl = pto->args;
152 Py_INCREF(pto->args);
153 } else {
154 argappl = PySequence_Concat(pto->args, args);
155 if (argappl == NULL)
156 return NULL;
157 }
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000158
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000159 if (pto->kw == Py_None) {
160 kwappl = kw;
161 Py_XINCREF(kw);
162 } else {
163 kwappl = PyDict_Copy(pto->kw);
164 if (kwappl == NULL) {
165 Py_DECREF(argappl);
166 return NULL;
167 }
168 if (kw != NULL) {
169 if (PyDict_Merge(kwappl, kw, 1) != 0) {
170 Py_DECREF(argappl);
171 Py_DECREF(kwappl);
172 return NULL;
173 }
174 }
175 }
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000176
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000177 ret = PyObject_Call(pto->fn, argappl, kwappl);
178 Py_DECREF(argappl);
179 Py_XDECREF(kwappl);
180 return ret;
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000181}
182
183static int
184partial_traverse(partialobject *pto, visitproc visit, void *arg)
185{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000186 Py_VISIT(pto->fn);
187 Py_VISIT(pto->args);
188 Py_VISIT(pto->kw);
189 Py_VISIT(pto->dict);
190 return 0;
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000191}
192
193PyDoc_STRVAR(partial_doc,
194"partial(func, *args, **keywords) - new function with partial application\n\
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000195 of the given arguments and keywords.\n");
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000196
197#define OFF(x) offsetof(partialobject, x)
198static PyMemberDef partial_memberlist[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000199 {"func", T_OBJECT, OFF(fn), READONLY,
200 "function object to use in future partial calls"},
201 {"args", T_OBJECT, OFF(args), READONLY,
202 "tuple of arguments to future partial calls"},
203 {"keywords", T_OBJECT, OFF(kw), READONLY,
204 "dictionary of keyword arguments to future partial calls"},
205 {NULL} /* Sentinel */
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000206};
207
Georg Brandlc2fb6c72006-02-21 17:49:57 +0000208static PyGetSetDef partial_getsetlist[] = {
Benjamin Peterson23d7f122012-02-19 20:02:57 -0500209 {"__dict__", PyObject_GenericGetDict, PyObject_GenericSetDict},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000210 {NULL} /* Sentinel */
Raymond Hettingerc8b6d1b2005-03-08 06:14:50 +0000211};
212
Alexander Belopolsky41e422a2010-12-01 20:05:49 +0000213static PyObject *
214partial_repr(partialobject *pto)
215{
216 PyObject *result;
217 PyObject *arglist;
218 PyObject *tmp;
219 Py_ssize_t i, n;
220
221 arglist = PyUnicode_FromString("");
222 if (arglist == NULL) {
223 return NULL;
224 }
225 /* Pack positional arguments */
226 assert (PyTuple_Check(pto->args));
227 n = PyTuple_GET_SIZE(pto->args);
228 for (i = 0; i < n; i++) {
229 tmp = PyUnicode_FromFormat("%U, %R", arglist,
230 PyTuple_GET_ITEM(pto->args, i));
231 Py_DECREF(arglist);
232 if (tmp == NULL)
233 return NULL;
234 arglist = tmp;
235 }
236 /* Pack keyword arguments */
237 assert (pto->kw == Py_None || PyDict_Check(pto->kw));
238 if (pto->kw != Py_None) {
239 PyObject *key, *value;
240 for (i = 0; PyDict_Next(pto->kw, &i, &key, &value);) {
241 tmp = PyUnicode_FromFormat("%U, %U=%R", arglist,
242 key, value);
243 Py_DECREF(arglist);
244 if (tmp == NULL)
245 return NULL;
246 arglist = tmp;
247 }
248 }
249 result = PyUnicode_FromFormat("%s(%R%U)", Py_TYPE(pto)->tp_name,
250 pto->fn, arglist);
251 Py_DECREF(arglist);
252 return result;
253}
254
Jack Diederiche0cbd692009-04-01 04:27:09 +0000255/* Pickle strategy:
256 __reduce__ by itself doesn't support getting kwargs in the unpickle
257 operation so we define a __setstate__ that replaces all the information
258 about the partial. If we only replaced part of it someone would use
Ezio Melotti13925002011-03-16 11:05:33 +0200259 it as a hook to do strange things.
Jack Diederiche0cbd692009-04-01 04:27:09 +0000260 */
261
Antoine Pitrou69f71142009-05-24 21:25:49 +0000262static PyObject *
Jack Diederiche0cbd692009-04-01 04:27:09 +0000263partial_reduce(partialobject *pto, PyObject *unused)
264{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000265 return Py_BuildValue("O(O)(OOOO)", Py_TYPE(pto), pto->fn, pto->fn,
266 pto->args, pto->kw,
267 pto->dict ? pto->dict : Py_None);
Jack Diederiche0cbd692009-04-01 04:27:09 +0000268}
269
Antoine Pitrou69f71142009-05-24 21:25:49 +0000270static PyObject *
Serhiy Storchaka19c4e0d2013-02-04 12:47:24 +0200271partial_setstate(partialobject *pto, PyObject *state)
Jack Diederiche0cbd692009-04-01 04:27:09 +0000272{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000273 PyObject *fn, *fnargs, *kw, *dict;
Serhiy Storchaka19c4e0d2013-02-04 12:47:24 +0200274 if (!PyArg_ParseTuple(state, "OOOO",
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000275 &fn, &fnargs, &kw, &dict))
276 return NULL;
277 Py_XDECREF(pto->fn);
278 Py_XDECREF(pto->args);
279 Py_XDECREF(pto->kw);
280 Py_XDECREF(pto->dict);
281 pto->fn = fn;
282 pto->args = fnargs;
283 pto->kw = kw;
284 if (dict != Py_None) {
285 pto->dict = dict;
286 Py_INCREF(dict);
287 } else {
288 pto->dict = NULL;
289 }
290 Py_INCREF(fn);
291 Py_INCREF(fnargs);
292 Py_INCREF(kw);
293 Py_RETURN_NONE;
Jack Diederiche0cbd692009-04-01 04:27:09 +0000294}
295
296static PyMethodDef partial_methods[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000297 {"__reduce__", (PyCFunction)partial_reduce, METH_NOARGS},
Serhiy Storchaka19c4e0d2013-02-04 12:47:24 +0200298 {"__setstate__", (PyCFunction)partial_setstate, METH_O},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000299 {NULL, NULL} /* sentinel */
Jack Diederiche0cbd692009-04-01 04:27:09 +0000300};
301
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000302static PyTypeObject partial_type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000303 PyVarObject_HEAD_INIT(NULL, 0)
304 "functools.partial", /* tp_name */
305 sizeof(partialobject), /* tp_basicsize */
306 0, /* tp_itemsize */
307 /* methods */
308 (destructor)partial_dealloc, /* tp_dealloc */
309 0, /* tp_print */
310 0, /* tp_getattr */
311 0, /* tp_setattr */
312 0, /* tp_reserved */
Alexander Belopolsky41e422a2010-12-01 20:05:49 +0000313 (reprfunc)partial_repr, /* tp_repr */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000314 0, /* tp_as_number */
315 0, /* tp_as_sequence */
316 0, /* tp_as_mapping */
317 0, /* tp_hash */
318 (ternaryfunc)partial_call, /* tp_call */
319 0, /* tp_str */
320 PyObject_GenericGetAttr, /* tp_getattro */
321 PyObject_GenericSetAttr, /* tp_setattro */
322 0, /* tp_as_buffer */
323 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
324 Py_TPFLAGS_BASETYPE, /* tp_flags */
325 partial_doc, /* tp_doc */
326 (traverseproc)partial_traverse, /* tp_traverse */
327 0, /* tp_clear */
328 0, /* tp_richcompare */
329 offsetof(partialobject, weakreflist), /* tp_weaklistoffset */
330 0, /* tp_iter */
331 0, /* tp_iternext */
332 partial_methods, /* tp_methods */
333 partial_memberlist, /* tp_members */
334 partial_getsetlist, /* tp_getset */
335 0, /* tp_base */
336 0, /* tp_dict */
337 0, /* tp_descr_get */
338 0, /* tp_descr_set */
339 offsetof(partialobject, dict), /* tp_dictoffset */
340 0, /* tp_init */
341 0, /* tp_alloc */
342 partial_new, /* tp_new */
343 PyObject_GC_Del, /* tp_free */
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000344};
345
346
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700347/* cmp_to_key ***************************************************************/
348
349typedef struct {
Victor Stinner446c8d52011-04-05 12:21:35 +0200350 PyObject_HEAD
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700351 PyObject *cmp;
352 PyObject *object;
353} keyobject;
354
355static void
356keyobject_dealloc(keyobject *ko)
357{
358 Py_DECREF(ko->cmp);
359 Py_XDECREF(ko->object);
360 PyObject_FREE(ko);
361}
362
363static int
364keyobject_traverse(keyobject *ko, visitproc visit, void *arg)
365{
366 Py_VISIT(ko->cmp);
367 if (ko->object)
368 Py_VISIT(ko->object);
369 return 0;
370}
371
Benjamin Peterson3bd97292011-04-05 17:25:14 -0500372static int
373keyobject_clear(keyobject *ko)
374{
375 Py_CLEAR(ko->cmp);
376 if (ko->object)
377 Py_CLEAR(ko->object);
378 return 0;
379}
380
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700381static PyMemberDef keyobject_members[] = {
382 {"obj", T_OBJECT,
383 offsetof(keyobject, object), 0,
384 PyDoc_STR("Value wrapped by a key function.")},
385 {NULL}
386};
387
388static PyObject *
Raymond Hettingera5632862011-04-09 12:57:00 -0700389keyobject_call(keyobject *ko, PyObject *args, PyObject *kwds);
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700390
391static PyObject *
392keyobject_richcompare(PyObject *ko, PyObject *other, int op);
393
394static PyTypeObject keyobject_type = {
395 PyVarObject_HEAD_INIT(&PyType_Type, 0)
396 "functools.KeyWrapper", /* tp_name */
397 sizeof(keyobject), /* tp_basicsize */
398 0, /* tp_itemsize */
399 /* methods */
400 (destructor)keyobject_dealloc, /* tp_dealloc */
401 0, /* tp_print */
402 0, /* tp_getattr */
403 0, /* tp_setattr */
404 0, /* tp_reserved */
405 0, /* tp_repr */
406 0, /* tp_as_number */
407 0, /* tp_as_sequence */
408 0, /* tp_as_mapping */
409 0, /* tp_hash */
410 (ternaryfunc)keyobject_call, /* tp_call */
411 0, /* tp_str */
412 PyObject_GenericGetAttr, /* tp_getattro */
413 0, /* tp_setattro */
414 0, /* tp_as_buffer */
415 Py_TPFLAGS_DEFAULT, /* tp_flags */
416 0, /* tp_doc */
417 (traverseproc)keyobject_traverse, /* tp_traverse */
Benjamin Peterson3bd97292011-04-05 17:25:14 -0500418 (inquiry)keyobject_clear, /* tp_clear */
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700419 keyobject_richcompare, /* tp_richcompare */
420 0, /* tp_weaklistoffset */
421 0, /* tp_iter */
422 0, /* tp_iternext */
423 0, /* tp_methods */
424 keyobject_members, /* tp_members */
425 0, /* tp_getset */
426};
427
428static PyObject *
429keyobject_call(keyobject *ko, PyObject *args, PyObject *kwds)
430{
431 PyObject *object;
432 keyobject *result;
433 static char *kwargs[] = {"obj", NULL};
434
435 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:K", kwargs, &object))
436 return NULL;
437 result = PyObject_New(keyobject, &keyobject_type);
438 if (!result)
439 return NULL;
440 Py_INCREF(ko->cmp);
441 result->cmp = ko->cmp;
442 Py_INCREF(object);
443 result->object = object;
444 return (PyObject *)result;
445}
446
447static PyObject *
448keyobject_richcompare(PyObject *ko, PyObject *other, int op)
449{
450 PyObject *res;
451 PyObject *args;
452 PyObject *x;
453 PyObject *y;
454 PyObject *compare;
455 PyObject *answer;
456 static PyObject *zero;
457
458 if (zero == NULL) {
459 zero = PyLong_FromLong(0);
460 if (!zero)
461 return NULL;
462 }
463
464 if (Py_TYPE(other) != &keyobject_type){
465 PyErr_Format(PyExc_TypeError, "other argument must be K instance");
466 return NULL;
467 }
468 compare = ((keyobject *) ko)->cmp;
469 assert(compare != NULL);
470 x = ((keyobject *) ko)->object;
471 y = ((keyobject *) other)->object;
472 if (!x || !y){
473 PyErr_Format(PyExc_AttributeError, "object");
474 return NULL;
475 }
476
477 /* Call the user's comparison function and translate the 3-way
478 * result into true or false (or error).
479 */
480 args = PyTuple_New(2);
481 if (args == NULL)
482 return NULL;
483 Py_INCREF(x);
484 Py_INCREF(y);
485 PyTuple_SET_ITEM(args, 0, x);
486 PyTuple_SET_ITEM(args, 1, y);
487 res = PyObject_Call(compare, args, NULL);
488 Py_DECREF(args);
489 if (res == NULL)
490 return NULL;
491 answer = PyObject_RichCompare(res, zero, op);
492 Py_DECREF(res);
493 return answer;
494}
495
496static PyObject *
Victor Stinner446c8d52011-04-05 12:21:35 +0200497functools_cmp_to_key(PyObject *self, PyObject *args, PyObject *kwds)
498{
499 PyObject *cmp;
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700500 static char *kwargs[] = {"mycmp", NULL};
Victor Stinner446c8d52011-04-05 12:21:35 +0200501 keyobject *object;
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700502
503 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:cmp_to_key", kwargs, &cmp))
504 return NULL;
Victor Stinner446c8d52011-04-05 12:21:35 +0200505 object = PyObject_New(keyobject, &keyobject_type);
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700506 if (!object)
507 return NULL;
508 Py_INCREF(cmp);
509 object->cmp = cmp;
510 object->object = NULL;
511 return (PyObject *)object;
512}
513
514PyDoc_STRVAR(functools_cmp_to_key_doc,
515"Convert a cmp= function into a key= function.");
516
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000517/* reduce (used to be a builtin) ********************************************/
518
519static PyObject *
520functools_reduce(PyObject *self, PyObject *args)
521{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000522 PyObject *seq, *func, *result = NULL, *it;
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000523
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000524 if (!PyArg_UnpackTuple(args, "reduce", 2, 3, &func, &seq, &result))
525 return NULL;
526 if (result != NULL)
527 Py_INCREF(result);
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000528
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000529 it = PyObject_GetIter(seq);
530 if (it == NULL) {
Alexander Belopolskye29e6bf2010-08-16 18:55:46 +0000531 if (PyErr_ExceptionMatches(PyExc_TypeError))
532 PyErr_SetString(PyExc_TypeError,
533 "reduce() arg 2 must support iteration");
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000534 Py_XDECREF(result);
535 return NULL;
536 }
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000537
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000538 if ((args = PyTuple_New(2)) == NULL)
539 goto Fail;
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000540
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000541 for (;;) {
542 PyObject *op2;
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000543
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000544 if (args->ob_refcnt > 1) {
545 Py_DECREF(args);
546 if ((args = PyTuple_New(2)) == NULL)
547 goto Fail;
548 }
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000549
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000550 op2 = PyIter_Next(it);
551 if (op2 == NULL) {
552 if (PyErr_Occurred())
553 goto Fail;
554 break;
555 }
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000556
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000557 if (result == NULL)
558 result = op2;
559 else {
560 PyTuple_SetItem(args, 0, result);
561 PyTuple_SetItem(args, 1, op2);
562 if ((result = PyEval_CallObject(func, args)) == NULL)
563 goto Fail;
564 }
565 }
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000566
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000567 Py_DECREF(args);
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000568
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000569 if (result == NULL)
570 PyErr_SetString(PyExc_TypeError,
571 "reduce() of empty sequence with no initial value");
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000572
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000573 Py_DECREF(it);
574 return result;
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000575
576Fail:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000577 Py_XDECREF(args);
578 Py_XDECREF(result);
579 Py_DECREF(it);
580 return NULL;
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000581}
582
583PyDoc_STRVAR(functools_reduce_doc,
584"reduce(function, sequence[, initial]) -> value\n\
585\n\
586Apply a function of two arguments cumulatively to the items of a sequence,\n\
587from left to right, so as to reduce the sequence to a single value.\n\
588For example, reduce(lambda x, y: x+y, [1, 2, 3, 4, 5]) calculates\n\
589((((1+2)+3)+4)+5). If initial is present, it is placed before the items\n\
590of the sequence in the calculation, and serves as a default when the\n\
591sequence is empty.");
592
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000593/* module level code ********************************************************/
594
595PyDoc_STRVAR(module_doc,
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000596"Tools that operate on functions.");
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000597
598static PyMethodDef module_methods[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000599 {"reduce", functools_reduce, METH_VARARGS, functools_reduce_doc},
Victor Stinner446c8d52011-04-05 12:21:35 +0200600 {"cmp_to_key", (PyCFunction)functools_cmp_to_key,
601 METH_VARARGS | METH_KEYWORDS, functools_cmp_to_key_doc},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000602 {NULL, NULL} /* sentinel */
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000603};
604
Martin v. Löwis1a214512008-06-11 05:26:20 +0000605
606static struct PyModuleDef _functoolsmodule = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000607 PyModuleDef_HEAD_INIT,
608 "_functools",
609 module_doc,
610 -1,
611 module_methods,
612 NULL,
613 NULL,
614 NULL,
615 NULL
Martin v. Löwis1a214512008-06-11 05:26:20 +0000616};
617
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000618PyMODINIT_FUNC
Martin v. Löwis1a214512008-06-11 05:26:20 +0000619PyInit__functools(void)
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000620{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000621 int i;
622 PyObject *m;
623 char *name;
624 PyTypeObject *typelist[] = {
625 &partial_type,
626 NULL
627 };
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000628
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000629 m = PyModule_Create(&_functoolsmodule);
630 if (m == NULL)
631 return NULL;
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000632
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000633 for (i=0 ; typelist[i] != NULL ; i++) {
634 if (PyType_Ready(typelist[i]) < 0) {
635 Py_DECREF(m);
636 return NULL;
637 }
638 name = strchr(typelist[i]->tp_name, '.');
639 assert (name != NULL);
640 Py_INCREF(typelist[i]);
641 PyModule_AddObject(m, name+1, (PyObject *)typelist[i]);
642 }
643 return m;
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000644}