blob: d785c4932b6f4bb747d637c0881f48be44b6ccce [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
Serhiy Storchaka38741282016-02-02 18:45:17 +020037 pargs = pkw = NULL;
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;
Serhiy Storchaka38741282016-02-02 18:45:17 +020045 assert(PyTuple_Check(pargs));
46 assert(PyDict_Check(pkw));
Alexander Belopolskye49af342015-03-01 15:08:17 -050047 }
48 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000049 if (!PyCallable_Check(func)) {
50 PyErr_SetString(PyExc_TypeError,
51 "the first argument must be callable");
52 return NULL;
53 }
Raymond Hettinger9c323f82005-02-28 19:39:44 +000054
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000055 /* create partialobject structure */
56 pto = (partialobject *)type->tp_alloc(type, 0);
57 if (pto == NULL)
58 return NULL;
Raymond Hettinger9c323f82005-02-28 19:39:44 +000059
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000060 pto->fn = func;
61 Py_INCREF(func);
Alexander Belopolskye49af342015-03-01 15:08:17 -050062
63 nargs = PyTuple_GetSlice(args, 1, PY_SSIZE_T_MAX);
64 if (nargs == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000065 Py_DECREF(pto);
66 return NULL;
67 }
Serhiy Storchaka38741282016-02-02 18:45:17 +020068 if (pargs == NULL || PyTuple_GET_SIZE(pargs) == 0) {
Alexander Belopolskye49af342015-03-01 15:08:17 -050069 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) {
Serhiy Storchaka38741282016-02-02 18:45:17 +020079 Py_DECREF(nargs);
Alexander Belopolskye49af342015-03-01 15:08:17 -050080 Py_DECREF(pto);
81 return NULL;
82 }
Serhiy Storchaka38741282016-02-02 18:45:17 +020083 assert(PyTuple_Check(pto->args));
Alexander Belopolskye49af342015-03-01 15:08:17 -050084 }
85 Py_DECREF(nargs);
86
Serhiy Storchaka38741282016-02-02 18:45:17 +020087 if (pkw == NULL || PyDict_Size(pkw) == 0) {
88 if (kw == NULL) {
89 pto->kw = PyDict_New();
Alexander Belopolskye49af342015-03-01 15:08:17 -050090 }
91 else {
Serhiy Storchaka38741282016-02-02 18:45:17 +020092 Py_INCREF(kw);
93 pto->kw = kw;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000094 }
Alexander Belopolskye49af342015-03-01 15:08:17 -050095 }
96 else {
Serhiy Storchaka38741282016-02-02 18:45:17 +020097 pto->kw = PyDict_Copy(pkw);
98 if (kw != NULL && pto->kw != NULL) {
99 if (PyDict_Merge(pto->kw, kw, 1) != 0) {
Benjamin Petersondae2ef12015-05-09 00:29:08 -0400100 Py_DECREF(pto);
101 return NULL;
102 }
103 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000104 }
Serhiy Storchaka38741282016-02-02 18:45:17 +0200105 if (pto->kw == NULL) {
106 Py_DECREF(pto);
107 return NULL;
108 }
Raymond Hettingerc8b6d1b2005-03-08 06:14:50 +0000109
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000110 return (PyObject *)pto;
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000111}
112
113static void
114partial_dealloc(partialobject *pto)
115{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000116 PyObject_GC_UnTrack(pto);
117 if (pto->weakreflist != NULL)
118 PyObject_ClearWeakRefs((PyObject *) pto);
119 Py_XDECREF(pto->fn);
120 Py_XDECREF(pto->args);
121 Py_XDECREF(pto->kw);
122 Py_XDECREF(pto->dict);
123 Py_TYPE(pto)->tp_free(pto);
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000124}
125
126static PyObject *
127partial_call(partialobject *pto, PyObject *args, PyObject *kw)
128{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000129 PyObject *ret;
Serhiy Storchaka38741282016-02-02 18:45:17 +0200130 PyObject *argappl, *kwappl;
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000131
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000132 assert (PyCallable_Check(pto->fn));
133 assert (PyTuple_Check(pto->args));
Serhiy Storchaka38741282016-02-02 18:45:17 +0200134 assert (PyDict_Check(pto->kw));
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000135
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000136 if (PyTuple_GET_SIZE(pto->args) == 0) {
137 argappl = args;
138 Py_INCREF(args);
139 } else if (PyTuple_GET_SIZE(args) == 0) {
140 argappl = pto->args;
141 Py_INCREF(pto->args);
142 } else {
143 argappl = PySequence_Concat(pto->args, args);
144 if (argappl == NULL)
145 return NULL;
Serhiy Storchaka38741282016-02-02 18:45:17 +0200146 assert(PyTuple_Check(argappl));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000147 }
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000148
Serhiy Storchaka38741282016-02-02 18:45:17 +0200149 if (PyDict_Size(pto->kw) == 0) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000150 kwappl = kw;
Serhiy Storchaka38741282016-02-02 18:45:17 +0200151 Py_XINCREF(kwappl);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000152 } else {
153 kwappl = PyDict_Copy(pto->kw);
154 if (kwappl == NULL) {
155 Py_DECREF(argappl);
156 return NULL;
157 }
158 if (kw != NULL) {
159 if (PyDict_Merge(kwappl, kw, 1) != 0) {
160 Py_DECREF(argappl);
161 Py_DECREF(kwappl);
162 return NULL;
163 }
164 }
165 }
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000166
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000167 ret = PyObject_Call(pto->fn, argappl, kwappl);
168 Py_DECREF(argappl);
169 Py_XDECREF(kwappl);
170 return ret;
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000171}
172
173static int
174partial_traverse(partialobject *pto, visitproc visit, void *arg)
175{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000176 Py_VISIT(pto->fn);
177 Py_VISIT(pto->args);
178 Py_VISIT(pto->kw);
179 Py_VISIT(pto->dict);
180 return 0;
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000181}
182
183PyDoc_STRVAR(partial_doc,
184"partial(func, *args, **keywords) - new function with partial application\n\
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000185 of the given arguments and keywords.\n");
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000186
187#define OFF(x) offsetof(partialobject, x)
188static PyMemberDef partial_memberlist[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000189 {"func", T_OBJECT, OFF(fn), READONLY,
190 "function object to use in future partial calls"},
191 {"args", T_OBJECT, OFF(args), READONLY,
192 "tuple of arguments to future partial calls"},
193 {"keywords", T_OBJECT, OFF(kw), READONLY,
194 "dictionary of keyword arguments to future partial calls"},
195 {NULL} /* Sentinel */
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000196};
197
Georg Brandlc2fb6c72006-02-21 17:49:57 +0000198static PyGetSetDef partial_getsetlist[] = {
Benjamin Peterson23d7f122012-02-19 20:02:57 -0500199 {"__dict__", PyObject_GenericGetDict, PyObject_GenericSetDict},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000200 {NULL} /* Sentinel */
Raymond Hettingerc8b6d1b2005-03-08 06:14:50 +0000201};
202
Alexander Belopolsky41e422a2010-12-01 20:05:49 +0000203static PyObject *
204partial_repr(partialobject *pto)
205{
Serhiy Storchaka179f9602016-06-12 11:44:06 +0300206 PyObject *result = NULL;
Alexander Belopolsky41e422a2010-12-01 20:05:49 +0000207 PyObject *arglist;
Alexander Belopolsky41e422a2010-12-01 20:05:49 +0000208 Py_ssize_t i, n;
Serhiy Storchaka38741282016-02-02 18:45:17 +0200209 PyObject *key, *value;
Serhiy Storchaka179f9602016-06-12 11:44:06 +0300210 int status;
211
212 status = Py_ReprEnter((PyObject *)pto);
213 if (status != 0) {
214 if (status < 0)
215 return NULL;
216 return PyUnicode_FromFormat("%s(...)", Py_TYPE(pto)->tp_name);
217 }
Alexander Belopolsky41e422a2010-12-01 20:05:49 +0000218
219 arglist = PyUnicode_FromString("");
Serhiy Storchaka179f9602016-06-12 11:44:06 +0300220 if (arglist == NULL)
221 goto done;
Alexander Belopolsky41e422a2010-12-01 20:05:49 +0000222 /* Pack positional arguments */
223 assert (PyTuple_Check(pto->args));
224 n = PyTuple_GET_SIZE(pto->args);
225 for (i = 0; i < n; i++) {
Serhiy Storchaka179f9602016-06-12 11:44:06 +0300226 Py_SETREF(arglist, PyUnicode_FromFormat("%U, %R", arglist,
227 PyTuple_GET_ITEM(pto->args, i)));
228 if (arglist == NULL)
229 goto done;
Alexander Belopolsky41e422a2010-12-01 20:05:49 +0000230 }
231 /* Pack keyword arguments */
Serhiy Storchaka38741282016-02-02 18:45:17 +0200232 assert (PyDict_Check(pto->kw));
233 for (i = 0; PyDict_Next(pto->kw, &i, &key, &value);) {
Serhiy Storchaka179f9602016-06-12 11:44:06 +0300234 Py_SETREF(arglist, PyUnicode_FromFormat("%U, %U=%R", arglist,
235 key, value));
236 if (arglist == NULL)
237 goto done;
Alexander Belopolsky41e422a2010-12-01 20:05:49 +0000238 }
239 result = PyUnicode_FromFormat("%s(%R%U)", Py_TYPE(pto)->tp_name,
240 pto->fn, arglist);
241 Py_DECREF(arglist);
Serhiy Storchaka179f9602016-06-12 11:44:06 +0300242
243 done:
244 Py_ReprLeave((PyObject *)pto);
Alexander Belopolsky41e422a2010-12-01 20:05:49 +0000245 return result;
246}
247
Jack Diederiche0cbd692009-04-01 04:27:09 +0000248/* Pickle strategy:
249 __reduce__ by itself doesn't support getting kwargs in the unpickle
250 operation so we define a __setstate__ that replaces all the information
251 about the partial. If we only replaced part of it someone would use
Ezio Melotti13925002011-03-16 11:05:33 +0200252 it as a hook to do strange things.
Jack Diederiche0cbd692009-04-01 04:27:09 +0000253 */
254
Antoine Pitrou69f71142009-05-24 21:25:49 +0000255static PyObject *
Jack Diederiche0cbd692009-04-01 04:27:09 +0000256partial_reduce(partialobject *pto, PyObject *unused)
257{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000258 return Py_BuildValue("O(O)(OOOO)", Py_TYPE(pto), pto->fn, pto->fn,
259 pto->args, pto->kw,
260 pto->dict ? pto->dict : Py_None);
Jack Diederiche0cbd692009-04-01 04:27:09 +0000261}
262
Antoine Pitrou69f71142009-05-24 21:25:49 +0000263static PyObject *
Serhiy Storchaka19c4e0d2013-02-04 12:47:24 +0200264partial_setstate(partialobject *pto, PyObject *state)
Jack Diederiche0cbd692009-04-01 04:27:09 +0000265{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000266 PyObject *fn, *fnargs, *kw, *dict;
Serhiy Storchaka38741282016-02-02 18:45:17 +0200267
268 if (!PyTuple_Check(state) ||
269 !PyArg_ParseTuple(state, "OOOO", &fn, &fnargs, &kw, &dict) ||
270 !PyCallable_Check(fn) ||
271 !PyTuple_Check(fnargs) ||
272 (kw != Py_None && !PyDict_Check(kw)))
273 {
274 PyErr_SetString(PyExc_TypeError, "invalid partial state");
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000275 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000276 }
Serhiy Storchaka38741282016-02-02 18:45:17 +0200277
278 if(!PyTuple_CheckExact(fnargs))
279 fnargs = PySequence_Tuple(fnargs);
280 else
281 Py_INCREF(fnargs);
282 if (fnargs == NULL)
283 return NULL;
284
285 if (kw == Py_None)
286 kw = PyDict_New();
287 else if(!PyDict_CheckExact(kw))
288 kw = PyDict_Copy(kw);
289 else
290 Py_INCREF(kw);
291 if (kw == NULL) {
292 Py_DECREF(fnargs);
293 return NULL;
294 }
295
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000296 Py_INCREF(fn);
Serhiy Storchaka38741282016-02-02 18:45:17 +0200297 if (dict == Py_None)
298 dict = NULL;
299 else
300 Py_INCREF(dict);
301
Serhiy Storchaka864b63c2016-04-11 09:53:37 +0300302 Py_SETREF(pto->fn, fn);
303 Py_SETREF(pto->args, fnargs);
304 Py_SETREF(pto->kw, kw);
Serhiy Storchaka48842712016-04-06 09:45:48 +0300305 Py_XSETREF(pto->dict, dict);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000306 Py_RETURN_NONE;
Jack Diederiche0cbd692009-04-01 04:27:09 +0000307}
308
309static PyMethodDef partial_methods[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000310 {"__reduce__", (PyCFunction)partial_reduce, METH_NOARGS},
Serhiy Storchaka19c4e0d2013-02-04 12:47:24 +0200311 {"__setstate__", (PyCFunction)partial_setstate, METH_O},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000312 {NULL, NULL} /* sentinel */
Jack Diederiche0cbd692009-04-01 04:27:09 +0000313};
314
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000315static PyTypeObject partial_type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000316 PyVarObject_HEAD_INIT(NULL, 0)
317 "functools.partial", /* tp_name */
318 sizeof(partialobject), /* tp_basicsize */
319 0, /* tp_itemsize */
320 /* methods */
321 (destructor)partial_dealloc, /* tp_dealloc */
322 0, /* tp_print */
323 0, /* tp_getattr */
324 0, /* tp_setattr */
325 0, /* tp_reserved */
Alexander Belopolsky41e422a2010-12-01 20:05:49 +0000326 (reprfunc)partial_repr, /* tp_repr */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000327 0, /* tp_as_number */
328 0, /* tp_as_sequence */
329 0, /* tp_as_mapping */
330 0, /* tp_hash */
331 (ternaryfunc)partial_call, /* tp_call */
332 0, /* tp_str */
333 PyObject_GenericGetAttr, /* tp_getattro */
334 PyObject_GenericSetAttr, /* tp_setattro */
335 0, /* tp_as_buffer */
336 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
337 Py_TPFLAGS_BASETYPE, /* tp_flags */
338 partial_doc, /* tp_doc */
339 (traverseproc)partial_traverse, /* tp_traverse */
340 0, /* tp_clear */
341 0, /* tp_richcompare */
342 offsetof(partialobject, weakreflist), /* tp_weaklistoffset */
343 0, /* tp_iter */
344 0, /* tp_iternext */
345 partial_methods, /* tp_methods */
346 partial_memberlist, /* tp_members */
347 partial_getsetlist, /* tp_getset */
348 0, /* tp_base */
349 0, /* tp_dict */
350 0, /* tp_descr_get */
351 0, /* tp_descr_set */
352 offsetof(partialobject, dict), /* tp_dictoffset */
353 0, /* tp_init */
354 0, /* tp_alloc */
355 partial_new, /* tp_new */
356 PyObject_GC_Del, /* tp_free */
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000357};
358
359
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700360/* cmp_to_key ***************************************************************/
361
362typedef struct {
Victor Stinner446c8d52011-04-05 12:21:35 +0200363 PyObject_HEAD
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700364 PyObject *cmp;
365 PyObject *object;
366} keyobject;
367
368static void
369keyobject_dealloc(keyobject *ko)
370{
371 Py_DECREF(ko->cmp);
372 Py_XDECREF(ko->object);
373 PyObject_FREE(ko);
374}
375
376static int
377keyobject_traverse(keyobject *ko, visitproc visit, void *arg)
378{
379 Py_VISIT(ko->cmp);
380 if (ko->object)
381 Py_VISIT(ko->object);
382 return 0;
383}
384
Benjamin Peterson3bd97292011-04-05 17:25:14 -0500385static int
386keyobject_clear(keyobject *ko)
387{
388 Py_CLEAR(ko->cmp);
389 if (ko->object)
390 Py_CLEAR(ko->object);
391 return 0;
392}
393
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700394static PyMemberDef keyobject_members[] = {
395 {"obj", T_OBJECT,
396 offsetof(keyobject, object), 0,
397 PyDoc_STR("Value wrapped by a key function.")},
398 {NULL}
399};
400
401static PyObject *
Raymond Hettingera5632862011-04-09 12:57:00 -0700402keyobject_call(keyobject *ko, PyObject *args, PyObject *kwds);
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700403
404static PyObject *
405keyobject_richcompare(PyObject *ko, PyObject *other, int op);
406
407static PyTypeObject keyobject_type = {
408 PyVarObject_HEAD_INIT(&PyType_Type, 0)
409 "functools.KeyWrapper", /* tp_name */
410 sizeof(keyobject), /* tp_basicsize */
411 0, /* tp_itemsize */
412 /* methods */
413 (destructor)keyobject_dealloc, /* tp_dealloc */
414 0, /* tp_print */
415 0, /* tp_getattr */
416 0, /* tp_setattr */
417 0, /* tp_reserved */
418 0, /* tp_repr */
419 0, /* tp_as_number */
420 0, /* tp_as_sequence */
421 0, /* tp_as_mapping */
422 0, /* tp_hash */
423 (ternaryfunc)keyobject_call, /* tp_call */
424 0, /* tp_str */
425 PyObject_GenericGetAttr, /* tp_getattro */
426 0, /* tp_setattro */
427 0, /* tp_as_buffer */
428 Py_TPFLAGS_DEFAULT, /* tp_flags */
429 0, /* tp_doc */
430 (traverseproc)keyobject_traverse, /* tp_traverse */
Benjamin Peterson3bd97292011-04-05 17:25:14 -0500431 (inquiry)keyobject_clear, /* tp_clear */
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700432 keyobject_richcompare, /* tp_richcompare */
433 0, /* tp_weaklistoffset */
434 0, /* tp_iter */
435 0, /* tp_iternext */
436 0, /* tp_methods */
437 keyobject_members, /* tp_members */
438 0, /* tp_getset */
439};
440
441static PyObject *
442keyobject_call(keyobject *ko, PyObject *args, PyObject *kwds)
443{
444 PyObject *object;
445 keyobject *result;
446 static char *kwargs[] = {"obj", NULL};
447
448 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:K", kwargs, &object))
449 return NULL;
450 result = PyObject_New(keyobject, &keyobject_type);
451 if (!result)
452 return NULL;
453 Py_INCREF(ko->cmp);
454 result->cmp = ko->cmp;
455 Py_INCREF(object);
456 result->object = object;
457 return (PyObject *)result;
458}
459
460static PyObject *
461keyobject_richcompare(PyObject *ko, PyObject *other, int op)
462{
463 PyObject *res;
464 PyObject *args;
465 PyObject *x;
466 PyObject *y;
467 PyObject *compare;
468 PyObject *answer;
469 static PyObject *zero;
470
471 if (zero == NULL) {
472 zero = PyLong_FromLong(0);
473 if (!zero)
474 return NULL;
475 }
476
477 if (Py_TYPE(other) != &keyobject_type){
478 PyErr_Format(PyExc_TypeError, "other argument must be K instance");
479 return NULL;
480 }
481 compare = ((keyobject *) ko)->cmp;
482 assert(compare != NULL);
483 x = ((keyobject *) ko)->object;
484 y = ((keyobject *) other)->object;
485 if (!x || !y){
486 PyErr_Format(PyExc_AttributeError, "object");
487 return NULL;
488 }
489
490 /* Call the user's comparison function and translate the 3-way
491 * result into true or false (or error).
492 */
493 args = PyTuple_New(2);
494 if (args == NULL)
495 return NULL;
496 Py_INCREF(x);
497 Py_INCREF(y);
498 PyTuple_SET_ITEM(args, 0, x);
499 PyTuple_SET_ITEM(args, 1, y);
500 res = PyObject_Call(compare, args, NULL);
501 Py_DECREF(args);
502 if (res == NULL)
503 return NULL;
504 answer = PyObject_RichCompare(res, zero, op);
505 Py_DECREF(res);
506 return answer;
507}
508
509static PyObject *
Victor Stinner446c8d52011-04-05 12:21:35 +0200510functools_cmp_to_key(PyObject *self, PyObject *args, PyObject *kwds)
511{
512 PyObject *cmp;
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700513 static char *kwargs[] = {"mycmp", NULL};
Victor Stinner446c8d52011-04-05 12:21:35 +0200514 keyobject *object;
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700515
516 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:cmp_to_key", kwargs, &cmp))
517 return NULL;
Victor Stinner446c8d52011-04-05 12:21:35 +0200518 object = PyObject_New(keyobject, &keyobject_type);
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700519 if (!object)
520 return NULL;
521 Py_INCREF(cmp);
522 object->cmp = cmp;
523 object->object = NULL;
524 return (PyObject *)object;
525}
526
527PyDoc_STRVAR(functools_cmp_to_key_doc,
528"Convert a cmp= function into a key= function.");
529
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000530/* reduce (used to be a builtin) ********************************************/
531
532static PyObject *
533functools_reduce(PyObject *self, PyObject *args)
534{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000535 PyObject *seq, *func, *result = NULL, *it;
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000536
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000537 if (!PyArg_UnpackTuple(args, "reduce", 2, 3, &func, &seq, &result))
538 return NULL;
539 if (result != NULL)
540 Py_INCREF(result);
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000541
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000542 it = PyObject_GetIter(seq);
543 if (it == NULL) {
Alexander Belopolskye29e6bf2010-08-16 18:55:46 +0000544 if (PyErr_ExceptionMatches(PyExc_TypeError))
545 PyErr_SetString(PyExc_TypeError,
546 "reduce() arg 2 must support iteration");
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000547 Py_XDECREF(result);
548 return NULL;
549 }
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000550
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000551 if ((args = PyTuple_New(2)) == NULL)
552 goto Fail;
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000553
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000554 for (;;) {
555 PyObject *op2;
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000556
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000557 if (args->ob_refcnt > 1) {
558 Py_DECREF(args);
559 if ((args = PyTuple_New(2)) == NULL)
560 goto Fail;
561 }
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000562
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000563 op2 = PyIter_Next(it);
564 if (op2 == NULL) {
565 if (PyErr_Occurred())
566 goto Fail;
567 break;
568 }
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000569
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000570 if (result == NULL)
571 result = op2;
572 else {
573 PyTuple_SetItem(args, 0, result);
574 PyTuple_SetItem(args, 1, op2);
575 if ((result = PyEval_CallObject(func, args)) == NULL)
576 goto Fail;
577 }
578 }
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000579
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000580 Py_DECREF(args);
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000581
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000582 if (result == NULL)
583 PyErr_SetString(PyExc_TypeError,
584 "reduce() of empty sequence with no initial value");
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000585
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000586 Py_DECREF(it);
587 return result;
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000588
589Fail:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000590 Py_XDECREF(args);
591 Py_XDECREF(result);
592 Py_DECREF(it);
593 return NULL;
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000594}
595
596PyDoc_STRVAR(functools_reduce_doc,
597"reduce(function, sequence[, initial]) -> value\n\
598\n\
599Apply a function of two arguments cumulatively to the items of a sequence,\n\
600from left to right, so as to reduce the sequence to a single value.\n\
601For example, reduce(lambda x, y: x+y, [1, 2, 3, 4, 5]) calculates\n\
602((((1+2)+3)+4)+5). If initial is present, it is placed before the items\n\
603of the sequence in the calculation, and serves as a default when the\n\
604sequence is empty.");
605
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300606/* lru_cache object **********************************************************/
607
608/* this object is used delimit args and keywords in the cache keys */
609static PyObject *kwd_mark = NULL;
610
611struct lru_list_elem;
612struct lru_cache_object;
613
614typedef struct lru_list_elem {
615 PyObject_HEAD
616 struct lru_list_elem *prev, *next; /* borrowed links */
Serhiy Storchakab9d98d52015-10-02 12:47:11 +0300617 Py_hash_t hash;
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300618 PyObject *key, *result;
619} lru_list_elem;
620
621static void
622lru_list_elem_dealloc(lru_list_elem *link)
623{
624 _PyObject_GC_UNTRACK(link);
625 Py_XDECREF(link->key);
626 Py_XDECREF(link->result);
627 PyObject_GC_Del(link);
628}
629
630static int
631lru_list_elem_traverse(lru_list_elem *link, visitproc visit, void *arg)
632{
633 Py_VISIT(link->key);
634 Py_VISIT(link->result);
635 return 0;
636}
637
638static int
639lru_list_elem_clear(lru_list_elem *link)
640{
641 Py_CLEAR(link->key);
642 Py_CLEAR(link->result);
643 return 0;
644}
645
646static PyTypeObject lru_list_elem_type = {
647 PyVarObject_HEAD_INIT(&PyType_Type, 0)
648 "functools._lru_list_elem", /* tp_name */
649 sizeof(lru_list_elem), /* tp_basicsize */
650 0, /* tp_itemsize */
651 /* methods */
652 (destructor)lru_list_elem_dealloc, /* tp_dealloc */
653 0, /* tp_print */
654 0, /* tp_getattr */
655 0, /* tp_setattr */
656 0, /* tp_reserved */
657 0, /* tp_repr */
658 0, /* tp_as_number */
659 0, /* tp_as_sequence */
660 0, /* tp_as_mapping */
661 0, /* tp_hash */
662 0, /* tp_call */
663 0, /* tp_str */
664 0, /* tp_getattro */
665 0, /* tp_setattro */
666 0, /* tp_as_buffer */
667 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
668 0, /* tp_doc */
669 (traverseproc)lru_list_elem_traverse, /* tp_traverse */
670 (inquiry)lru_list_elem_clear, /* tp_clear */
671};
672
673
674typedef PyObject *(*lru_cache_ternaryfunc)(struct lru_cache_object *, PyObject *, PyObject *);
675
676typedef struct lru_cache_object {
677 lru_list_elem root; /* includes PyObject_HEAD */
678 Py_ssize_t maxsize;
679 PyObject *maxsize_O;
680 PyObject *func;
681 lru_cache_ternaryfunc wrapper;
682 PyObject *cache;
683 PyObject *cache_info_type;
684 Py_ssize_t misses, hits;
685 int typed;
686 PyObject *dict;
687 int full;
688} lru_cache_object;
689
690static PyTypeObject lru_cache_type;
691
692static PyObject *
693lru_cache_make_key(PyObject *args, PyObject *kwds, int typed)
694{
695 PyObject *key, *sorted_items;
696 Py_ssize_t key_size, pos, key_pos;
697
698 /* short path, key will match args anyway, which is a tuple */
699 if (!typed && !kwds) {
700 Py_INCREF(args);
701 return args;
702 }
703
704 if (kwds && PyDict_Size(kwds) > 0) {
705 sorted_items = PyDict_Items(kwds);
706 if (!sorted_items)
707 return NULL;
708 if (PyList_Sort(sorted_items) < 0) {
709 Py_DECREF(sorted_items);
710 return NULL;
711 }
712 } else
713 sorted_items = NULL;
714
715 key_size = PyTuple_GET_SIZE(args);
716 if (sorted_items)
717 key_size += PyList_GET_SIZE(sorted_items);
718 if (typed)
719 key_size *= 2;
720 if (sorted_items)
721 key_size++;
722
723 key = PyTuple_New(key_size);
724 if (key == NULL)
725 goto done;
726
727 key_pos = 0;
728 for (pos = 0; pos < PyTuple_GET_SIZE(args); ++pos) {
729 PyObject *item = PyTuple_GET_ITEM(args, pos);
730 Py_INCREF(item);
731 PyTuple_SET_ITEM(key, key_pos++, item);
732 }
733 if (sorted_items) {
734 Py_INCREF(kwd_mark);
735 PyTuple_SET_ITEM(key, key_pos++, kwd_mark);
736 for (pos = 0; pos < PyList_GET_SIZE(sorted_items); ++pos) {
737 PyObject *item = PyList_GET_ITEM(sorted_items, pos);
738 Py_INCREF(item);
739 PyTuple_SET_ITEM(key, key_pos++, item);
740 }
741 }
742 if (typed) {
743 for (pos = 0; pos < PyTuple_GET_SIZE(args); ++pos) {
744 PyObject *item = (PyObject *)Py_TYPE(PyTuple_GET_ITEM(args, pos));
745 Py_INCREF(item);
746 PyTuple_SET_ITEM(key, key_pos++, item);
747 }
748 if (sorted_items) {
749 for (pos = 0; pos < PyList_GET_SIZE(sorted_items); ++pos) {
750 PyObject *tp_items = PyList_GET_ITEM(sorted_items, pos);
751 PyObject *item = (PyObject *)Py_TYPE(PyTuple_GET_ITEM(tp_items, 1));
752 Py_INCREF(item);
753 PyTuple_SET_ITEM(key, key_pos++, item);
754 }
755 }
756 }
757 assert(key_pos == key_size);
758
759done:
760 if (sorted_items)
761 Py_DECREF(sorted_items);
762 return key;
763}
764
765static PyObject *
766uncached_lru_cache_wrapper(lru_cache_object *self, PyObject *args, PyObject *kwds)
767{
768 PyObject *result = PyObject_Call(self->func, args, kwds);
769 if (!result)
770 return NULL;
771 self->misses++;
772 return result;
773}
774
775static PyObject *
776infinite_lru_cache_wrapper(lru_cache_object *self, PyObject *args, PyObject *kwds)
777{
778 PyObject *result;
Serhiy Storchakab9d98d52015-10-02 12:47:11 +0300779 Py_hash_t hash;
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300780 PyObject *key = lru_cache_make_key(args, kwds, self->typed);
781 if (!key)
782 return NULL;
Serhiy Storchakab9d98d52015-10-02 12:47:11 +0300783 hash = PyObject_Hash(key);
784 if (hash == -1)
785 return NULL;
786 result = _PyDict_GetItem_KnownHash(self->cache, key, hash);
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300787 if (result) {
788 Py_INCREF(result);
789 self->hits++;
790 Py_DECREF(key);
791 return result;
792 }
793 if (PyErr_Occurred()) {
794 Py_DECREF(key);
795 return NULL;
796 }
797 result = PyObject_Call(self->func, args, kwds);
798 if (!result) {
799 Py_DECREF(key);
800 return NULL;
801 }
Serhiy Storchakab9d98d52015-10-02 12:47:11 +0300802 if (_PyDict_SetItem_KnownHash(self->cache, key, result, hash) < 0) {
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300803 Py_DECREF(result);
804 Py_DECREF(key);
805 return NULL;
806 }
807 Py_DECREF(key);
808 self->misses++;
809 return result;
810}
811
812static void
813lru_cache_extricate_link(lru_list_elem *link)
814{
815 link->prev->next = link->next;
816 link->next->prev = link->prev;
817}
818
819static void
820lru_cache_append_link(lru_cache_object *self, lru_list_elem *link)
821{
822 lru_list_elem *root = &self->root;
823 lru_list_elem *last = root->prev;
824 last->next = root->prev = link;
825 link->prev = last;
826 link->next = root;
827}
828
829static PyObject *
830bounded_lru_cache_wrapper(lru_cache_object *self, PyObject *args, PyObject *kwds)
831{
832 lru_list_elem *link;
833 PyObject *key, *result;
Serhiy Storchakab9d98d52015-10-02 12:47:11 +0300834 Py_hash_t hash;
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300835
836 key = lru_cache_make_key(args, kwds, self->typed);
837 if (!key)
838 return NULL;
Serhiy Storchakab9d98d52015-10-02 12:47:11 +0300839 hash = PyObject_Hash(key);
840 if (hash == -1)
841 return NULL;
842 link = (lru_list_elem *)_PyDict_GetItem_KnownHash(self->cache, key, hash);
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300843 if (link) {
844 lru_cache_extricate_link(link);
845 lru_cache_append_link(self, link);
846 self->hits++;
847 result = link->result;
848 Py_INCREF(result);
849 Py_DECREF(key);
850 return result;
851 }
852 if (PyErr_Occurred()) {
853 Py_DECREF(key);
854 return NULL;
855 }
856 result = PyObject_Call(self->func, args, kwds);
857 if (!result) {
858 Py_DECREF(key);
859 return NULL;
860 }
861 if (self->full && self->root.next != &self->root) {
862 /* Use the oldest item to store the new key and result. */
863 PyObject *oldkey, *oldresult;
864 /* Extricate the oldest item. */
865 link = self->root.next;
866 lru_cache_extricate_link(link);
867 /* Remove it from the cache.
868 The cache dict holds one reference to the link,
869 and the linked list holds yet one reference to it. */
Serhiy Storchakab9d98d52015-10-02 12:47:11 +0300870 if (_PyDict_DelItem_KnownHash(self->cache, link->key,
871 link->hash) < 0) {
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300872 lru_cache_append_link(self, link);
873 Py_DECREF(key);
874 Py_DECREF(result);
875 return NULL;
876 }
877 /* Keep a reference to the old key and old result to
878 prevent their ref counts from going to zero during the
879 update. That will prevent potentially arbitrary object
880 clean-up code (i.e. __del__) from running while we're
881 still adjusting the links. */
882 oldkey = link->key;
883 oldresult = link->result;
884
Serhiy Storchakab9d98d52015-10-02 12:47:11 +0300885 link->hash = hash;
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300886 link->key = key;
887 link->result = result;
Serhiy Storchakab9d98d52015-10-02 12:47:11 +0300888 if (_PyDict_SetItem_KnownHash(self->cache, key, (PyObject *)link,
889 hash) < 0) {
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300890 Py_DECREF(link);
891 Py_DECREF(oldkey);
892 Py_DECREF(oldresult);
893 return NULL;
894 }
895 lru_cache_append_link(self, link);
896 Py_INCREF(result); /* for return */
897 Py_DECREF(oldkey);
898 Py_DECREF(oldresult);
899 } else {
900 /* Put result in a new link at the front of the queue. */
901 link = (lru_list_elem *)PyObject_GC_New(lru_list_elem,
902 &lru_list_elem_type);
903 if (link == NULL) {
904 Py_DECREF(key);
905 Py_DECREF(result);
906 return NULL;
907 }
908
Serhiy Storchakab9d98d52015-10-02 12:47:11 +0300909 link->hash = hash;
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300910 link->key = key;
911 link->result = result;
912 _PyObject_GC_TRACK(link);
Serhiy Storchakab9d98d52015-10-02 12:47:11 +0300913 if (_PyDict_SetItem_KnownHash(self->cache, key, (PyObject *)link,
914 hash) < 0) {
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300915 Py_DECREF(link);
916 return NULL;
917 }
918 lru_cache_append_link(self, link);
919 Py_INCREF(result); /* for return */
920 self->full = (PyDict_Size(self->cache) >= self->maxsize);
921 }
922 self->misses++;
923 return result;
924}
925
926static PyObject *
927lru_cache_new(PyTypeObject *type, PyObject *args, PyObject *kw)
928{
Serhiy Storchaka374164c2015-07-25 12:10:21 +0300929 PyObject *func, *maxsize_O, *cache_info_type, *cachedict;
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300930 int typed;
931 lru_cache_object *obj;
932 Py_ssize_t maxsize;
933 PyObject *(*wrapper)(lru_cache_object *, PyObject *, PyObject *);
934 static char *keywords[] = {"user_function", "maxsize", "typed",
935 "cache_info_type", NULL};
936
937 if (!PyArg_ParseTupleAndKeywords(args, kw, "OOpO:lru_cache", keywords,
938 &func, &maxsize_O, &typed,
939 &cache_info_type)) {
940 return NULL;
941 }
942
943 if (!PyCallable_Check(func)) {
944 PyErr_SetString(PyExc_TypeError,
945 "the first argument must be callable");
946 return NULL;
947 }
948
949 /* select the caching function, and make/inc maxsize_O */
950 if (maxsize_O == Py_None) {
951 wrapper = infinite_lru_cache_wrapper;
952 /* use this only to initialize lru_cache_object attribute maxsize */
953 maxsize = -1;
954 } else if (PyIndex_Check(maxsize_O)) {
955 maxsize = PyNumber_AsSsize_t(maxsize_O, PyExc_OverflowError);
956 if (maxsize == -1 && PyErr_Occurred())
957 return NULL;
958 if (maxsize == 0)
959 wrapper = uncached_lru_cache_wrapper;
960 else
961 wrapper = bounded_lru_cache_wrapper;
962 } else {
963 PyErr_SetString(PyExc_TypeError, "maxsize should be integer or None");
964 return NULL;
965 }
966
Serhiy Storchaka374164c2015-07-25 12:10:21 +0300967 if (!(cachedict = PyDict_New()))
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300968 return NULL;
969
Serhiy Storchaka374164c2015-07-25 12:10:21 +0300970 obj = (lru_cache_object *)type->tp_alloc(type, 0);
971 if (obj == NULL) {
972 Py_DECREF(cachedict);
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300973 return NULL;
974 }
975
Serhiy Storchaka374164c2015-07-25 12:10:21 +0300976 obj->cache = cachedict;
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300977 obj->root.prev = &obj->root;
978 obj->root.next = &obj->root;
979 obj->maxsize = maxsize;
980 Py_INCREF(maxsize_O);
981 obj->maxsize_O = maxsize_O;
982 Py_INCREF(func);
983 obj->func = func;
984 obj->wrapper = wrapper;
985 obj->misses = obj->hits = 0;
986 obj->typed = typed;
987 Py_INCREF(cache_info_type);
988 obj->cache_info_type = cache_info_type;
989
990 return (PyObject *)obj;
991}
992
993static lru_list_elem *
994lru_cache_unlink_list(lru_cache_object *self)
995{
996 lru_list_elem *root = &self->root;
997 lru_list_elem *link = root->next;
998 if (link == root)
999 return NULL;
1000 root->prev->next = NULL;
1001 root->next = root->prev = root;
1002 return link;
1003}
1004
1005static void
1006lru_cache_clear_list(lru_list_elem *link)
1007{
1008 while (link != NULL) {
1009 lru_list_elem *next = link->next;
1010 Py_DECREF(link);
1011 link = next;
1012 }
1013}
1014
1015static void
1016lru_cache_dealloc(lru_cache_object *obj)
1017{
1018 lru_list_elem *list = lru_cache_unlink_list(obj);
1019 Py_XDECREF(obj->maxsize_O);
1020 Py_XDECREF(obj->func);
1021 Py_XDECREF(obj->cache);
1022 Py_XDECREF(obj->dict);
1023 Py_XDECREF(obj->cache_info_type);
1024 lru_cache_clear_list(list);
1025 Py_TYPE(obj)->tp_free(obj);
1026}
1027
1028static PyObject *
1029lru_cache_call(lru_cache_object *self, PyObject *args, PyObject *kwds)
1030{
1031 return self->wrapper(self, args, kwds);
1032}
1033
1034static PyObject *
Serhiy Storchakae7070f02015-06-08 11:19:24 +03001035lru_cache_descr_get(PyObject *self, PyObject *obj, PyObject *type)
1036{
1037 if (obj == Py_None || obj == NULL) {
1038 Py_INCREF(self);
1039 return self;
1040 }
1041 return PyMethod_New(self, obj);
1042}
1043
1044static PyObject *
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001045lru_cache_cache_info(lru_cache_object *self, PyObject *unused)
1046{
1047 return PyObject_CallFunction(self->cache_info_type, "nnOn",
1048 self->hits, self->misses, self->maxsize_O,
1049 PyDict_Size(self->cache));
1050}
1051
1052static PyObject *
1053lru_cache_cache_clear(lru_cache_object *self, PyObject *unused)
1054{
1055 lru_list_elem *list = lru_cache_unlink_list(self);
1056 self->hits = self->misses = 0;
1057 self->full = 0;
1058 PyDict_Clear(self->cache);
1059 lru_cache_clear_list(list);
1060 Py_RETURN_NONE;
1061}
1062
Serhiy Storchaka45120f22015-10-24 09:49:56 +03001063static PyObject *
1064lru_cache_reduce(PyObject *self, PyObject *unused)
1065{
1066 return PyObject_GetAttrString(self, "__qualname__");
1067}
1068
Serhiy Storchakae4d65e32015-12-28 23:58:07 +02001069static PyObject *
1070lru_cache_copy(PyObject *self, PyObject *unused)
1071{
1072 Py_INCREF(self);
1073 return self;
1074}
1075
1076static PyObject *
1077lru_cache_deepcopy(PyObject *self, PyObject *unused)
1078{
1079 Py_INCREF(self);
1080 return self;
1081}
1082
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001083static int
1084lru_cache_tp_traverse(lru_cache_object *self, visitproc visit, void *arg)
1085{
1086 lru_list_elem *link = self->root.next;
1087 while (link != &self->root) {
1088 lru_list_elem *next = link->next;
1089 Py_VISIT(link);
1090 link = next;
1091 }
1092 Py_VISIT(self->maxsize_O);
1093 Py_VISIT(self->func);
1094 Py_VISIT(self->cache);
1095 Py_VISIT(self->cache_info_type);
1096 Py_VISIT(self->dict);
1097 return 0;
1098}
1099
1100static int
1101lru_cache_tp_clear(lru_cache_object *self)
1102{
1103 lru_list_elem *list = lru_cache_unlink_list(self);
1104 Py_CLEAR(self->maxsize_O);
1105 Py_CLEAR(self->func);
1106 Py_CLEAR(self->cache);
1107 Py_CLEAR(self->cache_info_type);
1108 Py_CLEAR(self->dict);
1109 lru_cache_clear_list(list);
1110 return 0;
1111}
1112
1113
1114PyDoc_STRVAR(lru_cache_doc,
1115"Create a cached callable that wraps another function.\n\
1116\n\
1117user_function: the function being cached\n\
1118\n\
1119maxsize: 0 for no caching\n\
1120 None for unlimited cache size\n\
1121 n for a bounded cache\n\
1122\n\
1123typed: False cache f(3) and f(3.0) as identical calls\n\
1124 True cache f(3) and f(3.0) as distinct calls\n\
1125\n\
1126cache_info_type: namedtuple class with the fields:\n\
1127 hits misses currsize maxsize\n"
1128);
1129
1130static PyMethodDef lru_cache_methods[] = {
1131 {"cache_info", (PyCFunction)lru_cache_cache_info, METH_NOARGS},
1132 {"cache_clear", (PyCFunction)lru_cache_cache_clear, METH_NOARGS},
Serhiy Storchaka45120f22015-10-24 09:49:56 +03001133 {"__reduce__", (PyCFunction)lru_cache_reduce, METH_NOARGS},
Serhiy Storchakae4d65e32015-12-28 23:58:07 +02001134 {"__copy__", (PyCFunction)lru_cache_copy, METH_VARARGS},
1135 {"__deepcopy__", (PyCFunction)lru_cache_deepcopy, METH_VARARGS},
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001136 {NULL}
1137};
1138
1139static PyGetSetDef lru_cache_getsetlist[] = {
1140 {"__dict__", PyObject_GenericGetDict, PyObject_GenericSetDict},
1141 {NULL}
1142};
1143
1144static PyTypeObject lru_cache_type = {
1145 PyVarObject_HEAD_INIT(NULL, 0)
1146 "functools._lru_cache_wrapper", /* tp_name */
1147 sizeof(lru_cache_object), /* tp_basicsize */
1148 0, /* tp_itemsize */
1149 /* methods */
1150 (destructor)lru_cache_dealloc, /* tp_dealloc */
1151 0, /* tp_print */
1152 0, /* tp_getattr */
1153 0, /* tp_setattr */
1154 0, /* tp_reserved */
1155 0, /* tp_repr */
1156 0, /* tp_as_number */
1157 0, /* tp_as_sequence */
1158 0, /* tp_as_mapping */
1159 0, /* tp_hash */
1160 (ternaryfunc)lru_cache_call, /* tp_call */
1161 0, /* tp_str */
1162 0, /* tp_getattro */
1163 0, /* tp_setattro */
1164 0, /* tp_as_buffer */
1165 Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_HAVE_GC,
1166 /* tp_flags */
1167 lru_cache_doc, /* tp_doc */
1168 (traverseproc)lru_cache_tp_traverse,/* tp_traverse */
1169 (inquiry)lru_cache_tp_clear, /* tp_clear */
1170 0, /* tp_richcompare */
1171 0, /* tp_weaklistoffset */
1172 0, /* tp_iter */
1173 0, /* tp_iternext */
1174 lru_cache_methods, /* tp_methods */
1175 0, /* tp_members */
1176 lru_cache_getsetlist, /* tp_getset */
1177 0, /* tp_base */
1178 0, /* tp_dict */
Serhiy Storchakae7070f02015-06-08 11:19:24 +03001179 lru_cache_descr_get, /* tp_descr_get */
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001180 0, /* tp_descr_set */
1181 offsetof(lru_cache_object, dict), /* tp_dictoffset */
1182 0, /* tp_init */
1183 0, /* tp_alloc */
1184 lru_cache_new, /* tp_new */
1185};
1186
Raymond Hettinger9c323f82005-02-28 19:39:44 +00001187/* module level code ********************************************************/
1188
1189PyDoc_STRVAR(module_doc,
Thomas Wouters4d70c3d2006-06-08 14:42:34 +00001190"Tools that operate on functions.");
Raymond Hettinger9c323f82005-02-28 19:39:44 +00001191
1192static PyMethodDef module_methods[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001193 {"reduce", functools_reduce, METH_VARARGS, functools_reduce_doc},
Victor Stinner446c8d52011-04-05 12:21:35 +02001194 {"cmp_to_key", (PyCFunction)functools_cmp_to_key,
1195 METH_VARARGS | METH_KEYWORDS, functools_cmp_to_key_doc},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001196 {NULL, NULL} /* sentinel */
Raymond Hettinger9c323f82005-02-28 19:39:44 +00001197};
1198
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001199static void
1200module_free(void *m)
1201{
1202 Py_CLEAR(kwd_mark);
1203}
Martin v. Löwis1a214512008-06-11 05:26:20 +00001204
1205static struct PyModuleDef _functoolsmodule = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001206 PyModuleDef_HEAD_INIT,
1207 "_functools",
1208 module_doc,
1209 -1,
1210 module_methods,
1211 NULL,
1212 NULL,
1213 NULL,
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001214 module_free,
Martin v. Löwis1a214512008-06-11 05:26:20 +00001215};
1216
Raymond Hettinger9c323f82005-02-28 19:39:44 +00001217PyMODINIT_FUNC
Martin v. Löwis1a214512008-06-11 05:26:20 +00001218PyInit__functools(void)
Raymond Hettinger9c323f82005-02-28 19:39:44 +00001219{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001220 int i;
1221 PyObject *m;
1222 char *name;
1223 PyTypeObject *typelist[] = {
1224 &partial_type,
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001225 &lru_cache_type,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001226 NULL
1227 };
Raymond Hettinger9c323f82005-02-28 19:39:44 +00001228
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001229 m = PyModule_Create(&_functoolsmodule);
1230 if (m == NULL)
1231 return NULL;
Raymond Hettinger9c323f82005-02-28 19:39:44 +00001232
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001233 kwd_mark = PyObject_CallObject((PyObject *)&PyBaseObject_Type, NULL);
1234 if (!kwd_mark) {
1235 Py_DECREF(m);
1236 return NULL;
1237 }
1238
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001239 for (i=0 ; typelist[i] != NULL ; i++) {
1240 if (PyType_Ready(typelist[i]) < 0) {
1241 Py_DECREF(m);
1242 return NULL;
1243 }
1244 name = strchr(typelist[i]->tp_name, '.');
1245 assert (name != NULL);
1246 Py_INCREF(typelist[i]);
1247 PyModule_AddObject(m, name+1, (PyObject *)typelist[i]);
1248 }
1249 return m;
Raymond Hettinger9c323f82005-02-28 19:39:44 +00001250}