blob: 24da67741b841ff2ac71cb11564f2f2f19daee7b [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{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000028 PyObject *func;
29 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
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000037 func = PyTuple_GET_ITEM(args, 0);
38 if (!PyCallable_Check(func)) {
39 PyErr_SetString(PyExc_TypeError,
40 "the first argument must be callable");
41 return NULL;
42 }
Raymond Hettinger9c323f82005-02-28 19:39:44 +000043
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000044 /* create partialobject structure */
45 pto = (partialobject *)type->tp_alloc(type, 0);
46 if (pto == NULL)
47 return NULL;
Raymond Hettinger9c323f82005-02-28 19:39:44 +000048
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000049 pto->fn = func;
50 Py_INCREF(func);
51 pto->args = PyTuple_GetSlice(args, 1, PY_SSIZE_T_MAX);
52 if (pto->args == NULL) {
53 pto->kw = NULL;
54 Py_DECREF(pto);
55 return NULL;
56 }
Benjamin Peterson65bcdd72015-05-09 00:25:18 -040057 pto->kw = (kw != NULL) ? PyDict_Copy(kw) : PyDict_New();
58 if (pto->kw == NULL) {
59 Py_DECREF(pto);
60 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000061 }
Raymond Hettinger9c323f82005-02-28 19:39:44 +000062
Benjamin Peterson65bcdd72015-05-09 00:25:18 -040063
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000064 pto->weakreflist = NULL;
65 pto->dict = NULL;
Raymond Hettingerc8b6d1b2005-03-08 06:14:50 +000066
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000067 return (PyObject *)pto;
Raymond Hettinger9c323f82005-02-28 19:39:44 +000068}
69
70static void
71partial_dealloc(partialobject *pto)
72{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000073 PyObject_GC_UnTrack(pto);
74 if (pto->weakreflist != NULL)
75 PyObject_ClearWeakRefs((PyObject *) pto);
76 Py_XDECREF(pto->fn);
77 Py_XDECREF(pto->args);
78 Py_XDECREF(pto->kw);
79 Py_XDECREF(pto->dict);
80 Py_TYPE(pto)->tp_free(pto);
Raymond Hettinger9c323f82005-02-28 19:39:44 +000081}
82
83static PyObject *
84partial_call(partialobject *pto, PyObject *args, PyObject *kw)
85{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000086 PyObject *ret;
87 PyObject *argappl = NULL, *kwappl = NULL;
Raymond Hettinger9c323f82005-02-28 19:39:44 +000088
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000089 assert (PyCallable_Check(pto->fn));
90 assert (PyTuple_Check(pto->args));
91 assert (pto->kw == Py_None || PyDict_Check(pto->kw));
Raymond Hettinger9c323f82005-02-28 19:39:44 +000092
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000093 if (PyTuple_GET_SIZE(pto->args) == 0) {
94 argappl = args;
95 Py_INCREF(args);
96 } else if (PyTuple_GET_SIZE(args) == 0) {
97 argappl = pto->args;
98 Py_INCREF(pto->args);
99 } else {
100 argappl = PySequence_Concat(pto->args, args);
101 if (argappl == NULL)
102 return NULL;
103 }
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000104
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000105 if (pto->kw == Py_None) {
106 kwappl = kw;
107 Py_XINCREF(kw);
108 } else {
109 kwappl = PyDict_Copy(pto->kw);
110 if (kwappl == NULL) {
111 Py_DECREF(argappl);
112 return NULL;
113 }
114 if (kw != NULL) {
115 if (PyDict_Merge(kwappl, kw, 1) != 0) {
116 Py_DECREF(argappl);
117 Py_DECREF(kwappl);
118 return NULL;
119 }
120 }
121 }
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000122
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000123 ret = PyObject_Call(pto->fn, argappl, kwappl);
124 Py_DECREF(argappl);
125 Py_XDECREF(kwappl);
126 return ret;
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000127}
128
129static int
130partial_traverse(partialobject *pto, visitproc visit, void *arg)
131{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000132 Py_VISIT(pto->fn);
133 Py_VISIT(pto->args);
134 Py_VISIT(pto->kw);
135 Py_VISIT(pto->dict);
136 return 0;
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000137}
138
139PyDoc_STRVAR(partial_doc,
140"partial(func, *args, **keywords) - new function with partial application\n\
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000141 of the given arguments and keywords.\n");
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000142
143#define OFF(x) offsetof(partialobject, x)
144static PyMemberDef partial_memberlist[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000145 {"func", T_OBJECT, OFF(fn), READONLY,
146 "function object to use in future partial calls"},
147 {"args", T_OBJECT, OFF(args), READONLY,
148 "tuple of arguments to future partial calls"},
149 {"keywords", T_OBJECT, OFF(kw), READONLY,
150 "dictionary of keyword arguments to future partial calls"},
151 {NULL} /* Sentinel */
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000152};
153
Georg Brandlc2fb6c72006-02-21 17:49:57 +0000154static PyGetSetDef partial_getsetlist[] = {
Benjamin Peterson23d7f122012-02-19 20:02:57 -0500155 {"__dict__", PyObject_GenericGetDict, PyObject_GenericSetDict},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000156 {NULL} /* Sentinel */
Raymond Hettingerc8b6d1b2005-03-08 06:14:50 +0000157};
158
Alexander Belopolsky41e422a2010-12-01 20:05:49 +0000159static PyObject *
160partial_repr(partialobject *pto)
161{
162 PyObject *result;
163 PyObject *arglist;
164 PyObject *tmp;
165 Py_ssize_t i, n;
166
167 arglist = PyUnicode_FromString("");
168 if (arglist == NULL) {
169 return NULL;
170 }
171 /* Pack positional arguments */
172 assert (PyTuple_Check(pto->args));
173 n = PyTuple_GET_SIZE(pto->args);
174 for (i = 0; i < n; i++) {
175 tmp = PyUnicode_FromFormat("%U, %R", arglist,
176 PyTuple_GET_ITEM(pto->args, i));
177 Py_DECREF(arglist);
178 if (tmp == NULL)
179 return NULL;
180 arglist = tmp;
181 }
182 /* Pack keyword arguments */
183 assert (pto->kw == Py_None || PyDict_Check(pto->kw));
184 if (pto->kw != Py_None) {
185 PyObject *key, *value;
186 for (i = 0; PyDict_Next(pto->kw, &i, &key, &value);) {
187 tmp = PyUnicode_FromFormat("%U, %U=%R", arglist,
188 key, value);
189 Py_DECREF(arglist);
190 if (tmp == NULL)
191 return NULL;
192 arglist = tmp;
193 }
194 }
195 result = PyUnicode_FromFormat("%s(%R%U)", Py_TYPE(pto)->tp_name,
196 pto->fn, arglist);
197 Py_DECREF(arglist);
198 return result;
199}
200
Jack Diederiche0cbd692009-04-01 04:27:09 +0000201/* Pickle strategy:
202 __reduce__ by itself doesn't support getting kwargs in the unpickle
203 operation so we define a __setstate__ that replaces all the information
204 about the partial. If we only replaced part of it someone would use
Ezio Melotti13925002011-03-16 11:05:33 +0200205 it as a hook to do strange things.
Jack Diederiche0cbd692009-04-01 04:27:09 +0000206 */
207
Antoine Pitrou69f71142009-05-24 21:25:49 +0000208static PyObject *
Jack Diederiche0cbd692009-04-01 04:27:09 +0000209partial_reduce(partialobject *pto, PyObject *unused)
210{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000211 return Py_BuildValue("O(O)(OOOO)", Py_TYPE(pto), pto->fn, pto->fn,
212 pto->args, pto->kw,
213 pto->dict ? pto->dict : Py_None);
Jack Diederiche0cbd692009-04-01 04:27:09 +0000214}
215
Antoine Pitrou69f71142009-05-24 21:25:49 +0000216static PyObject *
Serhiy Storchaka19c4e0d2013-02-04 12:47:24 +0200217partial_setstate(partialobject *pto, PyObject *state)
Jack Diederiche0cbd692009-04-01 04:27:09 +0000218{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000219 PyObject *fn, *fnargs, *kw, *dict;
Serhiy Storchaka19c4e0d2013-02-04 12:47:24 +0200220 if (!PyArg_ParseTuple(state, "OOOO",
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000221 &fn, &fnargs, &kw, &dict))
222 return NULL;
223 Py_XDECREF(pto->fn);
224 Py_XDECREF(pto->args);
225 Py_XDECREF(pto->kw);
226 Py_XDECREF(pto->dict);
227 pto->fn = fn;
228 pto->args = fnargs;
229 pto->kw = kw;
230 if (dict != Py_None) {
231 pto->dict = dict;
232 Py_INCREF(dict);
233 } else {
234 pto->dict = NULL;
235 }
236 Py_INCREF(fn);
237 Py_INCREF(fnargs);
238 Py_INCREF(kw);
239 Py_RETURN_NONE;
Jack Diederiche0cbd692009-04-01 04:27:09 +0000240}
241
242static PyMethodDef partial_methods[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000243 {"__reduce__", (PyCFunction)partial_reduce, METH_NOARGS},
Serhiy Storchaka19c4e0d2013-02-04 12:47:24 +0200244 {"__setstate__", (PyCFunction)partial_setstate, METH_O},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000245 {NULL, NULL} /* sentinel */
Jack Diederiche0cbd692009-04-01 04:27:09 +0000246};
247
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000248static PyTypeObject partial_type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000249 PyVarObject_HEAD_INIT(NULL, 0)
250 "functools.partial", /* tp_name */
251 sizeof(partialobject), /* tp_basicsize */
252 0, /* tp_itemsize */
253 /* methods */
254 (destructor)partial_dealloc, /* tp_dealloc */
255 0, /* tp_print */
256 0, /* tp_getattr */
257 0, /* tp_setattr */
258 0, /* tp_reserved */
Alexander Belopolsky41e422a2010-12-01 20:05:49 +0000259 (reprfunc)partial_repr, /* tp_repr */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000260 0, /* tp_as_number */
261 0, /* tp_as_sequence */
262 0, /* tp_as_mapping */
263 0, /* tp_hash */
264 (ternaryfunc)partial_call, /* tp_call */
265 0, /* tp_str */
266 PyObject_GenericGetAttr, /* tp_getattro */
267 PyObject_GenericSetAttr, /* tp_setattro */
268 0, /* tp_as_buffer */
269 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
270 Py_TPFLAGS_BASETYPE, /* tp_flags */
271 partial_doc, /* tp_doc */
272 (traverseproc)partial_traverse, /* tp_traverse */
273 0, /* tp_clear */
274 0, /* tp_richcompare */
275 offsetof(partialobject, weakreflist), /* tp_weaklistoffset */
276 0, /* tp_iter */
277 0, /* tp_iternext */
278 partial_methods, /* tp_methods */
279 partial_memberlist, /* tp_members */
280 partial_getsetlist, /* tp_getset */
281 0, /* tp_base */
282 0, /* tp_dict */
283 0, /* tp_descr_get */
284 0, /* tp_descr_set */
285 offsetof(partialobject, dict), /* tp_dictoffset */
286 0, /* tp_init */
287 0, /* tp_alloc */
288 partial_new, /* tp_new */
289 PyObject_GC_Del, /* tp_free */
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000290};
291
292
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700293/* cmp_to_key ***************************************************************/
294
295typedef struct {
Victor Stinner446c8d52011-04-05 12:21:35 +0200296 PyObject_HEAD
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700297 PyObject *cmp;
298 PyObject *object;
299} keyobject;
300
301static void
302keyobject_dealloc(keyobject *ko)
303{
304 Py_DECREF(ko->cmp);
305 Py_XDECREF(ko->object);
306 PyObject_FREE(ko);
307}
308
309static int
310keyobject_traverse(keyobject *ko, visitproc visit, void *arg)
311{
312 Py_VISIT(ko->cmp);
313 if (ko->object)
314 Py_VISIT(ko->object);
315 return 0;
316}
317
Benjamin Peterson3bd97292011-04-05 17:25:14 -0500318static int
319keyobject_clear(keyobject *ko)
320{
321 Py_CLEAR(ko->cmp);
322 if (ko->object)
323 Py_CLEAR(ko->object);
324 return 0;
325}
326
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700327static PyMemberDef keyobject_members[] = {
328 {"obj", T_OBJECT,
329 offsetof(keyobject, object), 0,
330 PyDoc_STR("Value wrapped by a key function.")},
331 {NULL}
332};
333
334static PyObject *
Raymond Hettingera5632862011-04-09 12:57:00 -0700335keyobject_call(keyobject *ko, PyObject *args, PyObject *kwds);
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700336
337static PyObject *
338keyobject_richcompare(PyObject *ko, PyObject *other, int op);
339
340static PyTypeObject keyobject_type = {
341 PyVarObject_HEAD_INIT(&PyType_Type, 0)
342 "functools.KeyWrapper", /* tp_name */
343 sizeof(keyobject), /* tp_basicsize */
344 0, /* tp_itemsize */
345 /* methods */
346 (destructor)keyobject_dealloc, /* tp_dealloc */
347 0, /* tp_print */
348 0, /* tp_getattr */
349 0, /* tp_setattr */
350 0, /* tp_reserved */
351 0, /* tp_repr */
352 0, /* tp_as_number */
353 0, /* tp_as_sequence */
354 0, /* tp_as_mapping */
355 0, /* tp_hash */
356 (ternaryfunc)keyobject_call, /* tp_call */
357 0, /* tp_str */
358 PyObject_GenericGetAttr, /* tp_getattro */
359 0, /* tp_setattro */
360 0, /* tp_as_buffer */
361 Py_TPFLAGS_DEFAULT, /* tp_flags */
362 0, /* tp_doc */
363 (traverseproc)keyobject_traverse, /* tp_traverse */
Benjamin Peterson3bd97292011-04-05 17:25:14 -0500364 (inquiry)keyobject_clear, /* tp_clear */
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700365 keyobject_richcompare, /* tp_richcompare */
366 0, /* tp_weaklistoffset */
367 0, /* tp_iter */
368 0, /* tp_iternext */
369 0, /* tp_methods */
370 keyobject_members, /* tp_members */
371 0, /* tp_getset */
372};
373
374static PyObject *
375keyobject_call(keyobject *ko, PyObject *args, PyObject *kwds)
376{
377 PyObject *object;
378 keyobject *result;
379 static char *kwargs[] = {"obj", NULL};
380
381 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:K", kwargs, &object))
382 return NULL;
383 result = PyObject_New(keyobject, &keyobject_type);
384 if (!result)
385 return NULL;
386 Py_INCREF(ko->cmp);
387 result->cmp = ko->cmp;
388 Py_INCREF(object);
389 result->object = object;
390 return (PyObject *)result;
391}
392
393static PyObject *
394keyobject_richcompare(PyObject *ko, PyObject *other, int op)
395{
396 PyObject *res;
397 PyObject *args;
398 PyObject *x;
399 PyObject *y;
400 PyObject *compare;
401 PyObject *answer;
402 static PyObject *zero;
403
404 if (zero == NULL) {
405 zero = PyLong_FromLong(0);
406 if (!zero)
407 return NULL;
408 }
409
410 if (Py_TYPE(other) != &keyobject_type){
411 PyErr_Format(PyExc_TypeError, "other argument must be K instance");
412 return NULL;
413 }
414 compare = ((keyobject *) ko)->cmp;
415 assert(compare != NULL);
416 x = ((keyobject *) ko)->object;
417 y = ((keyobject *) other)->object;
418 if (!x || !y){
419 PyErr_Format(PyExc_AttributeError, "object");
420 return NULL;
421 }
422
423 /* Call the user's comparison function and translate the 3-way
424 * result into true or false (or error).
425 */
426 args = PyTuple_New(2);
427 if (args == NULL)
428 return NULL;
429 Py_INCREF(x);
430 Py_INCREF(y);
431 PyTuple_SET_ITEM(args, 0, x);
432 PyTuple_SET_ITEM(args, 1, y);
433 res = PyObject_Call(compare, args, NULL);
434 Py_DECREF(args);
435 if (res == NULL)
436 return NULL;
437 answer = PyObject_RichCompare(res, zero, op);
438 Py_DECREF(res);
439 return answer;
440}
441
442static PyObject *
Victor Stinner446c8d52011-04-05 12:21:35 +0200443functools_cmp_to_key(PyObject *self, PyObject *args, PyObject *kwds)
444{
445 PyObject *cmp;
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700446 static char *kwargs[] = {"mycmp", NULL};
Victor Stinner446c8d52011-04-05 12:21:35 +0200447 keyobject *object;
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700448
449 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:cmp_to_key", kwargs, &cmp))
450 return NULL;
Victor Stinner446c8d52011-04-05 12:21:35 +0200451 object = PyObject_New(keyobject, &keyobject_type);
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700452 if (!object)
453 return NULL;
454 Py_INCREF(cmp);
455 object->cmp = cmp;
456 object->object = NULL;
457 return (PyObject *)object;
458}
459
460PyDoc_STRVAR(functools_cmp_to_key_doc,
461"Convert a cmp= function into a key= function.");
462
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000463/* reduce (used to be a builtin) ********************************************/
464
465static PyObject *
466functools_reduce(PyObject *self, PyObject *args)
467{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000468 PyObject *seq, *func, *result = NULL, *it;
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000469
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000470 if (!PyArg_UnpackTuple(args, "reduce", 2, 3, &func, &seq, &result))
471 return NULL;
472 if (result != NULL)
473 Py_INCREF(result);
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000474
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000475 it = PyObject_GetIter(seq);
476 if (it == NULL) {
Alexander Belopolskye29e6bf2010-08-16 18:55:46 +0000477 if (PyErr_ExceptionMatches(PyExc_TypeError))
478 PyErr_SetString(PyExc_TypeError,
479 "reduce() arg 2 must support iteration");
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000480 Py_XDECREF(result);
481 return NULL;
482 }
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000483
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000484 if ((args = PyTuple_New(2)) == NULL)
485 goto Fail;
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000486
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000487 for (;;) {
488 PyObject *op2;
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000489
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000490 if (args->ob_refcnt > 1) {
491 Py_DECREF(args);
492 if ((args = PyTuple_New(2)) == NULL)
493 goto Fail;
494 }
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000495
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000496 op2 = PyIter_Next(it);
497 if (op2 == NULL) {
498 if (PyErr_Occurred())
499 goto Fail;
500 break;
501 }
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000502
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000503 if (result == NULL)
504 result = op2;
505 else {
506 PyTuple_SetItem(args, 0, result);
507 PyTuple_SetItem(args, 1, op2);
508 if ((result = PyEval_CallObject(func, args)) == NULL)
509 goto Fail;
510 }
511 }
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000512
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000513 Py_DECREF(args);
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000514
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000515 if (result == NULL)
516 PyErr_SetString(PyExc_TypeError,
517 "reduce() of empty sequence with no initial value");
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000518
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000519 Py_DECREF(it);
520 return result;
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000521
522Fail:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000523 Py_XDECREF(args);
524 Py_XDECREF(result);
525 Py_DECREF(it);
526 return NULL;
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000527}
528
529PyDoc_STRVAR(functools_reduce_doc,
530"reduce(function, sequence[, initial]) -> value\n\
531\n\
532Apply a function of two arguments cumulatively to the items of a sequence,\n\
533from left to right, so as to reduce the sequence to a single value.\n\
534For example, reduce(lambda x, y: x+y, [1, 2, 3, 4, 5]) calculates\n\
535((((1+2)+3)+4)+5). If initial is present, it is placed before the items\n\
536of the sequence in the calculation, and serves as a default when the\n\
537sequence is empty.");
538
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000539/* module level code ********************************************************/
540
541PyDoc_STRVAR(module_doc,
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000542"Tools that operate on functions.");
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000543
544static PyMethodDef module_methods[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000545 {"reduce", functools_reduce, METH_VARARGS, functools_reduce_doc},
Victor Stinner446c8d52011-04-05 12:21:35 +0200546 {"cmp_to_key", (PyCFunction)functools_cmp_to_key,
547 METH_VARARGS | METH_KEYWORDS, functools_cmp_to_key_doc},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000548 {NULL, NULL} /* sentinel */
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000549};
550
Martin v. Löwis1a214512008-06-11 05:26:20 +0000551
552static struct PyModuleDef _functoolsmodule = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000553 PyModuleDef_HEAD_INIT,
554 "_functools",
555 module_doc,
556 -1,
557 module_methods,
558 NULL,
559 NULL,
560 NULL,
561 NULL
Martin v. Löwis1a214512008-06-11 05:26:20 +0000562};
563
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000564PyMODINIT_FUNC
Martin v. Löwis1a214512008-06-11 05:26:20 +0000565PyInit__functools(void)
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000566{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000567 int i;
568 PyObject *m;
569 char *name;
570 PyTypeObject *typelist[] = {
571 &partial_type,
572 NULL
573 };
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000574
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000575 m = PyModule_Create(&_functoolsmodule);
576 if (m == NULL)
577 return NULL;
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000578
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000579 for (i=0 ; typelist[i] != NULL ; i++) {
580 if (PyType_Ready(typelist[i]) < 0) {
581 Py_DECREF(m);
582 return NULL;
583 }
584 name = strchr(typelist[i]->tp_name, '.');
585 assert (name != NULL);
586 Py_INCREF(typelist[i]);
587 PyModule_AddObject(m, name+1, (PyObject *)typelist[i]);
588 }
589 return m;
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000590}