blob: dc64cfee2df9f88fb5f48749f415e6f76bfad40e [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
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300593/* lru_cache object **********************************************************/
594
595/* this object is used delimit args and keywords in the cache keys */
596static PyObject *kwd_mark = NULL;
597
598struct lru_list_elem;
599struct lru_cache_object;
600
601typedef struct lru_list_elem {
602 PyObject_HEAD
603 struct lru_list_elem *prev, *next; /* borrowed links */
604 PyObject *key, *result;
605} lru_list_elem;
606
607static void
608lru_list_elem_dealloc(lru_list_elem *link)
609{
610 _PyObject_GC_UNTRACK(link);
611 Py_XDECREF(link->key);
612 Py_XDECREF(link->result);
613 PyObject_GC_Del(link);
614}
615
616static int
617lru_list_elem_traverse(lru_list_elem *link, visitproc visit, void *arg)
618{
619 Py_VISIT(link->key);
620 Py_VISIT(link->result);
621 return 0;
622}
623
624static int
625lru_list_elem_clear(lru_list_elem *link)
626{
627 Py_CLEAR(link->key);
628 Py_CLEAR(link->result);
629 return 0;
630}
631
632static PyTypeObject lru_list_elem_type = {
633 PyVarObject_HEAD_INIT(&PyType_Type, 0)
634 "functools._lru_list_elem", /* tp_name */
635 sizeof(lru_list_elem), /* tp_basicsize */
636 0, /* tp_itemsize */
637 /* methods */
638 (destructor)lru_list_elem_dealloc, /* tp_dealloc */
639 0, /* tp_print */
640 0, /* tp_getattr */
641 0, /* tp_setattr */
642 0, /* tp_reserved */
643 0, /* tp_repr */
644 0, /* tp_as_number */
645 0, /* tp_as_sequence */
646 0, /* tp_as_mapping */
647 0, /* tp_hash */
648 0, /* tp_call */
649 0, /* tp_str */
650 0, /* tp_getattro */
651 0, /* tp_setattro */
652 0, /* tp_as_buffer */
653 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
654 0, /* tp_doc */
655 (traverseproc)lru_list_elem_traverse, /* tp_traverse */
656 (inquiry)lru_list_elem_clear, /* tp_clear */
657};
658
659
660typedef PyObject *(*lru_cache_ternaryfunc)(struct lru_cache_object *, PyObject *, PyObject *);
661
662typedef struct lru_cache_object {
663 lru_list_elem root; /* includes PyObject_HEAD */
664 Py_ssize_t maxsize;
665 PyObject *maxsize_O;
666 PyObject *func;
667 lru_cache_ternaryfunc wrapper;
668 PyObject *cache;
669 PyObject *cache_info_type;
670 Py_ssize_t misses, hits;
671 int typed;
672 PyObject *dict;
673 int full;
674} lru_cache_object;
675
676static PyTypeObject lru_cache_type;
677
678static PyObject *
679lru_cache_make_key(PyObject *args, PyObject *kwds, int typed)
680{
681 PyObject *key, *sorted_items;
682 Py_ssize_t key_size, pos, key_pos;
683
684 /* short path, key will match args anyway, which is a tuple */
685 if (!typed && !kwds) {
686 Py_INCREF(args);
687 return args;
688 }
689
690 if (kwds && PyDict_Size(kwds) > 0) {
691 sorted_items = PyDict_Items(kwds);
692 if (!sorted_items)
693 return NULL;
694 if (PyList_Sort(sorted_items) < 0) {
695 Py_DECREF(sorted_items);
696 return NULL;
697 }
698 } else
699 sorted_items = NULL;
700
701 key_size = PyTuple_GET_SIZE(args);
702 if (sorted_items)
703 key_size += PyList_GET_SIZE(sorted_items);
704 if (typed)
705 key_size *= 2;
706 if (sorted_items)
707 key_size++;
708
709 key = PyTuple_New(key_size);
710 if (key == NULL)
711 goto done;
712
713 key_pos = 0;
714 for (pos = 0; pos < PyTuple_GET_SIZE(args); ++pos) {
715 PyObject *item = PyTuple_GET_ITEM(args, pos);
716 Py_INCREF(item);
717 PyTuple_SET_ITEM(key, key_pos++, item);
718 }
719 if (sorted_items) {
720 Py_INCREF(kwd_mark);
721 PyTuple_SET_ITEM(key, key_pos++, kwd_mark);
722 for (pos = 0; pos < PyList_GET_SIZE(sorted_items); ++pos) {
723 PyObject *item = PyList_GET_ITEM(sorted_items, pos);
724 Py_INCREF(item);
725 PyTuple_SET_ITEM(key, key_pos++, item);
726 }
727 }
728 if (typed) {
729 for (pos = 0; pos < PyTuple_GET_SIZE(args); ++pos) {
730 PyObject *item = (PyObject *)Py_TYPE(PyTuple_GET_ITEM(args, pos));
731 Py_INCREF(item);
732 PyTuple_SET_ITEM(key, key_pos++, item);
733 }
734 if (sorted_items) {
735 for (pos = 0; pos < PyList_GET_SIZE(sorted_items); ++pos) {
736 PyObject *tp_items = PyList_GET_ITEM(sorted_items, pos);
737 PyObject *item = (PyObject *)Py_TYPE(PyTuple_GET_ITEM(tp_items, 1));
738 Py_INCREF(item);
739 PyTuple_SET_ITEM(key, key_pos++, item);
740 }
741 }
742 }
743 assert(key_pos == key_size);
744
745done:
746 if (sorted_items)
747 Py_DECREF(sorted_items);
748 return key;
749}
750
751static PyObject *
752uncached_lru_cache_wrapper(lru_cache_object *self, PyObject *args, PyObject *kwds)
753{
754 PyObject *result = PyObject_Call(self->func, args, kwds);
755 if (!result)
756 return NULL;
757 self->misses++;
758 return result;
759}
760
761static PyObject *
762infinite_lru_cache_wrapper(lru_cache_object *self, PyObject *args, PyObject *kwds)
763{
764 PyObject *result;
765 PyObject *key = lru_cache_make_key(args, kwds, self->typed);
766 if (!key)
767 return NULL;
768 result = PyDict_GetItemWithError(self->cache, key);
769 if (result) {
770 Py_INCREF(result);
771 self->hits++;
772 Py_DECREF(key);
773 return result;
774 }
775 if (PyErr_Occurred()) {
776 Py_DECREF(key);
777 return NULL;
778 }
779 result = PyObject_Call(self->func, args, kwds);
780 if (!result) {
781 Py_DECREF(key);
782 return NULL;
783 }
784 if (PyDict_SetItem(self->cache, key, result) < 0) {
785 Py_DECREF(result);
786 Py_DECREF(key);
787 return NULL;
788 }
789 Py_DECREF(key);
790 self->misses++;
791 return result;
792}
793
794static void
795lru_cache_extricate_link(lru_list_elem *link)
796{
797 link->prev->next = link->next;
798 link->next->prev = link->prev;
799}
800
801static void
802lru_cache_append_link(lru_cache_object *self, lru_list_elem *link)
803{
804 lru_list_elem *root = &self->root;
805 lru_list_elem *last = root->prev;
806 last->next = root->prev = link;
807 link->prev = last;
808 link->next = root;
809}
810
811static PyObject *
812bounded_lru_cache_wrapper(lru_cache_object *self, PyObject *args, PyObject *kwds)
813{
814 lru_list_elem *link;
815 PyObject *key, *result;
816
817 key = lru_cache_make_key(args, kwds, self->typed);
818 if (!key)
819 return NULL;
820 link = (lru_list_elem *)PyDict_GetItemWithError(self->cache, key);
821 if (link) {
822 lru_cache_extricate_link(link);
823 lru_cache_append_link(self, link);
824 self->hits++;
825 result = link->result;
826 Py_INCREF(result);
827 Py_DECREF(key);
828 return result;
829 }
830 if (PyErr_Occurred()) {
831 Py_DECREF(key);
832 return NULL;
833 }
834 result = PyObject_Call(self->func, args, kwds);
835 if (!result) {
836 Py_DECREF(key);
837 return NULL;
838 }
839 if (self->full && self->root.next != &self->root) {
840 /* Use the oldest item to store the new key and result. */
841 PyObject *oldkey, *oldresult;
842 /* Extricate the oldest item. */
843 link = self->root.next;
844 lru_cache_extricate_link(link);
845 /* Remove it from the cache.
846 The cache dict holds one reference to the link,
847 and the linked list holds yet one reference to it. */
848 if (PyDict_DelItem(self->cache, link->key) < 0) {
849 lru_cache_append_link(self, link);
850 Py_DECREF(key);
851 Py_DECREF(result);
852 return NULL;
853 }
854 /* Keep a reference to the old key and old result to
855 prevent their ref counts from going to zero during the
856 update. That will prevent potentially arbitrary object
857 clean-up code (i.e. __del__) from running while we're
858 still adjusting the links. */
859 oldkey = link->key;
860 oldresult = link->result;
861
862 link->key = key;
863 link->result = result;
864 if (PyDict_SetItem(self->cache, key, (PyObject *)link) < 0) {
865 Py_DECREF(link);
866 Py_DECREF(oldkey);
867 Py_DECREF(oldresult);
868 return NULL;
869 }
870 lru_cache_append_link(self, link);
871 Py_INCREF(result); /* for return */
872 Py_DECREF(oldkey);
873 Py_DECREF(oldresult);
874 } else {
875 /* Put result in a new link at the front of the queue. */
876 link = (lru_list_elem *)PyObject_GC_New(lru_list_elem,
877 &lru_list_elem_type);
878 if (link == NULL) {
879 Py_DECREF(key);
880 Py_DECREF(result);
881 return NULL;
882 }
883
884 link->key = key;
885 link->result = result;
886 _PyObject_GC_TRACK(link);
887 if (PyDict_SetItem(self->cache, key, (PyObject *)link) < 0) {
888 Py_DECREF(link);
889 return NULL;
890 }
891 lru_cache_append_link(self, link);
892 Py_INCREF(result); /* for return */
893 self->full = (PyDict_Size(self->cache) >= self->maxsize);
894 }
895 self->misses++;
896 return result;
897}
898
899static PyObject *
900lru_cache_new(PyTypeObject *type, PyObject *args, PyObject *kw)
901{
Serhiy Storchaka374164c2015-07-25 12:10:21 +0300902 PyObject *func, *maxsize_O, *cache_info_type, *cachedict;
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300903 int typed;
904 lru_cache_object *obj;
905 Py_ssize_t maxsize;
906 PyObject *(*wrapper)(lru_cache_object *, PyObject *, PyObject *);
907 static char *keywords[] = {"user_function", "maxsize", "typed",
908 "cache_info_type", NULL};
909
910 if (!PyArg_ParseTupleAndKeywords(args, kw, "OOpO:lru_cache", keywords,
911 &func, &maxsize_O, &typed,
912 &cache_info_type)) {
913 return NULL;
914 }
915
916 if (!PyCallable_Check(func)) {
917 PyErr_SetString(PyExc_TypeError,
918 "the first argument must be callable");
919 return NULL;
920 }
921
922 /* select the caching function, and make/inc maxsize_O */
923 if (maxsize_O == Py_None) {
924 wrapper = infinite_lru_cache_wrapper;
925 /* use this only to initialize lru_cache_object attribute maxsize */
926 maxsize = -1;
927 } else if (PyIndex_Check(maxsize_O)) {
928 maxsize = PyNumber_AsSsize_t(maxsize_O, PyExc_OverflowError);
929 if (maxsize == -1 && PyErr_Occurred())
930 return NULL;
931 if (maxsize == 0)
932 wrapper = uncached_lru_cache_wrapper;
933 else
934 wrapper = bounded_lru_cache_wrapper;
935 } else {
936 PyErr_SetString(PyExc_TypeError, "maxsize should be integer or None");
937 return NULL;
938 }
939
Serhiy Storchaka374164c2015-07-25 12:10:21 +0300940 if (!(cachedict = PyDict_New()))
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300941 return NULL;
942
Serhiy Storchaka374164c2015-07-25 12:10:21 +0300943 obj = (lru_cache_object *)type->tp_alloc(type, 0);
944 if (obj == NULL) {
945 Py_DECREF(cachedict);
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300946 return NULL;
947 }
948
Serhiy Storchaka374164c2015-07-25 12:10:21 +0300949 obj->cache = cachedict;
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300950 obj->root.prev = &obj->root;
951 obj->root.next = &obj->root;
952 obj->maxsize = maxsize;
953 Py_INCREF(maxsize_O);
954 obj->maxsize_O = maxsize_O;
955 Py_INCREF(func);
956 obj->func = func;
957 obj->wrapper = wrapper;
958 obj->misses = obj->hits = 0;
959 obj->typed = typed;
960 Py_INCREF(cache_info_type);
961 obj->cache_info_type = cache_info_type;
962
963 return (PyObject *)obj;
964}
965
966static lru_list_elem *
967lru_cache_unlink_list(lru_cache_object *self)
968{
969 lru_list_elem *root = &self->root;
970 lru_list_elem *link = root->next;
971 if (link == root)
972 return NULL;
973 root->prev->next = NULL;
974 root->next = root->prev = root;
975 return link;
976}
977
978static void
979lru_cache_clear_list(lru_list_elem *link)
980{
981 while (link != NULL) {
982 lru_list_elem *next = link->next;
983 Py_DECREF(link);
984 link = next;
985 }
986}
987
988static void
989lru_cache_dealloc(lru_cache_object *obj)
990{
991 lru_list_elem *list = lru_cache_unlink_list(obj);
992 Py_XDECREF(obj->maxsize_O);
993 Py_XDECREF(obj->func);
994 Py_XDECREF(obj->cache);
995 Py_XDECREF(obj->dict);
996 Py_XDECREF(obj->cache_info_type);
997 lru_cache_clear_list(list);
998 Py_TYPE(obj)->tp_free(obj);
999}
1000
1001static PyObject *
1002lru_cache_call(lru_cache_object *self, PyObject *args, PyObject *kwds)
1003{
1004 return self->wrapper(self, args, kwds);
1005}
1006
1007static PyObject *
Serhiy Storchakae7070f02015-06-08 11:19:24 +03001008lru_cache_descr_get(PyObject *self, PyObject *obj, PyObject *type)
1009{
1010 if (obj == Py_None || obj == NULL) {
1011 Py_INCREF(self);
1012 return self;
1013 }
1014 return PyMethod_New(self, obj);
1015}
1016
1017static PyObject *
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001018lru_cache_cache_info(lru_cache_object *self, PyObject *unused)
1019{
1020 return PyObject_CallFunction(self->cache_info_type, "nnOn",
1021 self->hits, self->misses, self->maxsize_O,
1022 PyDict_Size(self->cache));
1023}
1024
1025static PyObject *
1026lru_cache_cache_clear(lru_cache_object *self, PyObject *unused)
1027{
1028 lru_list_elem *list = lru_cache_unlink_list(self);
1029 self->hits = self->misses = 0;
1030 self->full = 0;
1031 PyDict_Clear(self->cache);
1032 lru_cache_clear_list(list);
1033 Py_RETURN_NONE;
1034}
1035
1036static int
1037lru_cache_tp_traverse(lru_cache_object *self, visitproc visit, void *arg)
1038{
1039 lru_list_elem *link = self->root.next;
1040 while (link != &self->root) {
1041 lru_list_elem *next = link->next;
1042 Py_VISIT(link);
1043 link = next;
1044 }
1045 Py_VISIT(self->maxsize_O);
1046 Py_VISIT(self->func);
1047 Py_VISIT(self->cache);
1048 Py_VISIT(self->cache_info_type);
1049 Py_VISIT(self->dict);
1050 return 0;
1051}
1052
1053static int
1054lru_cache_tp_clear(lru_cache_object *self)
1055{
1056 lru_list_elem *list = lru_cache_unlink_list(self);
1057 Py_CLEAR(self->maxsize_O);
1058 Py_CLEAR(self->func);
1059 Py_CLEAR(self->cache);
1060 Py_CLEAR(self->cache_info_type);
1061 Py_CLEAR(self->dict);
1062 lru_cache_clear_list(list);
1063 return 0;
1064}
1065
1066
1067PyDoc_STRVAR(lru_cache_doc,
1068"Create a cached callable that wraps another function.\n\
1069\n\
1070user_function: the function being cached\n\
1071\n\
1072maxsize: 0 for no caching\n\
1073 None for unlimited cache size\n\
1074 n for a bounded cache\n\
1075\n\
1076typed: False cache f(3) and f(3.0) as identical calls\n\
1077 True cache f(3) and f(3.0) as distinct calls\n\
1078\n\
1079cache_info_type: namedtuple class with the fields:\n\
1080 hits misses currsize maxsize\n"
1081);
1082
1083static PyMethodDef lru_cache_methods[] = {
1084 {"cache_info", (PyCFunction)lru_cache_cache_info, METH_NOARGS},
1085 {"cache_clear", (PyCFunction)lru_cache_cache_clear, METH_NOARGS},
1086 {NULL}
1087};
1088
1089static PyGetSetDef lru_cache_getsetlist[] = {
1090 {"__dict__", PyObject_GenericGetDict, PyObject_GenericSetDict},
1091 {NULL}
1092};
1093
1094static PyTypeObject lru_cache_type = {
1095 PyVarObject_HEAD_INIT(NULL, 0)
1096 "functools._lru_cache_wrapper", /* tp_name */
1097 sizeof(lru_cache_object), /* tp_basicsize */
1098 0, /* tp_itemsize */
1099 /* methods */
1100 (destructor)lru_cache_dealloc, /* tp_dealloc */
1101 0, /* tp_print */
1102 0, /* tp_getattr */
1103 0, /* tp_setattr */
1104 0, /* tp_reserved */
1105 0, /* tp_repr */
1106 0, /* tp_as_number */
1107 0, /* tp_as_sequence */
1108 0, /* tp_as_mapping */
1109 0, /* tp_hash */
1110 (ternaryfunc)lru_cache_call, /* tp_call */
1111 0, /* tp_str */
1112 0, /* tp_getattro */
1113 0, /* tp_setattro */
1114 0, /* tp_as_buffer */
1115 Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_HAVE_GC,
1116 /* tp_flags */
1117 lru_cache_doc, /* tp_doc */
1118 (traverseproc)lru_cache_tp_traverse,/* tp_traverse */
1119 (inquiry)lru_cache_tp_clear, /* tp_clear */
1120 0, /* tp_richcompare */
1121 0, /* tp_weaklistoffset */
1122 0, /* tp_iter */
1123 0, /* tp_iternext */
1124 lru_cache_methods, /* tp_methods */
1125 0, /* tp_members */
1126 lru_cache_getsetlist, /* tp_getset */
1127 0, /* tp_base */
1128 0, /* tp_dict */
Serhiy Storchakae7070f02015-06-08 11:19:24 +03001129 lru_cache_descr_get, /* tp_descr_get */
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001130 0, /* tp_descr_set */
1131 offsetof(lru_cache_object, dict), /* tp_dictoffset */
1132 0, /* tp_init */
1133 0, /* tp_alloc */
1134 lru_cache_new, /* tp_new */
1135};
1136
Raymond Hettinger9c323f82005-02-28 19:39:44 +00001137/* module level code ********************************************************/
1138
1139PyDoc_STRVAR(module_doc,
Thomas Wouters4d70c3d2006-06-08 14:42:34 +00001140"Tools that operate on functions.");
Raymond Hettinger9c323f82005-02-28 19:39:44 +00001141
1142static PyMethodDef module_methods[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001143 {"reduce", functools_reduce, METH_VARARGS, functools_reduce_doc},
Victor Stinner446c8d52011-04-05 12:21:35 +02001144 {"cmp_to_key", (PyCFunction)functools_cmp_to_key,
1145 METH_VARARGS | METH_KEYWORDS, functools_cmp_to_key_doc},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001146 {NULL, NULL} /* sentinel */
Raymond Hettinger9c323f82005-02-28 19:39:44 +00001147};
1148
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001149static void
1150module_free(void *m)
1151{
1152 Py_CLEAR(kwd_mark);
1153}
Martin v. Löwis1a214512008-06-11 05:26:20 +00001154
1155static struct PyModuleDef _functoolsmodule = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001156 PyModuleDef_HEAD_INIT,
1157 "_functools",
1158 module_doc,
1159 -1,
1160 module_methods,
1161 NULL,
1162 NULL,
1163 NULL,
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001164 module_free,
Martin v. Löwis1a214512008-06-11 05:26:20 +00001165};
1166
Raymond Hettinger9c323f82005-02-28 19:39:44 +00001167PyMODINIT_FUNC
Martin v. Löwis1a214512008-06-11 05:26:20 +00001168PyInit__functools(void)
Raymond Hettinger9c323f82005-02-28 19:39:44 +00001169{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001170 int i;
1171 PyObject *m;
1172 char *name;
1173 PyTypeObject *typelist[] = {
1174 &partial_type,
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001175 &lru_cache_type,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001176 NULL
1177 };
Raymond Hettinger9c323f82005-02-28 19:39:44 +00001178
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001179 m = PyModule_Create(&_functoolsmodule);
1180 if (m == NULL)
1181 return NULL;
Raymond Hettinger9c323f82005-02-28 19:39:44 +00001182
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001183 kwd_mark = PyObject_CallObject((PyObject *)&PyBaseObject_Type, NULL);
1184 if (!kwd_mark) {
1185 Py_DECREF(m);
1186 return NULL;
1187 }
1188
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001189 for (i=0 ; typelist[i] != NULL ; i++) {
1190 if (PyType_Ready(typelist[i]) < 0) {
1191 Py_DECREF(m);
1192 return NULL;
1193 }
1194 name = strchr(typelist[i]->tp_name, '.');
1195 assert (name != NULL);
1196 Py_INCREF(typelist[i]);
1197 PyModule_AddObject(m, name+1, (PyObject *)typelist[i]);
1198 }
1199 return m;
Raymond Hettinger9c323f82005-02-28 19:39:44 +00001200}