blob: be0f5f9e652abc10d193bb9e99a5e60f87e96b3f [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);
Yury Selivanov46a02db2016-11-09 18:55:45 -0500784 if (hash == -1) {
785 Py_DECREF(key);
Serhiy Storchakab9d98d52015-10-02 12:47:11 +0300786 return NULL;
Yury Selivanov46a02db2016-11-09 18:55:45 -0500787 }
Serhiy Storchakab9d98d52015-10-02 12:47:11 +0300788 result = _PyDict_GetItem_KnownHash(self->cache, key, hash);
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300789 if (result) {
790 Py_INCREF(result);
791 self->hits++;
792 Py_DECREF(key);
793 return result;
794 }
795 if (PyErr_Occurred()) {
796 Py_DECREF(key);
797 return NULL;
798 }
799 result = PyObject_Call(self->func, args, kwds);
800 if (!result) {
801 Py_DECREF(key);
802 return NULL;
803 }
Serhiy Storchakab9d98d52015-10-02 12:47:11 +0300804 if (_PyDict_SetItem_KnownHash(self->cache, key, result, hash) < 0) {
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300805 Py_DECREF(result);
806 Py_DECREF(key);
807 return NULL;
808 }
809 Py_DECREF(key);
810 self->misses++;
811 return result;
812}
813
814static void
815lru_cache_extricate_link(lru_list_elem *link)
816{
817 link->prev->next = link->next;
818 link->next->prev = link->prev;
819}
820
821static void
822lru_cache_append_link(lru_cache_object *self, lru_list_elem *link)
823{
824 lru_list_elem *root = &self->root;
825 lru_list_elem *last = root->prev;
826 last->next = root->prev = link;
827 link->prev = last;
828 link->next = root;
829}
830
831static PyObject *
832bounded_lru_cache_wrapper(lru_cache_object *self, PyObject *args, PyObject *kwds)
833{
834 lru_list_elem *link;
835 PyObject *key, *result;
Serhiy Storchakab9d98d52015-10-02 12:47:11 +0300836 Py_hash_t hash;
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300837
838 key = lru_cache_make_key(args, kwds, self->typed);
839 if (!key)
840 return NULL;
Serhiy Storchakab9d98d52015-10-02 12:47:11 +0300841 hash = PyObject_Hash(key);
Yury Selivanov46a02db2016-11-09 18:55:45 -0500842 if (hash == -1) {
843 Py_DECREF(key);
Serhiy Storchakab9d98d52015-10-02 12:47:11 +0300844 return NULL;
Yury Selivanov46a02db2016-11-09 18:55:45 -0500845 }
Serhiy Storchakab9d98d52015-10-02 12:47:11 +0300846 link = (lru_list_elem *)_PyDict_GetItem_KnownHash(self->cache, key, hash);
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300847 if (link) {
848 lru_cache_extricate_link(link);
849 lru_cache_append_link(self, link);
850 self->hits++;
851 result = link->result;
852 Py_INCREF(result);
853 Py_DECREF(key);
854 return result;
855 }
856 if (PyErr_Occurred()) {
857 Py_DECREF(key);
858 return NULL;
859 }
860 result = PyObject_Call(self->func, args, kwds);
861 if (!result) {
862 Py_DECREF(key);
863 return NULL;
864 }
865 if (self->full && self->root.next != &self->root) {
866 /* Use the oldest item to store the new key and result. */
Serhiy Storchaka67796522017-01-12 18:34:33 +0200867 PyObject *oldkey, *oldresult, *popresult;
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300868 /* Extricate the oldest item. */
869 link = self->root.next;
870 lru_cache_extricate_link(link);
871 /* Remove it from the cache.
872 The cache dict holds one reference to the link,
873 and the linked list holds yet one reference to it. */
Serhiy Storchaka67796522017-01-12 18:34:33 +0200874 popresult = _PyDict_Pop_KnownHash((PyDictObject *)self->cache,
875 link->key, link->hash,
876 Py_None);
877 if (popresult == Py_None) {
878 /* Getting here means that this same key was added to the
879 cache while the lock was released. Since the link
880 update is already done, we need only return the
881 computed result and update the count of misses. */
882 Py_DECREF(popresult);
883 Py_DECREF(link);
884 Py_DECREF(key);
885 }
886 else if (popresult == NULL) {
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300887 lru_cache_append_link(self, link);
888 Py_DECREF(key);
889 Py_DECREF(result);
890 return NULL;
891 }
Serhiy Storchaka67796522017-01-12 18:34:33 +0200892 else {
893 Py_DECREF(popresult);
894 /* Keep a reference to the old key and old result to
895 prevent their ref counts from going to zero during the
896 update. That will prevent potentially arbitrary object
897 clean-up code (i.e. __del__) from running while we're
898 still adjusting the links. */
899 oldkey = link->key;
900 oldresult = link->result;
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300901
Serhiy Storchaka67796522017-01-12 18:34:33 +0200902 link->hash = hash;
903 link->key = key;
904 link->result = result;
905 if (_PyDict_SetItem_KnownHash(self->cache, key, (PyObject *)link,
906 hash) < 0) {
907 Py_DECREF(link);
908 Py_DECREF(oldkey);
909 Py_DECREF(oldresult);
910 return NULL;
911 }
912 lru_cache_append_link(self, link);
913 Py_INCREF(result); /* for return */
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300914 Py_DECREF(oldkey);
915 Py_DECREF(oldresult);
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300916 }
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300917 } else {
918 /* Put result in a new link at the front of the queue. */
919 link = (lru_list_elem *)PyObject_GC_New(lru_list_elem,
920 &lru_list_elem_type);
921 if (link == NULL) {
922 Py_DECREF(key);
923 Py_DECREF(result);
924 return NULL;
925 }
926
Serhiy Storchakab9d98d52015-10-02 12:47:11 +0300927 link->hash = hash;
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300928 link->key = key;
929 link->result = result;
930 _PyObject_GC_TRACK(link);
Serhiy Storchakab9d98d52015-10-02 12:47:11 +0300931 if (_PyDict_SetItem_KnownHash(self->cache, key, (PyObject *)link,
932 hash) < 0) {
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300933 Py_DECREF(link);
934 return NULL;
935 }
936 lru_cache_append_link(self, link);
937 Py_INCREF(result); /* for return */
938 self->full = (PyDict_Size(self->cache) >= self->maxsize);
939 }
940 self->misses++;
941 return result;
942}
943
944static PyObject *
945lru_cache_new(PyTypeObject *type, PyObject *args, PyObject *kw)
946{
Serhiy Storchaka374164c2015-07-25 12:10:21 +0300947 PyObject *func, *maxsize_O, *cache_info_type, *cachedict;
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300948 int typed;
949 lru_cache_object *obj;
950 Py_ssize_t maxsize;
951 PyObject *(*wrapper)(lru_cache_object *, PyObject *, PyObject *);
952 static char *keywords[] = {"user_function", "maxsize", "typed",
953 "cache_info_type", NULL};
954
955 if (!PyArg_ParseTupleAndKeywords(args, kw, "OOpO:lru_cache", keywords,
956 &func, &maxsize_O, &typed,
957 &cache_info_type)) {
958 return NULL;
959 }
960
961 if (!PyCallable_Check(func)) {
962 PyErr_SetString(PyExc_TypeError,
963 "the first argument must be callable");
964 return NULL;
965 }
966
967 /* select the caching function, and make/inc maxsize_O */
968 if (maxsize_O == Py_None) {
969 wrapper = infinite_lru_cache_wrapper;
970 /* use this only to initialize lru_cache_object attribute maxsize */
971 maxsize = -1;
972 } else if (PyIndex_Check(maxsize_O)) {
973 maxsize = PyNumber_AsSsize_t(maxsize_O, PyExc_OverflowError);
974 if (maxsize == -1 && PyErr_Occurred())
975 return NULL;
976 if (maxsize == 0)
977 wrapper = uncached_lru_cache_wrapper;
978 else
979 wrapper = bounded_lru_cache_wrapper;
980 } else {
981 PyErr_SetString(PyExc_TypeError, "maxsize should be integer or None");
982 return NULL;
983 }
984
Serhiy Storchaka374164c2015-07-25 12:10:21 +0300985 if (!(cachedict = PyDict_New()))
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300986 return NULL;
987
Serhiy Storchaka374164c2015-07-25 12:10:21 +0300988 obj = (lru_cache_object *)type->tp_alloc(type, 0);
989 if (obj == NULL) {
990 Py_DECREF(cachedict);
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300991 return NULL;
992 }
993
Serhiy Storchaka374164c2015-07-25 12:10:21 +0300994 obj->cache = cachedict;
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300995 obj->root.prev = &obj->root;
996 obj->root.next = &obj->root;
997 obj->maxsize = maxsize;
998 Py_INCREF(maxsize_O);
999 obj->maxsize_O = maxsize_O;
1000 Py_INCREF(func);
1001 obj->func = func;
1002 obj->wrapper = wrapper;
1003 obj->misses = obj->hits = 0;
1004 obj->typed = typed;
1005 Py_INCREF(cache_info_type);
1006 obj->cache_info_type = cache_info_type;
1007
1008 return (PyObject *)obj;
1009}
1010
1011static lru_list_elem *
1012lru_cache_unlink_list(lru_cache_object *self)
1013{
1014 lru_list_elem *root = &self->root;
1015 lru_list_elem *link = root->next;
1016 if (link == root)
1017 return NULL;
1018 root->prev->next = NULL;
1019 root->next = root->prev = root;
1020 return link;
1021}
1022
1023static void
1024lru_cache_clear_list(lru_list_elem *link)
1025{
1026 while (link != NULL) {
1027 lru_list_elem *next = link->next;
1028 Py_DECREF(link);
1029 link = next;
1030 }
1031}
1032
1033static void
1034lru_cache_dealloc(lru_cache_object *obj)
1035{
1036 lru_list_elem *list = lru_cache_unlink_list(obj);
1037 Py_XDECREF(obj->maxsize_O);
1038 Py_XDECREF(obj->func);
1039 Py_XDECREF(obj->cache);
1040 Py_XDECREF(obj->dict);
1041 Py_XDECREF(obj->cache_info_type);
1042 lru_cache_clear_list(list);
1043 Py_TYPE(obj)->tp_free(obj);
1044}
1045
1046static PyObject *
1047lru_cache_call(lru_cache_object *self, PyObject *args, PyObject *kwds)
1048{
1049 return self->wrapper(self, args, kwds);
1050}
1051
1052static PyObject *
Serhiy Storchakae7070f02015-06-08 11:19:24 +03001053lru_cache_descr_get(PyObject *self, PyObject *obj, PyObject *type)
1054{
1055 if (obj == Py_None || obj == NULL) {
1056 Py_INCREF(self);
1057 return self;
1058 }
1059 return PyMethod_New(self, obj);
1060}
1061
1062static PyObject *
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001063lru_cache_cache_info(lru_cache_object *self, PyObject *unused)
1064{
1065 return PyObject_CallFunction(self->cache_info_type, "nnOn",
1066 self->hits, self->misses, self->maxsize_O,
1067 PyDict_Size(self->cache));
1068}
1069
1070static PyObject *
1071lru_cache_cache_clear(lru_cache_object *self, PyObject *unused)
1072{
1073 lru_list_elem *list = lru_cache_unlink_list(self);
1074 self->hits = self->misses = 0;
1075 self->full = 0;
1076 PyDict_Clear(self->cache);
1077 lru_cache_clear_list(list);
1078 Py_RETURN_NONE;
1079}
1080
Serhiy Storchaka45120f22015-10-24 09:49:56 +03001081static PyObject *
1082lru_cache_reduce(PyObject *self, PyObject *unused)
1083{
1084 return PyObject_GetAttrString(self, "__qualname__");
1085}
1086
Serhiy Storchakae4d65e32015-12-28 23:58:07 +02001087static PyObject *
1088lru_cache_copy(PyObject *self, PyObject *unused)
1089{
1090 Py_INCREF(self);
1091 return self;
1092}
1093
1094static PyObject *
1095lru_cache_deepcopy(PyObject *self, PyObject *unused)
1096{
1097 Py_INCREF(self);
1098 return self;
1099}
1100
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001101static int
1102lru_cache_tp_traverse(lru_cache_object *self, visitproc visit, void *arg)
1103{
1104 lru_list_elem *link = self->root.next;
1105 while (link != &self->root) {
1106 lru_list_elem *next = link->next;
1107 Py_VISIT(link);
1108 link = next;
1109 }
1110 Py_VISIT(self->maxsize_O);
1111 Py_VISIT(self->func);
1112 Py_VISIT(self->cache);
1113 Py_VISIT(self->cache_info_type);
1114 Py_VISIT(self->dict);
1115 return 0;
1116}
1117
1118static int
1119lru_cache_tp_clear(lru_cache_object *self)
1120{
1121 lru_list_elem *list = lru_cache_unlink_list(self);
1122 Py_CLEAR(self->maxsize_O);
1123 Py_CLEAR(self->func);
1124 Py_CLEAR(self->cache);
1125 Py_CLEAR(self->cache_info_type);
1126 Py_CLEAR(self->dict);
1127 lru_cache_clear_list(list);
1128 return 0;
1129}
1130
1131
1132PyDoc_STRVAR(lru_cache_doc,
1133"Create a cached callable that wraps another function.\n\
1134\n\
1135user_function: the function being cached\n\
1136\n\
1137maxsize: 0 for no caching\n\
1138 None for unlimited cache size\n\
1139 n for a bounded cache\n\
1140\n\
1141typed: False cache f(3) and f(3.0) as identical calls\n\
1142 True cache f(3) and f(3.0) as distinct calls\n\
1143\n\
1144cache_info_type: namedtuple class with the fields:\n\
1145 hits misses currsize maxsize\n"
1146);
1147
1148static PyMethodDef lru_cache_methods[] = {
1149 {"cache_info", (PyCFunction)lru_cache_cache_info, METH_NOARGS},
1150 {"cache_clear", (PyCFunction)lru_cache_cache_clear, METH_NOARGS},
Serhiy Storchaka45120f22015-10-24 09:49:56 +03001151 {"__reduce__", (PyCFunction)lru_cache_reduce, METH_NOARGS},
Serhiy Storchakae4d65e32015-12-28 23:58:07 +02001152 {"__copy__", (PyCFunction)lru_cache_copy, METH_VARARGS},
1153 {"__deepcopy__", (PyCFunction)lru_cache_deepcopy, METH_VARARGS},
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001154 {NULL}
1155};
1156
1157static PyGetSetDef lru_cache_getsetlist[] = {
1158 {"__dict__", PyObject_GenericGetDict, PyObject_GenericSetDict},
1159 {NULL}
1160};
1161
1162static PyTypeObject lru_cache_type = {
1163 PyVarObject_HEAD_INIT(NULL, 0)
1164 "functools._lru_cache_wrapper", /* tp_name */
1165 sizeof(lru_cache_object), /* tp_basicsize */
1166 0, /* tp_itemsize */
1167 /* methods */
1168 (destructor)lru_cache_dealloc, /* tp_dealloc */
1169 0, /* tp_print */
1170 0, /* tp_getattr */
1171 0, /* tp_setattr */
1172 0, /* tp_reserved */
1173 0, /* tp_repr */
1174 0, /* tp_as_number */
1175 0, /* tp_as_sequence */
1176 0, /* tp_as_mapping */
1177 0, /* tp_hash */
1178 (ternaryfunc)lru_cache_call, /* tp_call */
1179 0, /* tp_str */
1180 0, /* tp_getattro */
1181 0, /* tp_setattro */
1182 0, /* tp_as_buffer */
1183 Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_HAVE_GC,
1184 /* tp_flags */
1185 lru_cache_doc, /* tp_doc */
1186 (traverseproc)lru_cache_tp_traverse,/* tp_traverse */
1187 (inquiry)lru_cache_tp_clear, /* tp_clear */
1188 0, /* tp_richcompare */
1189 0, /* tp_weaklistoffset */
1190 0, /* tp_iter */
1191 0, /* tp_iternext */
1192 lru_cache_methods, /* tp_methods */
1193 0, /* tp_members */
1194 lru_cache_getsetlist, /* tp_getset */
1195 0, /* tp_base */
1196 0, /* tp_dict */
Serhiy Storchakae7070f02015-06-08 11:19:24 +03001197 lru_cache_descr_get, /* tp_descr_get */
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001198 0, /* tp_descr_set */
1199 offsetof(lru_cache_object, dict), /* tp_dictoffset */
1200 0, /* tp_init */
1201 0, /* tp_alloc */
1202 lru_cache_new, /* tp_new */
1203};
1204
Raymond Hettinger9c323f82005-02-28 19:39:44 +00001205/* module level code ********************************************************/
1206
1207PyDoc_STRVAR(module_doc,
Thomas Wouters4d70c3d2006-06-08 14:42:34 +00001208"Tools that operate on functions.");
Raymond Hettinger9c323f82005-02-28 19:39:44 +00001209
1210static PyMethodDef module_methods[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001211 {"reduce", functools_reduce, METH_VARARGS, functools_reduce_doc},
Victor Stinner446c8d52011-04-05 12:21:35 +02001212 {"cmp_to_key", (PyCFunction)functools_cmp_to_key,
1213 METH_VARARGS | METH_KEYWORDS, functools_cmp_to_key_doc},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001214 {NULL, NULL} /* sentinel */
Raymond Hettinger9c323f82005-02-28 19:39:44 +00001215};
1216
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001217static void
1218module_free(void *m)
1219{
1220 Py_CLEAR(kwd_mark);
1221}
Martin v. Löwis1a214512008-06-11 05:26:20 +00001222
1223static struct PyModuleDef _functoolsmodule = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001224 PyModuleDef_HEAD_INIT,
1225 "_functools",
1226 module_doc,
1227 -1,
1228 module_methods,
1229 NULL,
1230 NULL,
1231 NULL,
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001232 module_free,
Martin v. Löwis1a214512008-06-11 05:26:20 +00001233};
1234
Raymond Hettinger9c323f82005-02-28 19:39:44 +00001235PyMODINIT_FUNC
Martin v. Löwis1a214512008-06-11 05:26:20 +00001236PyInit__functools(void)
Raymond Hettinger9c323f82005-02-28 19:39:44 +00001237{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001238 int i;
1239 PyObject *m;
1240 char *name;
1241 PyTypeObject *typelist[] = {
1242 &partial_type,
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001243 &lru_cache_type,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001244 NULL
1245 };
Raymond Hettinger9c323f82005-02-28 19:39:44 +00001246
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001247 m = PyModule_Create(&_functoolsmodule);
1248 if (m == NULL)
1249 return NULL;
Raymond Hettinger9c323f82005-02-28 19:39:44 +00001250
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001251 kwd_mark = PyObject_CallObject((PyObject *)&PyBaseObject_Type, NULL);
1252 if (!kwd_mark) {
1253 Py_DECREF(m);
1254 return NULL;
1255 }
1256
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001257 for (i=0 ; typelist[i] != NULL ; i++) {
1258 if (PyType_Ready(typelist[i]) < 0) {
1259 Py_DECREF(m);
1260 return NULL;
1261 }
1262 name = strchr(typelist[i]->tp_name, '.');
1263 assert (name != NULL);
1264 Py_INCREF(typelist[i]);
1265 PyModule_AddObject(m, name+1, (PyObject *)typelist[i]);
1266 }
1267 return m;
Raymond Hettinger9c323f82005-02-28 19:39:44 +00001268}