blob: 57dfba041013b82ce0b4fa8ec2a013e2663ad41b [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 }
57 if (kw != NULL) {
58 pto->kw = PyDict_Copy(kw);
59 if (pto->kw == NULL) {
60 Py_DECREF(pto);
61 return NULL;
62 }
63 } else {
64 pto->kw = Py_None;
65 Py_INCREF(Py_None);
66 }
Raymond Hettinger9c323f82005-02-28 19:39:44 +000067
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000068 pto->weakreflist = NULL;
69 pto->dict = NULL;
Raymond Hettingerc8b6d1b2005-03-08 06:14:50 +000070
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000071 return (PyObject *)pto;
Raymond Hettinger9c323f82005-02-28 19:39:44 +000072}
73
74static void
75partial_dealloc(partialobject *pto)
76{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000077 PyObject_GC_UnTrack(pto);
78 if (pto->weakreflist != NULL)
79 PyObject_ClearWeakRefs((PyObject *) pto);
80 Py_XDECREF(pto->fn);
81 Py_XDECREF(pto->args);
82 Py_XDECREF(pto->kw);
83 Py_XDECREF(pto->dict);
84 Py_TYPE(pto)->tp_free(pto);
Raymond Hettinger9c323f82005-02-28 19:39:44 +000085}
86
87static PyObject *
88partial_call(partialobject *pto, PyObject *args, PyObject *kw)
89{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000090 PyObject *ret;
91 PyObject *argappl = NULL, *kwappl = NULL;
Raymond Hettinger9c323f82005-02-28 19:39:44 +000092
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000093 assert (PyCallable_Check(pto->fn));
94 assert (PyTuple_Check(pto->args));
95 assert (pto->kw == Py_None || PyDict_Check(pto->kw));
Raymond Hettinger9c323f82005-02-28 19:39:44 +000096
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000097 if (PyTuple_GET_SIZE(pto->args) == 0) {
98 argappl = args;
99 Py_INCREF(args);
100 } else if (PyTuple_GET_SIZE(args) == 0) {
101 argappl = pto->args;
102 Py_INCREF(pto->args);
103 } else {
104 argappl = PySequence_Concat(pto->args, args);
105 if (argappl == NULL)
106 return NULL;
107 }
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000108
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000109 if (pto->kw == Py_None) {
110 kwappl = kw;
111 Py_XINCREF(kw);
112 } else {
113 kwappl = PyDict_Copy(pto->kw);
114 if (kwappl == NULL) {
115 Py_DECREF(argappl);
116 return NULL;
117 }
118 if (kw != NULL) {
119 if (PyDict_Merge(kwappl, kw, 1) != 0) {
120 Py_DECREF(argappl);
121 Py_DECREF(kwappl);
122 return NULL;
123 }
124 }
125 }
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000126
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000127 ret = PyObject_Call(pto->fn, argappl, kwappl);
128 Py_DECREF(argappl);
129 Py_XDECREF(kwappl);
130 return ret;
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000131}
132
133static int
134partial_traverse(partialobject *pto, visitproc visit, void *arg)
135{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000136 Py_VISIT(pto->fn);
137 Py_VISIT(pto->args);
138 Py_VISIT(pto->kw);
139 Py_VISIT(pto->dict);
140 return 0;
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000141}
142
143PyDoc_STRVAR(partial_doc,
144"partial(func, *args, **keywords) - new function with partial application\n\
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000145 of the given arguments and keywords.\n");
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000146
147#define OFF(x) offsetof(partialobject, x)
148static PyMemberDef partial_memberlist[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000149 {"func", T_OBJECT, OFF(fn), READONLY,
150 "function object to use in future partial calls"},
151 {"args", T_OBJECT, OFF(args), READONLY,
152 "tuple of arguments to future partial calls"},
153 {"keywords", T_OBJECT, OFF(kw), READONLY,
154 "dictionary of keyword arguments to future partial calls"},
155 {NULL} /* Sentinel */
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000156};
157
Georg Brandlc2fb6c72006-02-21 17:49:57 +0000158static PyGetSetDef partial_getsetlist[] = {
Benjamin Peterson23d7f122012-02-19 20:02:57 -0500159 {"__dict__", PyObject_GenericGetDict, PyObject_GenericSetDict},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000160 {NULL} /* Sentinel */
Raymond Hettingerc8b6d1b2005-03-08 06:14:50 +0000161};
162
Alexander Belopolsky41e422a2010-12-01 20:05:49 +0000163static PyObject *
164partial_repr(partialobject *pto)
165{
166 PyObject *result;
167 PyObject *arglist;
168 PyObject *tmp;
169 Py_ssize_t i, n;
170
171 arglist = PyUnicode_FromString("");
172 if (arglist == NULL) {
173 return NULL;
174 }
175 /* Pack positional arguments */
176 assert (PyTuple_Check(pto->args));
177 n = PyTuple_GET_SIZE(pto->args);
178 for (i = 0; i < n; i++) {
179 tmp = PyUnicode_FromFormat("%U, %R", arglist,
180 PyTuple_GET_ITEM(pto->args, i));
181 Py_DECREF(arglist);
182 if (tmp == NULL)
183 return NULL;
184 arglist = tmp;
185 }
186 /* Pack keyword arguments */
187 assert (pto->kw == Py_None || PyDict_Check(pto->kw));
188 if (pto->kw != Py_None) {
189 PyObject *key, *value;
190 for (i = 0; PyDict_Next(pto->kw, &i, &key, &value);) {
191 tmp = PyUnicode_FromFormat("%U, %U=%R", arglist,
192 key, value);
193 Py_DECREF(arglist);
194 if (tmp == NULL)
195 return NULL;
196 arglist = tmp;
197 }
198 }
199 result = PyUnicode_FromFormat("%s(%R%U)", Py_TYPE(pto)->tp_name,
200 pto->fn, arglist);
201 Py_DECREF(arglist);
202 return result;
203}
204
Jack Diederiche0cbd692009-04-01 04:27:09 +0000205/* Pickle strategy:
206 __reduce__ by itself doesn't support getting kwargs in the unpickle
207 operation so we define a __setstate__ that replaces all the information
208 about the partial. If we only replaced part of it someone would use
Ezio Melotti13925002011-03-16 11:05:33 +0200209 it as a hook to do strange things.
Jack Diederiche0cbd692009-04-01 04:27:09 +0000210 */
211
Antoine Pitrou69f71142009-05-24 21:25:49 +0000212static PyObject *
Jack Diederiche0cbd692009-04-01 04:27:09 +0000213partial_reduce(partialobject *pto, PyObject *unused)
214{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000215 return Py_BuildValue("O(O)(OOOO)", Py_TYPE(pto), pto->fn, pto->fn,
216 pto->args, pto->kw,
217 pto->dict ? pto->dict : Py_None);
Jack Diederiche0cbd692009-04-01 04:27:09 +0000218}
219
Antoine Pitrou69f71142009-05-24 21:25:49 +0000220static PyObject *
Serhiy Storchaka19c4e0d2013-02-04 12:47:24 +0200221partial_setstate(partialobject *pto, PyObject *state)
Jack Diederiche0cbd692009-04-01 04:27:09 +0000222{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000223 PyObject *fn, *fnargs, *kw, *dict;
Serhiy Storchaka19c4e0d2013-02-04 12:47:24 +0200224 if (!PyArg_ParseTuple(state, "OOOO",
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000225 &fn, &fnargs, &kw, &dict))
226 return NULL;
227 Py_XDECREF(pto->fn);
228 Py_XDECREF(pto->args);
229 Py_XDECREF(pto->kw);
230 Py_XDECREF(pto->dict);
231 pto->fn = fn;
232 pto->args = fnargs;
233 pto->kw = kw;
234 if (dict != Py_None) {
235 pto->dict = dict;
236 Py_INCREF(dict);
237 } else {
238 pto->dict = NULL;
239 }
240 Py_INCREF(fn);
241 Py_INCREF(fnargs);
242 Py_INCREF(kw);
243 Py_RETURN_NONE;
Jack Diederiche0cbd692009-04-01 04:27:09 +0000244}
245
246static PyMethodDef partial_methods[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000247 {"__reduce__", (PyCFunction)partial_reduce, METH_NOARGS},
Serhiy Storchaka19c4e0d2013-02-04 12:47:24 +0200248 {"__setstate__", (PyCFunction)partial_setstate, METH_O},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000249 {NULL, NULL} /* sentinel */
Jack Diederiche0cbd692009-04-01 04:27:09 +0000250};
251
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000252static PyTypeObject partial_type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000253 PyVarObject_HEAD_INIT(NULL, 0)
254 "functools.partial", /* tp_name */
255 sizeof(partialobject), /* tp_basicsize */
256 0, /* tp_itemsize */
257 /* methods */
258 (destructor)partial_dealloc, /* tp_dealloc */
259 0, /* tp_print */
260 0, /* tp_getattr */
261 0, /* tp_setattr */
262 0, /* tp_reserved */
Alexander Belopolsky41e422a2010-12-01 20:05:49 +0000263 (reprfunc)partial_repr, /* tp_repr */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000264 0, /* tp_as_number */
265 0, /* tp_as_sequence */
266 0, /* tp_as_mapping */
267 0, /* tp_hash */
268 (ternaryfunc)partial_call, /* tp_call */
269 0, /* tp_str */
270 PyObject_GenericGetAttr, /* tp_getattro */
271 PyObject_GenericSetAttr, /* tp_setattro */
272 0, /* tp_as_buffer */
273 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
274 Py_TPFLAGS_BASETYPE, /* tp_flags */
275 partial_doc, /* tp_doc */
276 (traverseproc)partial_traverse, /* tp_traverse */
277 0, /* tp_clear */
278 0, /* tp_richcompare */
279 offsetof(partialobject, weakreflist), /* tp_weaklistoffset */
280 0, /* tp_iter */
281 0, /* tp_iternext */
282 partial_methods, /* tp_methods */
283 partial_memberlist, /* tp_members */
284 partial_getsetlist, /* tp_getset */
285 0, /* tp_base */
286 0, /* tp_dict */
287 0, /* tp_descr_get */
288 0, /* tp_descr_set */
289 offsetof(partialobject, dict), /* tp_dictoffset */
290 0, /* tp_init */
291 0, /* tp_alloc */
292 partial_new, /* tp_new */
293 PyObject_GC_Del, /* tp_free */
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000294};
295
296
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700297/* cmp_to_key ***************************************************************/
298
299typedef struct {
Victor Stinner446c8d52011-04-05 12:21:35 +0200300 PyObject_HEAD
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700301 PyObject *cmp;
302 PyObject *object;
303} keyobject;
304
305static void
306keyobject_dealloc(keyobject *ko)
307{
308 Py_DECREF(ko->cmp);
309 Py_XDECREF(ko->object);
310 PyObject_FREE(ko);
311}
312
313static int
314keyobject_traverse(keyobject *ko, visitproc visit, void *arg)
315{
316 Py_VISIT(ko->cmp);
317 if (ko->object)
318 Py_VISIT(ko->object);
319 return 0;
320}
321
Benjamin Peterson3bd97292011-04-05 17:25:14 -0500322static int
323keyobject_clear(keyobject *ko)
324{
325 Py_CLEAR(ko->cmp);
326 if (ko->object)
327 Py_CLEAR(ko->object);
328 return 0;
329}
330
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700331static PyMemberDef keyobject_members[] = {
332 {"obj", T_OBJECT,
333 offsetof(keyobject, object), 0,
334 PyDoc_STR("Value wrapped by a key function.")},
335 {NULL}
336};
337
338static PyObject *
Raymond Hettingera5632862011-04-09 12:57:00 -0700339keyobject_call(keyobject *ko, PyObject *args, PyObject *kwds);
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700340
341static PyObject *
342keyobject_richcompare(PyObject *ko, PyObject *other, int op);
343
344static PyTypeObject keyobject_type = {
345 PyVarObject_HEAD_INIT(&PyType_Type, 0)
346 "functools.KeyWrapper", /* tp_name */
347 sizeof(keyobject), /* tp_basicsize */
348 0, /* tp_itemsize */
349 /* methods */
350 (destructor)keyobject_dealloc, /* tp_dealloc */
351 0, /* tp_print */
352 0, /* tp_getattr */
353 0, /* tp_setattr */
354 0, /* tp_reserved */
355 0, /* tp_repr */
356 0, /* tp_as_number */
357 0, /* tp_as_sequence */
358 0, /* tp_as_mapping */
359 0, /* tp_hash */
360 (ternaryfunc)keyobject_call, /* tp_call */
361 0, /* tp_str */
362 PyObject_GenericGetAttr, /* tp_getattro */
363 0, /* tp_setattro */
364 0, /* tp_as_buffer */
365 Py_TPFLAGS_DEFAULT, /* tp_flags */
366 0, /* tp_doc */
367 (traverseproc)keyobject_traverse, /* tp_traverse */
Benjamin Peterson3bd97292011-04-05 17:25:14 -0500368 (inquiry)keyobject_clear, /* tp_clear */
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700369 keyobject_richcompare, /* tp_richcompare */
370 0, /* tp_weaklistoffset */
371 0, /* tp_iter */
372 0, /* tp_iternext */
373 0, /* tp_methods */
374 keyobject_members, /* tp_members */
375 0, /* tp_getset */
376};
377
378static PyObject *
379keyobject_call(keyobject *ko, PyObject *args, PyObject *kwds)
380{
381 PyObject *object;
382 keyobject *result;
383 static char *kwargs[] = {"obj", NULL};
384
385 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:K", kwargs, &object))
386 return NULL;
387 result = PyObject_New(keyobject, &keyobject_type);
388 if (!result)
389 return NULL;
390 Py_INCREF(ko->cmp);
391 result->cmp = ko->cmp;
392 Py_INCREF(object);
393 result->object = object;
394 return (PyObject *)result;
395}
396
397static PyObject *
398keyobject_richcompare(PyObject *ko, PyObject *other, int op)
399{
400 PyObject *res;
401 PyObject *args;
402 PyObject *x;
403 PyObject *y;
404 PyObject *compare;
405 PyObject *answer;
406 static PyObject *zero;
407
408 if (zero == NULL) {
409 zero = PyLong_FromLong(0);
410 if (!zero)
411 return NULL;
412 }
413
414 if (Py_TYPE(other) != &keyobject_type){
415 PyErr_Format(PyExc_TypeError, "other argument must be K instance");
416 return NULL;
417 }
418 compare = ((keyobject *) ko)->cmp;
419 assert(compare != NULL);
420 x = ((keyobject *) ko)->object;
421 y = ((keyobject *) other)->object;
422 if (!x || !y){
423 PyErr_Format(PyExc_AttributeError, "object");
424 return NULL;
425 }
426
427 /* Call the user's comparison function and translate the 3-way
428 * result into true or false (or error).
429 */
430 args = PyTuple_New(2);
431 if (args == NULL)
432 return NULL;
433 Py_INCREF(x);
434 Py_INCREF(y);
435 PyTuple_SET_ITEM(args, 0, x);
436 PyTuple_SET_ITEM(args, 1, y);
437 res = PyObject_Call(compare, args, NULL);
438 Py_DECREF(args);
439 if (res == NULL)
440 return NULL;
441 answer = PyObject_RichCompare(res, zero, op);
442 Py_DECREF(res);
443 return answer;
444}
445
446static PyObject *
Victor Stinner446c8d52011-04-05 12:21:35 +0200447functools_cmp_to_key(PyObject *self, PyObject *args, PyObject *kwds)
448{
449 PyObject *cmp;
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700450 static char *kwargs[] = {"mycmp", NULL};
Victor Stinner446c8d52011-04-05 12:21:35 +0200451 keyobject *object;
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700452
453 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:cmp_to_key", kwargs, &cmp))
454 return NULL;
Victor Stinner446c8d52011-04-05 12:21:35 +0200455 object = PyObject_New(keyobject, &keyobject_type);
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700456 if (!object)
457 return NULL;
458 Py_INCREF(cmp);
459 object->cmp = cmp;
460 object->object = NULL;
461 return (PyObject *)object;
462}
463
464PyDoc_STRVAR(functools_cmp_to_key_doc,
465"Convert a cmp= function into a key= function.");
466
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000467/* reduce (used to be a builtin) ********************************************/
468
469static PyObject *
470functools_reduce(PyObject *self, PyObject *args)
471{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000472 PyObject *seq, *func, *result = NULL, *it;
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000473
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000474 if (!PyArg_UnpackTuple(args, "reduce", 2, 3, &func, &seq, &result))
475 return NULL;
476 if (result != NULL)
477 Py_INCREF(result);
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000478
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000479 it = PyObject_GetIter(seq);
480 if (it == NULL) {
Alexander Belopolskye29e6bf2010-08-16 18:55:46 +0000481 if (PyErr_ExceptionMatches(PyExc_TypeError))
482 PyErr_SetString(PyExc_TypeError,
483 "reduce() arg 2 must support iteration");
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000484 Py_XDECREF(result);
485 return NULL;
486 }
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000487
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000488 if ((args = PyTuple_New(2)) == NULL)
489 goto Fail;
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000490
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000491 for (;;) {
492 PyObject *op2;
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000493
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000494 if (args->ob_refcnt > 1) {
495 Py_DECREF(args);
496 if ((args = PyTuple_New(2)) == NULL)
497 goto Fail;
498 }
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000499
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000500 op2 = PyIter_Next(it);
501 if (op2 == NULL) {
502 if (PyErr_Occurred())
503 goto Fail;
504 break;
505 }
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000506
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000507 if (result == NULL)
508 result = op2;
509 else {
510 PyTuple_SetItem(args, 0, result);
511 PyTuple_SetItem(args, 1, op2);
512 if ((result = PyEval_CallObject(func, args)) == NULL)
513 goto Fail;
514 }
515 }
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000516
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000517 Py_DECREF(args);
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000518
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000519 if (result == NULL)
520 PyErr_SetString(PyExc_TypeError,
521 "reduce() of empty sequence with no initial value");
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000522
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000523 Py_DECREF(it);
524 return result;
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000525
526Fail:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000527 Py_XDECREF(args);
528 Py_XDECREF(result);
529 Py_DECREF(it);
530 return NULL;
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000531}
532
533PyDoc_STRVAR(functools_reduce_doc,
534"reduce(function, sequence[, initial]) -> value\n\
535\n\
536Apply a function of two arguments cumulatively to the items of a sequence,\n\
537from left to right, so as to reduce the sequence to a single value.\n\
538For example, reduce(lambda x, y: x+y, [1, 2, 3, 4, 5]) calculates\n\
539((((1+2)+3)+4)+5). If initial is present, it is placed before the items\n\
540of the sequence in the calculation, and serves as a default when the\n\
541sequence is empty.");
542
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000543/* module level code ********************************************************/
544
545PyDoc_STRVAR(module_doc,
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000546"Tools that operate on functions.");
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000547
548static PyMethodDef module_methods[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000549 {"reduce", functools_reduce, METH_VARARGS, functools_reduce_doc},
Victor Stinner446c8d52011-04-05 12:21:35 +0200550 {"cmp_to_key", (PyCFunction)functools_cmp_to_key,
551 METH_VARARGS | METH_KEYWORDS, functools_cmp_to_key_doc},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000552 {NULL, NULL} /* sentinel */
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000553};
554
Martin v. Löwis1a214512008-06-11 05:26:20 +0000555
556static struct PyModuleDef _functoolsmodule = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000557 PyModuleDef_HEAD_INIT,
558 "_functools",
559 module_doc,
560 -1,
561 module_methods,
562 NULL,
563 NULL,
564 NULL,
565 NULL
Martin v. Löwis1a214512008-06-11 05:26:20 +0000566};
567
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000568PyMODINIT_FUNC
Martin v. Löwis1a214512008-06-11 05:26:20 +0000569PyInit__functools(void)
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000570{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000571 int i;
572 PyObject *m;
573 char *name;
574 PyTypeObject *typelist[] = {
575 &partial_type,
576 NULL
577 };
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000578
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000579 m = PyModule_Create(&_functoolsmodule);
580 if (m == NULL)
581 return NULL;
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000582
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000583 for (i=0 ; typelist[i] != NULL ; i++) {
584 if (PyType_Ready(typelist[i]) < 0) {
585 Py_DECREF(m);
586 return NULL;
587 }
588 name = strchr(typelist[i]->tp_name, '.');
589 assert (name != NULL);
590 Py_INCREF(typelist[i]);
591 PyModule_AddObject(m, name+1, (PyObject *)typelist[i]);
592 }
593 return m;
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000594}