1
2 #include "Python.h"
3 #include "internal/mem.h"
4 #include "internal/pystate.h"
5 #include "structmember.h"
6
7 /* _functools module written and maintained
8 by Hye-Shik Chang <perky@FreeBSD.org>
9 with adaptations by Raymond Hettinger <python@rcn.com>
10 Copyright (c) 2004, 2005, 2006 Python Software Foundation.
11 All rights reserved.
12 */
13
14 /* partial object **********************************************************/
15
16 typedef struct {
17 PyObject_HEAD
18 PyObject *fn;
19 PyObject *args;
20 PyObject *kw;
21 PyObject *dict;
22 PyObject *weakreflist; /* List of weak references */
23 int use_fastcall;
24 } partialobject;
25
26 static PyTypeObject partial_type;
27
28 static PyObject *
partial_new(PyTypeObject * type,PyObject * args,PyObject * kw)29 partial_new(PyTypeObject *type, PyObject *args, PyObject *kw)
30 {
31 PyObject *func, *pargs, *nargs, *pkw;
32 partialobject *pto;
33
34 if (PyTuple_GET_SIZE(args) < 1) {
35 PyErr_SetString(PyExc_TypeError,
36 "type 'partial' takes at least one argument");
37 return NULL;
38 }
39
40 pargs = pkw = NULL;
41 func = PyTuple_GET_ITEM(args, 0);
42 if (Py_TYPE(func) == &partial_type && type == &partial_type) {
43 partialobject *part = (partialobject *)func;
44 if (part->dict == NULL) {
45 pargs = part->args;
46 pkw = part->kw;
47 func = part->fn;
48 assert(PyTuple_Check(pargs));
49 assert(PyDict_Check(pkw));
50 }
51 }
52 if (!PyCallable_Check(func)) {
53 PyErr_SetString(PyExc_TypeError,
54 "the first argument must be callable");
55 return NULL;
56 }
57
58 /* create partialobject structure */
59 pto = (partialobject *)type->tp_alloc(type, 0);
60 if (pto == NULL)
61 return NULL;
62
63 pto->fn = func;
64 Py_INCREF(func);
65
66 nargs = PyTuple_GetSlice(args, 1, PY_SSIZE_T_MAX);
67 if (nargs == NULL) {
68 Py_DECREF(pto);
69 return NULL;
70 }
71 if (pargs == NULL) {
72 pto->args = nargs;
73 }
74 else {
75 pto->args = PySequence_Concat(pargs, nargs);
76 Py_DECREF(nargs);
77 if (pto->args == NULL) {
78 Py_DECREF(pto);
79 return NULL;
80 }
81 assert(PyTuple_Check(pto->args));
82 }
83
84 if (pkw == NULL || PyDict_GET_SIZE(pkw) == 0) {
85 if (kw == NULL) {
86 pto->kw = PyDict_New();
87 }
88 else if (Py_REFCNT(kw) == 1) {
89 Py_INCREF(kw);
90 pto->kw = kw;
91 }
92 else {
93 pto->kw = PyDict_Copy(kw);
94 }
95 }
96 else {
97 pto->kw = PyDict_Copy(pkw);
98 if (kw != NULL && pto->kw != NULL) {
99 if (PyDict_Merge(pto->kw, kw, 1) != 0) {
100 Py_DECREF(pto);
101 return NULL;
102 }
103 }
104 }
105 if (pto->kw == NULL) {
106 Py_DECREF(pto);
107 return NULL;
108 }
109
110 pto->use_fastcall = _PyObject_HasFastCall(func);
111
112 return (PyObject *)pto;
113 }
114
115 static void
partial_dealloc(partialobject * pto)116 partial_dealloc(partialobject *pto)
117 {
118 /* bpo-31095: UnTrack is needed before calling any callbacks */
119 PyObject_GC_UnTrack(pto);
120 if (pto->weakreflist != NULL)
121 PyObject_ClearWeakRefs((PyObject *) pto);
122 Py_XDECREF(pto->fn);
123 Py_XDECREF(pto->args);
124 Py_XDECREF(pto->kw);
125 Py_XDECREF(pto->dict);
126 Py_TYPE(pto)->tp_free(pto);
127 }
128
129 static PyObject *
partial_fastcall(partialobject * pto,PyObject ** args,Py_ssize_t nargs,PyObject * kwargs)130 partial_fastcall(partialobject *pto, PyObject **args, Py_ssize_t nargs,
131 PyObject *kwargs)
132 {
133 PyObject *small_stack[_PY_FASTCALL_SMALL_STACK];
134 PyObject *ret;
135 PyObject **stack, **stack_buf = NULL;
136 Py_ssize_t nargs2, pto_nargs;
137
138 pto_nargs = PyTuple_GET_SIZE(pto->args);
139 nargs2 = pto_nargs + nargs;
140
141 if (pto_nargs == 0) {
142 stack = args;
143 }
144 else if (nargs == 0) {
145 stack = &PyTuple_GET_ITEM(pto->args, 0);
146 }
147 else {
148 if (nargs2 <= (Py_ssize_t)Py_ARRAY_LENGTH(small_stack)) {
149 stack = small_stack;
150 }
151 else {
152 stack_buf = PyMem_Malloc(nargs2 * sizeof(PyObject *));
153 if (stack_buf == NULL) {
154 PyErr_NoMemory();
155 return NULL;
156 }
157 stack = stack_buf;
158 }
159
160 /* use borrowed references */
161 memcpy(stack,
162 &PyTuple_GET_ITEM(pto->args, 0),
163 pto_nargs * sizeof(PyObject*));
164 memcpy(&stack[pto_nargs],
165 args,
166 nargs * sizeof(PyObject*));
167 }
168
169 ret = _PyObject_FastCallDict(pto->fn, stack, nargs2, kwargs);
170 PyMem_Free(stack_buf);
171 return ret;
172 }
173
174 static PyObject *
partial_call_impl(partialobject * pto,PyObject * args,PyObject * kwargs)175 partial_call_impl(partialobject *pto, PyObject *args, PyObject *kwargs)
176 {
177 PyObject *ret, *args2;
178
179 /* Note: tupleconcat() is optimized for empty tuples */
180 args2 = PySequence_Concat(pto->args, args);
181 if (args2 == NULL) {
182 return NULL;
183 }
184 assert(PyTuple_Check(args2));
185
186 ret = PyObject_Call(pto->fn, args2, kwargs);
187 Py_DECREF(args2);
188 return ret;
189 }
190
191 static PyObject *
partial_call(partialobject * pto,PyObject * args,PyObject * kwargs)192 partial_call(partialobject *pto, PyObject *args, PyObject *kwargs)
193 {
194 PyObject *kwargs2, *res;
195
196 assert (PyCallable_Check(pto->fn));
197 assert (PyTuple_Check(pto->args));
198 assert (PyDict_Check(pto->kw));
199
200 if (PyDict_GET_SIZE(pto->kw) == 0) {
201 /* kwargs can be NULL */
202 kwargs2 = kwargs;
203 Py_XINCREF(kwargs2);
204 }
205 else {
206 /* bpo-27840, bpo-29318: dictionary of keyword parameters must be
207 copied, because a function using "**kwargs" can modify the
208 dictionary. */
209 kwargs2 = PyDict_Copy(pto->kw);
210 if (kwargs2 == NULL) {
211 return NULL;
212 }
213
214 if (kwargs != NULL) {
215 if (PyDict_Merge(kwargs2, kwargs, 1) != 0) {
216 Py_DECREF(kwargs2);
217 return NULL;
218 }
219 }
220 }
221
222
223 if (pto->use_fastcall) {
224 res = partial_fastcall(pto,
225 &PyTuple_GET_ITEM(args, 0),
226 PyTuple_GET_SIZE(args),
227 kwargs2);
228 }
229 else {
230 res = partial_call_impl(pto, args, kwargs2);
231 }
232 Py_XDECREF(kwargs2);
233 return res;
234 }
235
236 static int
partial_traverse(partialobject * pto,visitproc visit,void * arg)237 partial_traverse(partialobject *pto, visitproc visit, void *arg)
238 {
239 Py_VISIT(pto->fn);
240 Py_VISIT(pto->args);
241 Py_VISIT(pto->kw);
242 Py_VISIT(pto->dict);
243 return 0;
244 }
245
246 PyDoc_STRVAR(partial_doc,
247 "partial(func, *args, **keywords) - new function with partial application\n\
248 of the given arguments and keywords.\n");
249
250 #define OFF(x) offsetof(partialobject, x)
251 static PyMemberDef partial_memberlist[] = {
252 {"func", T_OBJECT, OFF(fn), READONLY,
253 "function object to use in future partial calls"},
254 {"args", T_OBJECT, OFF(args), READONLY,
255 "tuple of arguments to future partial calls"},
256 {"keywords", T_OBJECT, OFF(kw), READONLY,
257 "dictionary of keyword arguments to future partial calls"},
258 {NULL} /* Sentinel */
259 };
260
261 static PyGetSetDef partial_getsetlist[] = {
262 {"__dict__", PyObject_GenericGetDict, PyObject_GenericSetDict},
263 {NULL} /* Sentinel */
264 };
265
266 static PyObject *
partial_repr(partialobject * pto)267 partial_repr(partialobject *pto)
268 {
269 PyObject *result = NULL;
270 PyObject *arglist;
271 Py_ssize_t i, n;
272 PyObject *key, *value;
273 int status;
274
275 status = Py_ReprEnter((PyObject *)pto);
276 if (status != 0) {
277 if (status < 0)
278 return NULL;
279 return PyUnicode_FromString("...");
280 }
281
282 arglist = PyUnicode_FromString("");
283 if (arglist == NULL)
284 goto done;
285 /* Pack positional arguments */
286 assert (PyTuple_Check(pto->args));
287 n = PyTuple_GET_SIZE(pto->args);
288 for (i = 0; i < n; i++) {
289 Py_SETREF(arglist, PyUnicode_FromFormat("%U, %R", arglist,
290 PyTuple_GET_ITEM(pto->args, i)));
291 if (arglist == NULL)
292 goto done;
293 }
294 /* Pack keyword arguments */
295 assert (PyDict_Check(pto->kw));
296 for (i = 0; PyDict_Next(pto->kw, &i, &key, &value);) {
297 /* Prevent key.__str__ from deleting the value. */
298 Py_INCREF(value);
299 Py_SETREF(arglist, PyUnicode_FromFormat("%U, %S=%R", arglist,
300 key, value));
301 Py_DECREF(value);
302 if (arglist == NULL)
303 goto done;
304 }
305 result = PyUnicode_FromFormat("%s(%R%U)", Py_TYPE(pto)->tp_name,
306 pto->fn, arglist);
307 Py_DECREF(arglist);
308
309 done:
310 Py_ReprLeave((PyObject *)pto);
311 return result;
312 }
313
314 /* Pickle strategy:
315 __reduce__ by itself doesn't support getting kwargs in the unpickle
316 operation so we define a __setstate__ that replaces all the information
317 about the partial. If we only replaced part of it someone would use
318 it as a hook to do strange things.
319 */
320
321 static PyObject *
partial_reduce(partialobject * pto,PyObject * unused)322 partial_reduce(partialobject *pto, PyObject *unused)
323 {
324 return Py_BuildValue("O(O)(OOOO)", Py_TYPE(pto), pto->fn, pto->fn,
325 pto->args, pto->kw,
326 pto->dict ? pto->dict : Py_None);
327 }
328
329 static PyObject *
partial_setstate(partialobject * pto,PyObject * state)330 partial_setstate(partialobject *pto, PyObject *state)
331 {
332 PyObject *fn, *fnargs, *kw, *dict;
333
334 if (!PyTuple_Check(state) ||
335 !PyArg_ParseTuple(state, "OOOO", &fn, &fnargs, &kw, &dict) ||
336 !PyCallable_Check(fn) ||
337 !PyTuple_Check(fnargs) ||
338 (kw != Py_None && !PyDict_Check(kw)))
339 {
340 PyErr_SetString(PyExc_TypeError, "invalid partial state");
341 return NULL;
342 }
343
344 if(!PyTuple_CheckExact(fnargs))
345 fnargs = PySequence_Tuple(fnargs);
346 else
347 Py_INCREF(fnargs);
348 if (fnargs == NULL)
349 return NULL;
350
351 if (kw == Py_None)
352 kw = PyDict_New();
353 else if(!PyDict_CheckExact(kw))
354 kw = PyDict_Copy(kw);
355 else
356 Py_INCREF(kw);
357 if (kw == NULL) {
358 Py_DECREF(fnargs);
359 return NULL;
360 }
361
362 if (dict == Py_None)
363 dict = NULL;
364 else
365 Py_INCREF(dict);
366
367 Py_INCREF(fn);
368 pto->use_fastcall = _PyObject_HasFastCall(fn);
369 Py_SETREF(pto->fn, fn);
370 Py_SETREF(pto->args, fnargs);
371 Py_SETREF(pto->kw, kw);
372 Py_XSETREF(pto->dict, dict);
373 Py_RETURN_NONE;
374 }
375
376 static PyMethodDef partial_methods[] = {
377 {"__reduce__", (PyCFunction)partial_reduce, METH_NOARGS},
378 {"__setstate__", (PyCFunction)partial_setstate, METH_O},
379 {NULL, NULL} /* sentinel */
380 };
381
382 static PyTypeObject partial_type = {
383 PyVarObject_HEAD_INIT(NULL, 0)
384 "functools.partial", /* tp_name */
385 sizeof(partialobject), /* tp_basicsize */
386 0, /* tp_itemsize */
387 /* methods */
388 (destructor)partial_dealloc, /* tp_dealloc */
389 0, /* tp_print */
390 0, /* tp_getattr */
391 0, /* tp_setattr */
392 0, /* tp_reserved */
393 (reprfunc)partial_repr, /* tp_repr */
394 0, /* tp_as_number */
395 0, /* tp_as_sequence */
396 0, /* tp_as_mapping */
397 0, /* tp_hash */
398 (ternaryfunc)partial_call, /* tp_call */
399 0, /* tp_str */
400 PyObject_GenericGetAttr, /* tp_getattro */
401 PyObject_GenericSetAttr, /* tp_setattro */
402 0, /* tp_as_buffer */
403 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
404 Py_TPFLAGS_BASETYPE, /* tp_flags */
405 partial_doc, /* tp_doc */
406 (traverseproc)partial_traverse, /* tp_traverse */
407 0, /* tp_clear */
408 0, /* tp_richcompare */
409 offsetof(partialobject, weakreflist), /* tp_weaklistoffset */
410 0, /* tp_iter */
411 0, /* tp_iternext */
412 partial_methods, /* tp_methods */
413 partial_memberlist, /* tp_members */
414 partial_getsetlist, /* tp_getset */
415 0, /* tp_base */
416 0, /* tp_dict */
417 0, /* tp_descr_get */
418 0, /* tp_descr_set */
419 offsetof(partialobject, dict), /* tp_dictoffset */
420 0, /* tp_init */
421 0, /* tp_alloc */
422 partial_new, /* tp_new */
423 PyObject_GC_Del, /* tp_free */
424 };
425
426
427 /* cmp_to_key ***************************************************************/
428
429 typedef struct {
430 PyObject_HEAD
431 PyObject *cmp;
432 PyObject *object;
433 } keyobject;
434
435 static void
keyobject_dealloc(keyobject * ko)436 keyobject_dealloc(keyobject *ko)
437 {
438 Py_DECREF(ko->cmp);
439 Py_XDECREF(ko->object);
440 PyObject_FREE(ko);
441 }
442
443 static int
keyobject_traverse(keyobject * ko,visitproc visit,void * arg)444 keyobject_traverse(keyobject *ko, visitproc visit, void *arg)
445 {
446 Py_VISIT(ko->cmp);
447 if (ko->object)
448 Py_VISIT(ko->object);
449 return 0;
450 }
451
452 static int
keyobject_clear(keyobject * ko)453 keyobject_clear(keyobject *ko)
454 {
455 Py_CLEAR(ko->cmp);
456 if (ko->object)
457 Py_CLEAR(ko->object);
458 return 0;
459 }
460
461 static PyMemberDef keyobject_members[] = {
462 {"obj", T_OBJECT,
463 offsetof(keyobject, object), 0,
464 PyDoc_STR("Value wrapped by a key function.")},
465 {NULL}
466 };
467
468 static PyObject *
469 keyobject_call(keyobject *ko, PyObject *args, PyObject *kwds);
470
471 static PyObject *
472 keyobject_richcompare(PyObject *ko, PyObject *other, int op);
473
474 static PyTypeObject keyobject_type = {
475 PyVarObject_HEAD_INIT(&PyType_Type, 0)
476 "functools.KeyWrapper", /* tp_name */
477 sizeof(keyobject), /* tp_basicsize */
478 0, /* tp_itemsize */
479 /* methods */
480 (destructor)keyobject_dealloc, /* tp_dealloc */
481 0, /* tp_print */
482 0, /* tp_getattr */
483 0, /* tp_setattr */
484 0, /* tp_reserved */
485 0, /* tp_repr */
486 0, /* tp_as_number */
487 0, /* tp_as_sequence */
488 0, /* tp_as_mapping */
489 0, /* tp_hash */
490 (ternaryfunc)keyobject_call, /* tp_call */
491 0, /* tp_str */
492 PyObject_GenericGetAttr, /* tp_getattro */
493 0, /* tp_setattro */
494 0, /* tp_as_buffer */
495 Py_TPFLAGS_DEFAULT, /* tp_flags */
496 0, /* tp_doc */
497 (traverseproc)keyobject_traverse, /* tp_traverse */
498 (inquiry)keyobject_clear, /* tp_clear */
499 keyobject_richcompare, /* tp_richcompare */
500 0, /* tp_weaklistoffset */
501 0, /* tp_iter */
502 0, /* tp_iternext */
503 0, /* tp_methods */
504 keyobject_members, /* tp_members */
505 0, /* tp_getset */
506 };
507
508 static PyObject *
keyobject_call(keyobject * ko,PyObject * args,PyObject * kwds)509 keyobject_call(keyobject *ko, PyObject *args, PyObject *kwds)
510 {
511 PyObject *object;
512 keyobject *result;
513 static char *kwargs[] = {"obj", NULL};
514
515 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:K", kwargs, &object))
516 return NULL;
517 result = PyObject_New(keyobject, &keyobject_type);
518 if (!result)
519 return NULL;
520 Py_INCREF(ko->cmp);
521 result->cmp = ko->cmp;
522 Py_INCREF(object);
523 result->object = object;
524 return (PyObject *)result;
525 }
526
527 static PyObject *
keyobject_richcompare(PyObject * ko,PyObject * other,int op)528 keyobject_richcompare(PyObject *ko, PyObject *other, int op)
529 {
530 PyObject *res;
531 PyObject *x;
532 PyObject *y;
533 PyObject *compare;
534 PyObject *answer;
535 PyObject* stack[2];
536
537 if (Py_TYPE(other) != &keyobject_type){
538 PyErr_Format(PyExc_TypeError, "other argument must be K instance");
539 return NULL;
540 }
541 compare = ((keyobject *) ko)->cmp;
542 assert(compare != NULL);
543 x = ((keyobject *) ko)->object;
544 y = ((keyobject *) other)->object;
545 if (!x || !y){
546 PyErr_Format(PyExc_AttributeError, "object");
547 return NULL;
548 }
549
550 /* Call the user's comparison function and translate the 3-way
551 * result into true or false (or error).
552 */
553 stack[0] = x;
554 stack[1] = y;
555 res = _PyObject_FastCall(compare, stack, 2);
556 if (res == NULL) {
557 return NULL;
558 }
559
560 answer = PyObject_RichCompare(res, _PyLong_Zero, op);
561 Py_DECREF(res);
562 return answer;
563 }
564
565 static PyObject *
functools_cmp_to_key(PyObject * self,PyObject * args,PyObject * kwds)566 functools_cmp_to_key(PyObject *self, PyObject *args, PyObject *kwds)
567 {
568 PyObject *cmp;
569 static char *kwargs[] = {"mycmp", NULL};
570 keyobject *object;
571
572 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:cmp_to_key", kwargs, &cmp))
573 return NULL;
574 object = PyObject_New(keyobject, &keyobject_type);
575 if (!object)
576 return NULL;
577 Py_INCREF(cmp);
578 object->cmp = cmp;
579 object->object = NULL;
580 return (PyObject *)object;
581 }
582
583 PyDoc_STRVAR(functools_cmp_to_key_doc,
584 "Convert a cmp= function into a key= function.");
585
586 /* reduce (used to be a builtin) ********************************************/
587
588 static PyObject *
functools_reduce(PyObject * self,PyObject * args)589 functools_reduce(PyObject *self, PyObject *args)
590 {
591 PyObject *seq, *func, *result = NULL, *it;
592
593 if (!PyArg_UnpackTuple(args, "reduce", 2, 3, &func, &seq, &result))
594 return NULL;
595 if (result != NULL)
596 Py_INCREF(result);
597
598 it = PyObject_GetIter(seq);
599 if (it == NULL) {
600 if (PyErr_ExceptionMatches(PyExc_TypeError))
601 PyErr_SetString(PyExc_TypeError,
602 "reduce() arg 2 must support iteration");
603 Py_XDECREF(result);
604 return NULL;
605 }
606
607 if ((args = PyTuple_New(2)) == NULL)
608 goto Fail;
609
610 for (;;) {
611 PyObject *op2;
612
613 if (args->ob_refcnt > 1) {
614 Py_DECREF(args);
615 if ((args = PyTuple_New(2)) == NULL)
616 goto Fail;
617 }
618
619 op2 = PyIter_Next(it);
620 if (op2 == NULL) {
621 if (PyErr_Occurred())
622 goto Fail;
623 break;
624 }
625
626 if (result == NULL)
627 result = op2;
628 else {
629 PyTuple_SetItem(args, 0, result);
630 PyTuple_SetItem(args, 1, op2);
631 if ((result = PyEval_CallObject(func, args)) == NULL)
632 goto Fail;
633 }
634 }
635
636 Py_DECREF(args);
637
638 if (result == NULL)
639 PyErr_SetString(PyExc_TypeError,
640 "reduce() of empty sequence with no initial value");
641
642 Py_DECREF(it);
643 return result;
644
645 Fail:
646 Py_XDECREF(args);
647 Py_XDECREF(result);
648 Py_DECREF(it);
649 return NULL;
650 }
651
652 PyDoc_STRVAR(functools_reduce_doc,
653 "reduce(function, sequence[, initial]) -> value\n\
654 \n\
655 Apply a function of two arguments cumulatively to the items of a sequence,\n\
656 from left to right, so as to reduce the sequence to a single value.\n\
657 For example, reduce(lambda x, y: x+y, [1, 2, 3, 4, 5]) calculates\n\
658 ((((1+2)+3)+4)+5). If initial is present, it is placed before the items\n\
659 of the sequence in the calculation, and serves as a default when the\n\
660 sequence is empty.");
661
662 /* lru_cache object **********************************************************/
663
664 /* There are four principal algorithmic differences from the pure python version:
665
666 1). The C version relies on the GIL instead of having its own reentrant lock.
667
668 2). The prev/next link fields use borrowed references.
669
670 3). For a full cache, the pure python version rotates the location of the
671 root entry so that it never has to move individual links and it can
672 limit updates to just the key and result fields. However, in the C
673 version, links are temporarily removed while the cache dict updates are
674 occurring. Afterwards, they are appended or prepended back into the
675 doubly-linked lists.
676
677 4) In the Python version, the _HashSeq class is used to prevent __hash__
678 from being called more than once. In the C version, the "known hash"
679 variants of dictionary calls as used to the same effect.
680
681 */
682
683
684 /* this object is used delimit args and keywords in the cache keys */
685 static PyObject *kwd_mark = NULL;
686
687 struct lru_list_elem;
688 struct lru_cache_object;
689
690 typedef struct lru_list_elem {
691 PyObject_HEAD
692 struct lru_list_elem *prev, *next; /* borrowed links */
693 Py_hash_t hash;
694 PyObject *key, *result;
695 } lru_list_elem;
696
697 static void
lru_list_elem_dealloc(lru_list_elem * link)698 lru_list_elem_dealloc(lru_list_elem *link)
699 {
700 Py_XDECREF(link->key);
701 Py_XDECREF(link->result);
702 PyObject_Del(link);
703 }
704
705 static PyTypeObject lru_list_elem_type = {
706 PyVarObject_HEAD_INIT(&PyType_Type, 0)
707 "functools._lru_list_elem", /* tp_name */
708 sizeof(lru_list_elem), /* tp_basicsize */
709 0, /* tp_itemsize */
710 /* methods */
711 (destructor)lru_list_elem_dealloc, /* tp_dealloc */
712 0, /* tp_print */
713 0, /* tp_getattr */
714 0, /* tp_setattr */
715 0, /* tp_reserved */
716 0, /* tp_repr */
717 0, /* tp_as_number */
718 0, /* tp_as_sequence */
719 0, /* tp_as_mapping */
720 0, /* tp_hash */
721 0, /* tp_call */
722 0, /* tp_str */
723 0, /* tp_getattro */
724 0, /* tp_setattro */
725 0, /* tp_as_buffer */
726 Py_TPFLAGS_DEFAULT, /* tp_flags */
727 };
728
729
730 typedef PyObject *(*lru_cache_ternaryfunc)(struct lru_cache_object *, PyObject *, PyObject *);
731
732 typedef struct lru_cache_object {
733 lru_list_elem root; /* includes PyObject_HEAD */
734 lru_cache_ternaryfunc wrapper;
735 int typed;
736 PyObject *cache;
737 Py_ssize_t hits;
738 PyObject *func;
739 Py_ssize_t maxsize;
740 Py_ssize_t misses;
741 PyObject *cache_info_type;
742 PyObject *dict;
743 } lru_cache_object;
744
745 static PyTypeObject lru_cache_type;
746
747 static PyObject *
lru_cache_make_key(PyObject * args,PyObject * kwds,int typed)748 lru_cache_make_key(PyObject *args, PyObject *kwds, int typed)
749 {
750 PyObject *key, *keyword, *value;
751 Py_ssize_t key_size, pos, key_pos, kwds_size;
752
753 /* short path, key will match args anyway, which is a tuple */
754 if (!typed && !kwds) {
755 if (PyTuple_GET_SIZE(args) == 1) {
756 key = PyTuple_GET_ITEM(args, 0);
757 if (PyUnicode_CheckExact(key) || PyLong_CheckExact(key)) {
758 /* For common scalar keys, save space by
759 dropping the enclosing args tuple */
760 Py_INCREF(key);
761 return key;
762 }
763 }
764 Py_INCREF(args);
765 return args;
766 }
767
768 kwds_size = kwds ? PyDict_GET_SIZE(kwds) : 0;
769 assert(kwds_size >= 0);
770
771 key_size = PyTuple_GET_SIZE(args);
772 if (kwds_size)
773 key_size += kwds_size * 2 + 1;
774 if (typed)
775 key_size += PyTuple_GET_SIZE(args) + kwds_size;
776
777 key = PyTuple_New(key_size);
778 if (key == NULL)
779 return NULL;
780
781 key_pos = 0;
782 for (pos = 0; pos < PyTuple_GET_SIZE(args); ++pos) {
783 PyObject *item = PyTuple_GET_ITEM(args, pos);
784 Py_INCREF(item);
785 PyTuple_SET_ITEM(key, key_pos++, item);
786 }
787 if (kwds_size) {
788 Py_INCREF(kwd_mark);
789 PyTuple_SET_ITEM(key, key_pos++, kwd_mark);
790 for (pos = 0; PyDict_Next(kwds, &pos, &keyword, &value);) {
791 Py_INCREF(keyword);
792 PyTuple_SET_ITEM(key, key_pos++, keyword);
793 Py_INCREF(value);
794 PyTuple_SET_ITEM(key, key_pos++, value);
795 }
796 assert(key_pos == PyTuple_GET_SIZE(args) + kwds_size * 2 + 1);
797 }
798 if (typed) {
799 for (pos = 0; pos < PyTuple_GET_SIZE(args); ++pos) {
800 PyObject *item = (PyObject *)Py_TYPE(PyTuple_GET_ITEM(args, pos));
801 Py_INCREF(item);
802 PyTuple_SET_ITEM(key, key_pos++, item);
803 }
804 if (kwds_size) {
805 for (pos = 0; PyDict_Next(kwds, &pos, &keyword, &value);) {
806 PyObject *item = (PyObject *)Py_TYPE(value);
807 Py_INCREF(item);
808 PyTuple_SET_ITEM(key, key_pos++, item);
809 }
810 }
811 }
812 assert(key_pos == key_size);
813 return key;
814 }
815
816 static PyObject *
uncached_lru_cache_wrapper(lru_cache_object * self,PyObject * args,PyObject * kwds)817 uncached_lru_cache_wrapper(lru_cache_object *self, PyObject *args, PyObject *kwds)
818 {
819 PyObject *result;
820
821 self->misses++;
822 result = PyObject_Call(self->func, args, kwds);
823 if (!result)
824 return NULL;
825 return result;
826 }
827
828 static PyObject *
infinite_lru_cache_wrapper(lru_cache_object * self,PyObject * args,PyObject * kwds)829 infinite_lru_cache_wrapper(lru_cache_object *self, PyObject *args, PyObject *kwds)
830 {
831 PyObject *result;
832 Py_hash_t hash;
833 PyObject *key = lru_cache_make_key(args, kwds, self->typed);
834 if (!key)
835 return NULL;
836 hash = PyObject_Hash(key);
837 if (hash == -1) {
838 Py_DECREF(key);
839 return NULL;
840 }
841 result = _PyDict_GetItem_KnownHash(self->cache, key, hash);
842 if (result) {
843 Py_INCREF(result);
844 self->hits++;
845 Py_DECREF(key);
846 return result;
847 }
848 if (PyErr_Occurred()) {
849 Py_DECREF(key);
850 return NULL;
851 }
852 self->misses++;
853 result = PyObject_Call(self->func, args, kwds);
854 if (!result) {
855 Py_DECREF(key);
856 return NULL;
857 }
858 if (_PyDict_SetItem_KnownHash(self->cache, key, result, hash) < 0) {
859 Py_DECREF(result);
860 Py_DECREF(key);
861 return NULL;
862 }
863 Py_DECREF(key);
864 return result;
865 }
866
867 static void
lru_cache_extract_link(lru_list_elem * link)868 lru_cache_extract_link(lru_list_elem *link)
869 {
870 lru_list_elem *link_prev = link->prev;
871 lru_list_elem *link_next = link->next;
872 link_prev->next = link->next;
873 link_next->prev = link->prev;
874 }
875
876 static void
lru_cache_append_link(lru_cache_object * self,lru_list_elem * link)877 lru_cache_append_link(lru_cache_object *self, lru_list_elem *link)
878 {
879 lru_list_elem *root = &self->root;
880 lru_list_elem *last = root->prev;
881 last->next = root->prev = link;
882 link->prev = last;
883 link->next = root;
884 }
885
886 static void
lru_cache_prepend_link(lru_cache_object * self,lru_list_elem * link)887 lru_cache_prepend_link(lru_cache_object *self, lru_list_elem *link)
888 {
889 lru_list_elem *root = &self->root;
890 lru_list_elem *first = root->next;
891 first->prev = root->next = link;
892 link->prev = root;
893 link->next = first;
894 }
895
896 /* General note on reentrancy:
897
898 There are four dictionary calls in the bounded_lru_cache_wrapper():
899 1) The initial check for a cache match. 2) The post user-function
900 check for a cache match. 3) The deletion of the oldest entry.
901 4) The addition of the newest entry.
902
903 In all four calls, we have a known hash which lets use avoid a call
904 to __hash__(). That leaves only __eq__ as a possible source of a
905 reentrant call.
906
907 The __eq__ method call is always made for a cache hit (dict access #1).
908 Accordingly, we have make sure not modify the cache state prior to
909 this call.
910
911 The __eq__ method call is never made for the deletion (dict access #3)
912 because it is an identity match.
913
914 For the other two accesses (#2 and #4), calls to __eq__ only occur
915 when some other entry happens to have an exactly matching hash (all
916 64-bits). Though rare, this can happen, so we have to make sure to
917 either call it at the top of its code path before any cache
918 state modifications (dict access #2) or be prepared to restore
919 invariants at the end of the code path (dict access #4).
920
921 Another possible source of reentrancy is a decref which can trigger
922 arbitrary code execution. To make the code easier to reason about,
923 the decrefs are deferred to the end of the each possible code path
924 so that we know the cache is a consistent state.
925 */
926
927 static PyObject *
bounded_lru_cache_wrapper(lru_cache_object * self,PyObject * args,PyObject * kwds)928 bounded_lru_cache_wrapper(lru_cache_object *self, PyObject *args, PyObject *kwds)
929 {
930 lru_list_elem *link;
931 PyObject *key, *result, *testresult;
932 Py_hash_t hash;
933
934 key = lru_cache_make_key(args, kwds, self->typed);
935 if (!key)
936 return NULL;
937 hash = PyObject_Hash(key);
938 if (hash == -1) {
939 Py_DECREF(key);
940 return NULL;
941 }
942 link = (lru_list_elem *)_PyDict_GetItem_KnownHash(self->cache, key, hash);
943 if (link != NULL) {
944 lru_cache_extract_link(link);
945 lru_cache_append_link(self, link);
946 result = link->result;
947 self->hits++;
948 Py_INCREF(result);
949 Py_DECREF(key);
950 return result;
951 }
952 if (PyErr_Occurred()) {
953 Py_DECREF(key);
954 return NULL;
955 }
956 self->misses++;
957 result = PyObject_Call(self->func, args, kwds);
958 if (!result) {
959 Py_DECREF(key);
960 return NULL;
961 }
962 testresult = _PyDict_GetItem_KnownHash(self->cache, key, hash);
963 if (testresult != NULL) {
964 /* Getting here means that this same key was added to the cache
965 during the PyObject_Call(). Since the link update is already
966 done, we need only return the computed result. */
967 Py_DECREF(key);
968 return result;
969 }
970 if (PyErr_Occurred()) {
971 /* This is an unusual case since this same lookup
972 did not previously trigger an error during lookup.
973 Treat it the same as an error in user function
974 and return with the error set. */
975 Py_DECREF(key);
976 Py_DECREF(result);
977 return NULL;
978 }
979 /* This is the normal case. The new key wasn't found before
980 user function call and it is still not there. So we
981 proceed normally and update the cache with the new result. */
982
983 assert(self->maxsize > 0);
984 if (PyDict_GET_SIZE(self->cache) < self->maxsize ||
985 self->root.next == &self->root)
986 {
987 /* Cache is not full, so put the result in a new link */
988 link = (lru_list_elem *)PyObject_New(lru_list_elem,
989 &lru_list_elem_type);
990 if (link == NULL) {
991 Py_DECREF(key);
992 Py_DECREF(result);
993 return NULL;
994 }
995
996 link->hash = hash;
997 link->key = key;
998 link->result = result;
999 /* What is really needed here is a SetItem variant with a "no clobber"
1000 option. If the __eq__ call triggers a reentrant call that adds
1001 this same key, then this setitem call will update the cache dict
1002 with this new link, leaving the old link as an orphan (i.e. not
1003 having a cache dict entry that refers to it). */
1004 if (_PyDict_SetItem_KnownHash(self->cache, key, (PyObject *)link,
1005 hash) < 0) {
1006 Py_DECREF(link);
1007 return NULL;
1008 }
1009 lru_cache_append_link(self, link);
1010 Py_INCREF(result); /* for return */
1011 return result;
1012 }
1013 /* Since the cache is full, we need to evict an old key and add
1014 a new key. Rather than free the old link and allocate a new
1015 one, we reuse the link for the new key and result and move it
1016 to front of the cache to mark it as recently used.
1017
1018 We try to assure all code paths (including errors) leave all
1019 of the links in place. Either the link is successfully
1020 updated and moved or it is restored to its old position.
1021 However if an unrecoverable error is found, it doesn't
1022 make sense to reinsert the link, so we leave it out
1023 and the cache will no longer register as full.
1024 */
1025 PyObject *oldkey, *oldresult, *popresult;
1026
1027 /* Extract the oldest item. */
1028 assert(self->root.next != &self->root);
1029 link = self->root.next;
1030 lru_cache_extract_link(link);
1031 /* Remove it from the cache.
1032 The cache dict holds one reference to the link.
1033 We created one other reference when the link was created.
1034 The linked list only has borrowed references. */
1035 popresult = _PyDict_Pop_KnownHash(self->cache, link->key,
1036 link->hash, Py_None);
1037 if (popresult == Py_None) {
1038 /* Getting here means that the user function call or another
1039 thread has already removed the old key from the dictionary.
1040 This link is now an orphan. Since we don't want to leave the
1041 cache in an inconsistent state, we don't restore the link. */
1042 Py_DECREF(popresult);
1043 Py_DECREF(link);
1044 Py_DECREF(key);
1045 return result;
1046 }
1047 if (popresult == NULL) {
1048 /* An error arose while trying to remove the oldest key (the one
1049 being evicted) from the cache. We restore the link to its
1050 original position as the oldest link. Then we allow the
1051 error propagate upward; treating it the same as an error
1052 arising in the user function. */
1053 lru_cache_prepend_link(self, link);
1054 Py_DECREF(key);
1055 Py_DECREF(result);
1056 return NULL;
1057 }
1058 /* Keep a reference to the old key and old result to prevent their
1059 ref counts from going to zero during the update. That will
1060 prevent potentially arbitrary object clean-up code (i.e. __del__)
1061 from running while we're still adjusting the links. */
1062 oldkey = link->key;
1063 oldresult = link->result;
1064
1065 link->hash = hash;
1066 link->key = key;
1067 link->result = result;
1068 /* Note: The link is being added to the cache dict without the
1069 prev and next fields set to valid values. We have to wait
1070 for successful insertion in the cache dict before adding the
1071 link to the linked list. Otherwise, the potentially reentrant
1072 __eq__ call could cause the then orphan link to be visited. */
1073 if (_PyDict_SetItem_KnownHash(self->cache, key, (PyObject *)link,
1074 hash) < 0) {
1075 /* Somehow the cache dict update failed. We no longer can
1076 restore the old link. Let the error propagate upward and
1077 leave the cache short one link. */
1078 Py_DECREF(popresult);
1079 Py_DECREF(link);
1080 Py_DECREF(oldkey);
1081 Py_DECREF(oldresult);
1082 return NULL;
1083 }
1084 lru_cache_append_link(self, link);
1085 Py_INCREF(result); /* for return */
1086 Py_DECREF(popresult);
1087 Py_DECREF(oldkey);
1088 Py_DECREF(oldresult);
1089 return result;
1090 }
1091
1092 static PyObject *
lru_cache_new(PyTypeObject * type,PyObject * args,PyObject * kw)1093 lru_cache_new(PyTypeObject *type, PyObject *args, PyObject *kw)
1094 {
1095 PyObject *func, *maxsize_O, *cache_info_type, *cachedict;
1096 int typed;
1097 lru_cache_object *obj;
1098 Py_ssize_t maxsize;
1099 PyObject *(*wrapper)(lru_cache_object *, PyObject *, PyObject *);
1100 static char *keywords[] = {"user_function", "maxsize", "typed",
1101 "cache_info_type", NULL};
1102
1103 if (!PyArg_ParseTupleAndKeywords(args, kw, "OOpO:lru_cache", keywords,
1104 &func, &maxsize_O, &typed,
1105 &cache_info_type)) {
1106 return NULL;
1107 }
1108
1109 if (!PyCallable_Check(func)) {
1110 PyErr_SetString(PyExc_TypeError,
1111 "the first argument must be callable");
1112 return NULL;
1113 }
1114
1115 /* select the caching function, and make/inc maxsize_O */
1116 if (maxsize_O == Py_None) {
1117 wrapper = infinite_lru_cache_wrapper;
1118 /* use this only to initialize lru_cache_object attribute maxsize */
1119 maxsize = -1;
1120 } else if (PyIndex_Check(maxsize_O)) {
1121 maxsize = PyNumber_AsSsize_t(maxsize_O, PyExc_OverflowError);
1122 if (maxsize == -1 && PyErr_Occurred())
1123 return NULL;
1124 if (maxsize < 0) {
1125 maxsize = 0;
1126 }
1127 if (maxsize == 0)
1128 wrapper = uncached_lru_cache_wrapper;
1129 else
1130 wrapper = bounded_lru_cache_wrapper;
1131 } else {
1132 PyErr_SetString(PyExc_TypeError, "maxsize should be integer or None");
1133 return NULL;
1134 }
1135
1136 if (!(cachedict = PyDict_New()))
1137 return NULL;
1138
1139 obj = (lru_cache_object *)type->tp_alloc(type, 0);
1140 if (obj == NULL) {
1141 Py_DECREF(cachedict);
1142 return NULL;
1143 }
1144
1145 obj->root.prev = &obj->root;
1146 obj->root.next = &obj->root;
1147 obj->wrapper = wrapper;
1148 obj->typed = typed;
1149 obj->cache = cachedict;
1150 Py_INCREF(func);
1151 obj->func = func;
1152 obj->misses = obj->hits = 0;
1153 obj->maxsize = maxsize;
1154 Py_INCREF(cache_info_type);
1155 obj->cache_info_type = cache_info_type;
1156 return (PyObject *)obj;
1157 }
1158
1159 static lru_list_elem *
lru_cache_unlink_list(lru_cache_object * self)1160 lru_cache_unlink_list(lru_cache_object *self)
1161 {
1162 lru_list_elem *root = &self->root;
1163 lru_list_elem *link = root->next;
1164 if (link == root)
1165 return NULL;
1166 root->prev->next = NULL;
1167 root->next = root->prev = root;
1168 return link;
1169 }
1170
1171 static void
lru_cache_clear_list(lru_list_elem * link)1172 lru_cache_clear_list(lru_list_elem *link)
1173 {
1174 while (link != NULL) {
1175 lru_list_elem *next = link->next;
1176 Py_DECREF(link);
1177 link = next;
1178 }
1179 }
1180
1181 static void
lru_cache_dealloc(lru_cache_object * obj)1182 lru_cache_dealloc(lru_cache_object *obj)
1183 {
1184 lru_list_elem *list;
1185 /* bpo-31095: UnTrack is needed before calling any callbacks */
1186 PyObject_GC_UnTrack(obj);
1187
1188 list = lru_cache_unlink_list(obj);
1189 Py_XDECREF(obj->cache);
1190 Py_XDECREF(obj->func);
1191 Py_XDECREF(obj->cache_info_type);
1192 Py_XDECREF(obj->dict);
1193 lru_cache_clear_list(list);
1194 Py_TYPE(obj)->tp_free(obj);
1195 }
1196
1197 static PyObject *
lru_cache_call(lru_cache_object * self,PyObject * args,PyObject * kwds)1198 lru_cache_call(lru_cache_object *self, PyObject *args, PyObject *kwds)
1199 {
1200 return self->wrapper(self, args, kwds);
1201 }
1202
1203 static PyObject *
lru_cache_descr_get(PyObject * self,PyObject * obj,PyObject * type)1204 lru_cache_descr_get(PyObject *self, PyObject *obj, PyObject *type)
1205 {
1206 if (obj == Py_None || obj == NULL) {
1207 Py_INCREF(self);
1208 return self;
1209 }
1210 return PyMethod_New(self, obj);
1211 }
1212
1213 static PyObject *
lru_cache_cache_info(lru_cache_object * self,PyObject * unused)1214 lru_cache_cache_info(lru_cache_object *self, PyObject *unused)
1215 {
1216 if (self->maxsize == -1) {
1217 return PyObject_CallFunction(self->cache_info_type, "nnOn",
1218 self->hits, self->misses, Py_None,
1219 PyDict_GET_SIZE(self->cache));
1220 }
1221 return PyObject_CallFunction(self->cache_info_type, "nnnn",
1222 self->hits, self->misses, self->maxsize,
1223 PyDict_GET_SIZE(self->cache));
1224 }
1225
1226 static PyObject *
lru_cache_cache_clear(lru_cache_object * self,PyObject * unused)1227 lru_cache_cache_clear(lru_cache_object *self, PyObject *unused)
1228 {
1229 lru_list_elem *list = lru_cache_unlink_list(self);
1230 self->hits = self->misses = 0;
1231 PyDict_Clear(self->cache);
1232 lru_cache_clear_list(list);
1233 Py_RETURN_NONE;
1234 }
1235
1236 static PyObject *
lru_cache_reduce(PyObject * self,PyObject * unused)1237 lru_cache_reduce(PyObject *self, PyObject *unused)
1238 {
1239 return PyObject_GetAttrString(self, "__qualname__");
1240 }
1241
1242 static PyObject *
lru_cache_copy(PyObject * self,PyObject * unused)1243 lru_cache_copy(PyObject *self, PyObject *unused)
1244 {
1245 Py_INCREF(self);
1246 return self;
1247 }
1248
1249 static PyObject *
lru_cache_deepcopy(PyObject * self,PyObject * unused)1250 lru_cache_deepcopy(PyObject *self, PyObject *unused)
1251 {
1252 Py_INCREF(self);
1253 return self;
1254 }
1255
1256 static int
lru_cache_tp_traverse(lru_cache_object * self,visitproc visit,void * arg)1257 lru_cache_tp_traverse(lru_cache_object *self, visitproc visit, void *arg)
1258 {
1259 lru_list_elem *link = self->root.next;
1260 while (link != &self->root) {
1261 lru_list_elem *next = link->next;
1262 Py_VISIT(link->key);
1263 Py_VISIT(link->result);
1264 link = next;
1265 }
1266 Py_VISIT(self->func);
1267 Py_VISIT(self->cache);
1268 Py_VISIT(self->cache_info_type);
1269 Py_VISIT(self->dict);
1270 return 0;
1271 }
1272
1273 static int
lru_cache_tp_clear(lru_cache_object * self)1274 lru_cache_tp_clear(lru_cache_object *self)
1275 {
1276 lru_list_elem *list = lru_cache_unlink_list(self);
1277 Py_CLEAR(self->func);
1278 Py_CLEAR(self->cache);
1279 Py_CLEAR(self->cache_info_type);
1280 Py_CLEAR(self->dict);
1281 lru_cache_clear_list(list);
1282 return 0;
1283 }
1284
1285
1286 PyDoc_STRVAR(lru_cache_doc,
1287 "Create a cached callable that wraps another function.\n\
1288 \n\
1289 user_function: the function being cached\n\
1290 \n\
1291 maxsize: 0 for no caching\n\
1292 None for unlimited cache size\n\
1293 n for a bounded cache\n\
1294 \n\
1295 typed: False cache f(3) and f(3.0) as identical calls\n\
1296 True cache f(3) and f(3.0) as distinct calls\n\
1297 \n\
1298 cache_info_type: namedtuple class with the fields:\n\
1299 hits misses currsize maxsize\n"
1300 );
1301
1302 static PyMethodDef lru_cache_methods[] = {
1303 {"cache_info", (PyCFunction)lru_cache_cache_info, METH_NOARGS},
1304 {"cache_clear", (PyCFunction)lru_cache_cache_clear, METH_NOARGS},
1305 {"__reduce__", (PyCFunction)lru_cache_reduce, METH_NOARGS},
1306 {"__copy__", (PyCFunction)lru_cache_copy, METH_VARARGS},
1307 {"__deepcopy__", (PyCFunction)lru_cache_deepcopy, METH_VARARGS},
1308 {NULL}
1309 };
1310
1311 static PyGetSetDef lru_cache_getsetlist[] = {
1312 {"__dict__", PyObject_GenericGetDict, PyObject_GenericSetDict},
1313 {NULL}
1314 };
1315
1316 static PyTypeObject lru_cache_type = {
1317 PyVarObject_HEAD_INIT(NULL, 0)
1318 "functools._lru_cache_wrapper", /* tp_name */
1319 sizeof(lru_cache_object), /* tp_basicsize */
1320 0, /* tp_itemsize */
1321 /* methods */
1322 (destructor)lru_cache_dealloc, /* tp_dealloc */
1323 0, /* tp_print */
1324 0, /* tp_getattr */
1325 0, /* tp_setattr */
1326 0, /* tp_reserved */
1327 0, /* tp_repr */
1328 0, /* tp_as_number */
1329 0, /* tp_as_sequence */
1330 0, /* tp_as_mapping */
1331 0, /* tp_hash */
1332 (ternaryfunc)lru_cache_call, /* tp_call */
1333 0, /* tp_str */
1334 0, /* tp_getattro */
1335 0, /* tp_setattro */
1336 0, /* tp_as_buffer */
1337 Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_HAVE_GC,
1338 /* tp_flags */
1339 lru_cache_doc, /* tp_doc */
1340 (traverseproc)lru_cache_tp_traverse,/* tp_traverse */
1341 (inquiry)lru_cache_tp_clear, /* tp_clear */
1342 0, /* tp_richcompare */
1343 0, /* tp_weaklistoffset */
1344 0, /* tp_iter */
1345 0, /* tp_iternext */
1346 lru_cache_methods, /* tp_methods */
1347 0, /* tp_members */
1348 lru_cache_getsetlist, /* tp_getset */
1349 0, /* tp_base */
1350 0, /* tp_dict */
1351 lru_cache_descr_get, /* tp_descr_get */
1352 0, /* tp_descr_set */
1353 offsetof(lru_cache_object, dict), /* tp_dictoffset */
1354 0, /* tp_init */
1355 0, /* tp_alloc */
1356 lru_cache_new, /* tp_new */
1357 };
1358
1359 /* module level code ********************************************************/
1360
1361 PyDoc_STRVAR(module_doc,
1362 "Tools that operate on functions.");
1363
1364 static PyMethodDef module_methods[] = {
1365 {"reduce", functools_reduce, METH_VARARGS, functools_reduce_doc},
1366 {"cmp_to_key", (PyCFunction)functools_cmp_to_key,
1367 METH_VARARGS | METH_KEYWORDS, functools_cmp_to_key_doc},
1368 {NULL, NULL} /* sentinel */
1369 };
1370
1371 static void
module_free(void * m)1372 module_free(void *m)
1373 {
1374 Py_CLEAR(kwd_mark);
1375 }
1376
1377 static struct PyModuleDef _functoolsmodule = {
1378 PyModuleDef_HEAD_INIT,
1379 "_functools",
1380 module_doc,
1381 -1,
1382 module_methods,
1383 NULL,
1384 NULL,
1385 NULL,
1386 module_free,
1387 };
1388
1389 PyMODINIT_FUNC
PyInit__functools(void)1390 PyInit__functools(void)
1391 {
1392 int i;
1393 PyObject *m;
1394 const char *name;
1395 PyTypeObject *typelist[] = {
1396 &partial_type,
1397 &lru_cache_type,
1398 NULL
1399 };
1400
1401 m = PyModule_Create(&_functoolsmodule);
1402 if (m == NULL)
1403 return NULL;
1404
1405 kwd_mark = _PyObject_CallNoArg((PyObject *)&PyBaseObject_Type);
1406 if (!kwd_mark) {
1407 Py_DECREF(m);
1408 return NULL;
1409 }
1410
1411 for (i=0 ; typelist[i] != NULL ; i++) {
1412 if (PyType_Ready(typelist[i]) < 0) {
1413 Py_DECREF(m);
1414 return NULL;
1415 }
1416 name = _PyType_Name(typelist[i]);
1417 Py_INCREF(typelist[i]);
1418 PyModule_AddObject(m, name, (PyObject *)typelist[i]);
1419 }
1420 return m;
1421 }
1422