1 #include "Python.h"
2 #include "pycore_pymem.h"
3 #include "pycore_pystate.h"
4 #include "pycore_tupleobject.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 = (_PyVectorcall_Function(func) != NULL);
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_ITEMS(pto->args);
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_ITEMS(pto->args),
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_ITEMS(args),
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 = (_PyVectorcall_Function(fn) != NULL);
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_vectorcall_offset */
390 0, /* tp_getattr */
391 0, /* tp_setattr */
392 0, /* tp_as_async */
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_vectorcall_offset */
482 0, /* tp_getattr */
483 0, /* tp_setattr */
484 0, /* tp_as_async */
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 /* Update the args tuple in-place */
630 assert(args->ob_refcnt == 1);
631 Py_XSETREF(_PyTuple_ITEMS(args)[0], result);
632 Py_XSETREF(_PyTuple_ITEMS(args)[1], op2);
633 if ((result = PyObject_Call(func, args, NULL)) == NULL) {
634 goto Fail;
635 }
636 }
637 }
638
639 Py_DECREF(args);
640
641 if (result == NULL)
642 PyErr_SetString(PyExc_TypeError,
643 "reduce() of empty sequence with no initial value");
644
645 Py_DECREF(it);
646 return result;
647
648 Fail:
649 Py_XDECREF(args);
650 Py_XDECREF(result);
651 Py_DECREF(it);
652 return NULL;
653 }
654
655 PyDoc_STRVAR(functools_reduce_doc,
656 "reduce(function, sequence[, initial]) -> value\n\
657 \n\
658 Apply a function of two arguments cumulatively to the items of a sequence,\n\
659 from left to right, so as to reduce the sequence to a single value.\n\
660 For example, reduce(lambda x, y: x+y, [1, 2, 3, 4, 5]) calculates\n\
661 ((((1+2)+3)+4)+5). If initial is present, it is placed before the items\n\
662 of the sequence in the calculation, and serves as a default when the\n\
663 sequence is empty.");
664
665 /* lru_cache object **********************************************************/
666
667 /* There are four principal algorithmic differences from the pure python version:
668
669 1). The C version relies on the GIL instead of having its own reentrant lock.
670
671 2). The prev/next link fields use borrowed references.
672
673 3). For a full cache, the pure python version rotates the location of the
674 root entry so that it never has to move individual links and it can
675 limit updates to just the key and result fields. However, in the C
676 version, links are temporarily removed while the cache dict updates are
677 occurring. Afterwards, they are appended or prepended back into the
678 doubly-linked lists.
679
680 4) In the Python version, the _HashSeq class is used to prevent __hash__
681 from being called more than once. In the C version, the "known hash"
682 variants of dictionary calls as used to the same effect.
683
684 */
685
686
687 /* this object is used delimit args and keywords in the cache keys */
688 static PyObject *kwd_mark = NULL;
689
690 struct lru_list_elem;
691 struct lru_cache_object;
692
693 typedef struct lru_list_elem {
694 PyObject_HEAD
695 struct lru_list_elem *prev, *next; /* borrowed links */
696 Py_hash_t hash;
697 PyObject *key, *result;
698 } lru_list_elem;
699
700 static void
lru_list_elem_dealloc(lru_list_elem * link)701 lru_list_elem_dealloc(lru_list_elem *link)
702 {
703 Py_XDECREF(link->key);
704 Py_XDECREF(link->result);
705 PyObject_Del(link);
706 }
707
708 static PyTypeObject lru_list_elem_type = {
709 PyVarObject_HEAD_INIT(&PyType_Type, 0)
710 "functools._lru_list_elem", /* tp_name */
711 sizeof(lru_list_elem), /* tp_basicsize */
712 0, /* tp_itemsize */
713 /* methods */
714 (destructor)lru_list_elem_dealloc, /* tp_dealloc */
715 0, /* tp_vectorcall_offset */
716 0, /* tp_getattr */
717 0, /* tp_setattr */
718 0, /* tp_as_async */
719 0, /* tp_repr */
720 0, /* tp_as_number */
721 0, /* tp_as_sequence */
722 0, /* tp_as_mapping */
723 0, /* tp_hash */
724 0, /* tp_call */
725 0, /* tp_str */
726 0, /* tp_getattro */
727 0, /* tp_setattro */
728 0, /* tp_as_buffer */
729 Py_TPFLAGS_DEFAULT, /* tp_flags */
730 };
731
732
733 typedef PyObject *(*lru_cache_ternaryfunc)(struct lru_cache_object *, PyObject *, PyObject *);
734
735 typedef struct lru_cache_object {
736 lru_list_elem root; /* includes PyObject_HEAD */
737 lru_cache_ternaryfunc wrapper;
738 int typed;
739 PyObject *cache;
740 Py_ssize_t hits;
741 PyObject *func;
742 Py_ssize_t maxsize;
743 Py_ssize_t misses;
744 PyObject *cache_info_type;
745 PyObject *dict;
746 } lru_cache_object;
747
748 static PyTypeObject lru_cache_type;
749
750 static PyObject *
lru_cache_make_key(PyObject * args,PyObject * kwds,int typed)751 lru_cache_make_key(PyObject *args, PyObject *kwds, int typed)
752 {
753 PyObject *key, *keyword, *value;
754 Py_ssize_t key_size, pos, key_pos, kwds_size;
755
756 kwds_size = kwds ? PyDict_GET_SIZE(kwds) : 0;
757
758 /* short path, key will match args anyway, which is a tuple */
759 if (!typed && !kwds_size) {
760 if (PyTuple_GET_SIZE(args) == 1) {
761 key = PyTuple_GET_ITEM(args, 0);
762 if (PyUnicode_CheckExact(key) || PyLong_CheckExact(key)) {
763 /* For common scalar keys, save space by
764 dropping the enclosing args tuple */
765 Py_INCREF(key);
766 return key;
767 }
768 }
769 Py_INCREF(args);
770 return args;
771 }
772
773 key_size = PyTuple_GET_SIZE(args);
774 if (kwds_size)
775 key_size += kwds_size * 2 + 1;
776 if (typed)
777 key_size += PyTuple_GET_SIZE(args) + kwds_size;
778
779 key = PyTuple_New(key_size);
780 if (key == NULL)
781 return NULL;
782
783 key_pos = 0;
784 for (pos = 0; pos < PyTuple_GET_SIZE(args); ++pos) {
785 PyObject *item = PyTuple_GET_ITEM(args, pos);
786 Py_INCREF(item);
787 PyTuple_SET_ITEM(key, key_pos++, item);
788 }
789 if (kwds_size) {
790 Py_INCREF(kwd_mark);
791 PyTuple_SET_ITEM(key, key_pos++, kwd_mark);
792 for (pos = 0; PyDict_Next(kwds, &pos, &keyword, &value);) {
793 Py_INCREF(keyword);
794 PyTuple_SET_ITEM(key, key_pos++, keyword);
795 Py_INCREF(value);
796 PyTuple_SET_ITEM(key, key_pos++, value);
797 }
798 assert(key_pos == PyTuple_GET_SIZE(args) + kwds_size * 2 + 1);
799 }
800 if (typed) {
801 for (pos = 0; pos < PyTuple_GET_SIZE(args); ++pos) {
802 PyObject *item = (PyObject *)Py_TYPE(PyTuple_GET_ITEM(args, pos));
803 Py_INCREF(item);
804 PyTuple_SET_ITEM(key, key_pos++, item);
805 }
806 if (kwds_size) {
807 for (pos = 0; PyDict_Next(kwds, &pos, &keyword, &value);) {
808 PyObject *item = (PyObject *)Py_TYPE(value);
809 Py_INCREF(item);
810 PyTuple_SET_ITEM(key, key_pos++, item);
811 }
812 }
813 }
814 assert(key_pos == key_size);
815 return key;
816 }
817
818 static PyObject *
uncached_lru_cache_wrapper(lru_cache_object * self,PyObject * args,PyObject * kwds)819 uncached_lru_cache_wrapper(lru_cache_object *self, PyObject *args, PyObject *kwds)
820 {
821 PyObject *result;
822
823 self->misses++;
824 result = PyObject_Call(self->func, args, kwds);
825 if (!result)
826 return NULL;
827 return result;
828 }
829
830 static PyObject *
infinite_lru_cache_wrapper(lru_cache_object * self,PyObject * args,PyObject * kwds)831 infinite_lru_cache_wrapper(lru_cache_object *self, PyObject *args, PyObject *kwds)
832 {
833 PyObject *result;
834 Py_hash_t hash;
835 PyObject *key = lru_cache_make_key(args, kwds, self->typed);
836 if (!key)
837 return NULL;
838 hash = PyObject_Hash(key);
839 if (hash == -1) {
840 Py_DECREF(key);
841 return NULL;
842 }
843 result = _PyDict_GetItem_KnownHash(self->cache, key, hash);
844 if (result) {
845 Py_INCREF(result);
846 self->hits++;
847 Py_DECREF(key);
848 return result;
849 }
850 if (PyErr_Occurred()) {
851 Py_DECREF(key);
852 return NULL;
853 }
854 self->misses++;
855 result = PyObject_Call(self->func, args, kwds);
856 if (!result) {
857 Py_DECREF(key);
858 return NULL;
859 }
860 if (_PyDict_SetItem_KnownHash(self->cache, key, result, hash) < 0) {
861 Py_DECREF(result);
862 Py_DECREF(key);
863 return NULL;
864 }
865 Py_DECREF(key);
866 return result;
867 }
868
869 static void
lru_cache_extract_link(lru_list_elem * link)870 lru_cache_extract_link(lru_list_elem *link)
871 {
872 lru_list_elem *link_prev = link->prev;
873 lru_list_elem *link_next = link->next;
874 link_prev->next = link->next;
875 link_next->prev = link->prev;
876 }
877
878 static void
lru_cache_append_link(lru_cache_object * self,lru_list_elem * link)879 lru_cache_append_link(lru_cache_object *self, lru_list_elem *link)
880 {
881 lru_list_elem *root = &self->root;
882 lru_list_elem *last = root->prev;
883 last->next = root->prev = link;
884 link->prev = last;
885 link->next = root;
886 }
887
888 static void
lru_cache_prepend_link(lru_cache_object * self,lru_list_elem * link)889 lru_cache_prepend_link(lru_cache_object *self, lru_list_elem *link)
890 {
891 lru_list_elem *root = &self->root;
892 lru_list_elem *first = root->next;
893 first->prev = root->next = link;
894 link->prev = root;
895 link->next = first;
896 }
897
898 /* General note on reentrancy:
899
900 There are four dictionary calls in the bounded_lru_cache_wrapper():
901 1) The initial check for a cache match. 2) The post user-function
902 check for a cache match. 3) The deletion of the oldest entry.
903 4) The addition of the newest entry.
904
905 In all four calls, we have a known hash which lets use avoid a call
906 to __hash__(). That leaves only __eq__ as a possible source of a
907 reentrant call.
908
909 The __eq__ method call is always made for a cache hit (dict access #1).
910 Accordingly, we have make sure not modify the cache state prior to
911 this call.
912
913 The __eq__ method call is never made for the deletion (dict access #3)
914 because it is an identity match.
915
916 For the other two accesses (#2 and #4), calls to __eq__ only occur
917 when some other entry happens to have an exactly matching hash (all
918 64-bits). Though rare, this can happen, so we have to make sure to
919 either call it at the top of its code path before any cache
920 state modifications (dict access #2) or be prepared to restore
921 invariants at the end of the code path (dict access #4).
922
923 Another possible source of reentrancy is a decref which can trigger
924 arbitrary code execution. To make the code easier to reason about,
925 the decrefs are deferred to the end of the each possible code path
926 so that we know the cache is a consistent state.
927 */
928
929 static PyObject *
bounded_lru_cache_wrapper(lru_cache_object * self,PyObject * args,PyObject * kwds)930 bounded_lru_cache_wrapper(lru_cache_object *self, PyObject *args, PyObject *kwds)
931 {
932 lru_list_elem *link;
933 PyObject *key, *result, *testresult;
934 Py_hash_t hash;
935
936 key = lru_cache_make_key(args, kwds, self->typed);
937 if (!key)
938 return NULL;
939 hash = PyObject_Hash(key);
940 if (hash == -1) {
941 Py_DECREF(key);
942 return NULL;
943 }
944 link = (lru_list_elem *)_PyDict_GetItem_KnownHash(self->cache, key, hash);
945 if (link != NULL) {
946 lru_cache_extract_link(link);
947 lru_cache_append_link(self, link);
948 result = link->result;
949 self->hits++;
950 Py_INCREF(result);
951 Py_DECREF(key);
952 return result;
953 }
954 if (PyErr_Occurred()) {
955 Py_DECREF(key);
956 return NULL;
957 }
958 self->misses++;
959 result = PyObject_Call(self->func, args, kwds);
960 if (!result) {
961 Py_DECREF(key);
962 return NULL;
963 }
964 testresult = _PyDict_GetItem_KnownHash(self->cache, key, hash);
965 if (testresult != NULL) {
966 /* Getting here means that this same key was added to the cache
967 during the PyObject_Call(). Since the link update is already
968 done, we need only return the computed result. */
969 Py_DECREF(key);
970 return result;
971 }
972 if (PyErr_Occurred()) {
973 /* This is an unusual case since this same lookup
974 did not previously trigger an error during lookup.
975 Treat it the same as an error in user function
976 and return with the error set. */
977 Py_DECREF(key);
978 Py_DECREF(result);
979 return NULL;
980 }
981 /* This is the normal case. The new key wasn't found before
982 user function call and it is still not there. So we
983 proceed normally and update the cache with the new result. */
984
985 assert(self->maxsize > 0);
986 if (PyDict_GET_SIZE(self->cache) < self->maxsize ||
987 self->root.next == &self->root)
988 {
989 /* Cache is not full, so put the result in a new link */
990 link = (lru_list_elem *)PyObject_New(lru_list_elem,
991 &lru_list_elem_type);
992 if (link == NULL) {
993 Py_DECREF(key);
994 Py_DECREF(result);
995 return NULL;
996 }
997
998 link->hash = hash;
999 link->key = key;
1000 link->result = result;
1001 /* What is really needed here is a SetItem variant with a "no clobber"
1002 option. If the __eq__ call triggers a reentrant call that adds
1003 this same key, then this setitem call will update the cache dict
1004 with this new link, leaving the old link as an orphan (i.e. not
1005 having a cache dict entry that refers to it). */
1006 if (_PyDict_SetItem_KnownHash(self->cache, key, (PyObject *)link,
1007 hash) < 0) {
1008 Py_DECREF(link);
1009 return NULL;
1010 }
1011 lru_cache_append_link(self, link);
1012 Py_INCREF(result); /* for return */
1013 return result;
1014 }
1015 /* Since the cache is full, we need to evict an old key and add
1016 a new key. Rather than free the old link and allocate a new
1017 one, we reuse the link for the new key and result and move it
1018 to front of the cache to mark it as recently used.
1019
1020 We try to assure all code paths (including errors) leave all
1021 of the links in place. Either the link is successfully
1022 updated and moved or it is restored to its old position.
1023 However if an unrecoverable error is found, it doesn't
1024 make sense to reinsert the link, so we leave it out
1025 and the cache will no longer register as full.
1026 */
1027 PyObject *oldkey, *oldresult, *popresult;
1028
1029 /* Extract the oldest item. */
1030 assert(self->root.next != &self->root);
1031 link = self->root.next;
1032 lru_cache_extract_link(link);
1033 /* Remove it from the cache.
1034 The cache dict holds one reference to the link.
1035 We created one other reference when the link was created.
1036 The linked list only has borrowed references. */
1037 popresult = _PyDict_Pop_KnownHash(self->cache, link->key,
1038 link->hash, Py_None);
1039 if (popresult == Py_None) {
1040 /* Getting here means that the user function call or another
1041 thread has already removed the old key from the dictionary.
1042 This link is now an orphan. Since we don't want to leave the
1043 cache in an inconsistent state, we don't restore the link. */
1044 Py_DECREF(popresult);
1045 Py_DECREF(link);
1046 Py_DECREF(key);
1047 return result;
1048 }
1049 if (popresult == NULL) {
1050 /* An error arose while trying to remove the oldest key (the one
1051 being evicted) from the cache. We restore the link to its
1052 original position as the oldest link. Then we allow the
1053 error propagate upward; treating it the same as an error
1054 arising in the user function. */
1055 lru_cache_prepend_link(self, link);
1056 Py_DECREF(key);
1057 Py_DECREF(result);
1058 return NULL;
1059 }
1060 /* Keep a reference to the old key and old result to prevent their
1061 ref counts from going to zero during the update. That will
1062 prevent potentially arbitrary object clean-up code (i.e. __del__)
1063 from running while we're still adjusting the links. */
1064 oldkey = link->key;
1065 oldresult = link->result;
1066
1067 link->hash = hash;
1068 link->key = key;
1069 link->result = result;
1070 /* Note: The link is being added to the cache dict without the
1071 prev and next fields set to valid values. We have to wait
1072 for successful insertion in the cache dict before adding the
1073 link to the linked list. Otherwise, the potentially reentrant
1074 __eq__ call could cause the then orphan link to be visited. */
1075 if (_PyDict_SetItem_KnownHash(self->cache, key, (PyObject *)link,
1076 hash) < 0) {
1077 /* Somehow the cache dict update failed. We no longer can
1078 restore the old link. Let the error propagate upward and
1079 leave the cache short one link. */
1080 Py_DECREF(popresult);
1081 Py_DECREF(link);
1082 Py_DECREF(oldkey);
1083 Py_DECREF(oldresult);
1084 return NULL;
1085 }
1086 lru_cache_append_link(self, link);
1087 Py_INCREF(result); /* for return */
1088 Py_DECREF(popresult);
1089 Py_DECREF(oldkey);
1090 Py_DECREF(oldresult);
1091 return result;
1092 }
1093
1094 static PyObject *
lru_cache_new(PyTypeObject * type,PyObject * args,PyObject * kw)1095 lru_cache_new(PyTypeObject *type, PyObject *args, PyObject *kw)
1096 {
1097 PyObject *func, *maxsize_O, *cache_info_type, *cachedict;
1098 int typed;
1099 lru_cache_object *obj;
1100 Py_ssize_t maxsize;
1101 PyObject *(*wrapper)(lru_cache_object *, PyObject *, PyObject *);
1102 static char *keywords[] = {"user_function", "maxsize", "typed",
1103 "cache_info_type", NULL};
1104
1105 if (!PyArg_ParseTupleAndKeywords(args, kw, "OOpO:lru_cache", keywords,
1106 &func, &maxsize_O, &typed,
1107 &cache_info_type)) {
1108 return NULL;
1109 }
1110
1111 if (!PyCallable_Check(func)) {
1112 PyErr_SetString(PyExc_TypeError,
1113 "the first argument must be callable");
1114 return NULL;
1115 }
1116
1117 /* select the caching function, and make/inc maxsize_O */
1118 if (maxsize_O == Py_None) {
1119 wrapper = infinite_lru_cache_wrapper;
1120 /* use this only to initialize lru_cache_object attribute maxsize */
1121 maxsize = -1;
1122 } else if (PyIndex_Check(maxsize_O)) {
1123 maxsize = PyNumber_AsSsize_t(maxsize_O, PyExc_OverflowError);
1124 if (maxsize == -1 && PyErr_Occurred())
1125 return NULL;
1126 if (maxsize < 0) {
1127 maxsize = 0;
1128 }
1129 if (maxsize == 0)
1130 wrapper = uncached_lru_cache_wrapper;
1131 else
1132 wrapper = bounded_lru_cache_wrapper;
1133 } else {
1134 PyErr_SetString(PyExc_TypeError, "maxsize should be integer or None");
1135 return NULL;
1136 }
1137
1138 if (!(cachedict = PyDict_New()))
1139 return NULL;
1140
1141 obj = (lru_cache_object *)type->tp_alloc(type, 0);
1142 if (obj == NULL) {
1143 Py_DECREF(cachedict);
1144 return NULL;
1145 }
1146
1147 obj->root.prev = &obj->root;
1148 obj->root.next = &obj->root;
1149 obj->wrapper = wrapper;
1150 obj->typed = typed;
1151 obj->cache = cachedict;
1152 Py_INCREF(func);
1153 obj->func = func;
1154 obj->misses = obj->hits = 0;
1155 obj->maxsize = maxsize;
1156 Py_INCREF(cache_info_type);
1157 obj->cache_info_type = cache_info_type;
1158 return (PyObject *)obj;
1159 }
1160
1161 static lru_list_elem *
lru_cache_unlink_list(lru_cache_object * self)1162 lru_cache_unlink_list(lru_cache_object *self)
1163 {
1164 lru_list_elem *root = &self->root;
1165 lru_list_elem *link = root->next;
1166 if (link == root)
1167 return NULL;
1168 root->prev->next = NULL;
1169 root->next = root->prev = root;
1170 return link;
1171 }
1172
1173 static void
lru_cache_clear_list(lru_list_elem * link)1174 lru_cache_clear_list(lru_list_elem *link)
1175 {
1176 while (link != NULL) {
1177 lru_list_elem *next = link->next;
1178 Py_DECREF(link);
1179 link = next;
1180 }
1181 }
1182
1183 static void
lru_cache_dealloc(lru_cache_object * obj)1184 lru_cache_dealloc(lru_cache_object *obj)
1185 {
1186 lru_list_elem *list;
1187 /* bpo-31095: UnTrack is needed before calling any callbacks */
1188 PyObject_GC_UnTrack(obj);
1189
1190 list = lru_cache_unlink_list(obj);
1191 Py_XDECREF(obj->cache);
1192 Py_XDECREF(obj->func);
1193 Py_XDECREF(obj->cache_info_type);
1194 Py_XDECREF(obj->dict);
1195 lru_cache_clear_list(list);
1196 Py_TYPE(obj)->tp_free(obj);
1197 }
1198
1199 static PyObject *
lru_cache_call(lru_cache_object * self,PyObject * args,PyObject * kwds)1200 lru_cache_call(lru_cache_object *self, PyObject *args, PyObject *kwds)
1201 {
1202 return self->wrapper(self, args, kwds);
1203 }
1204
1205 static PyObject *
lru_cache_descr_get(PyObject * self,PyObject * obj,PyObject * type)1206 lru_cache_descr_get(PyObject *self, PyObject *obj, PyObject *type)
1207 {
1208 if (obj == Py_None || obj == NULL) {
1209 Py_INCREF(self);
1210 return self;
1211 }
1212 return PyMethod_New(self, obj);
1213 }
1214
1215 static PyObject *
lru_cache_cache_info(lru_cache_object * self,PyObject * unused)1216 lru_cache_cache_info(lru_cache_object *self, PyObject *unused)
1217 {
1218 if (self->maxsize == -1) {
1219 return PyObject_CallFunction(self->cache_info_type, "nnOn",
1220 self->hits, self->misses, Py_None,
1221 PyDict_GET_SIZE(self->cache));
1222 }
1223 return PyObject_CallFunction(self->cache_info_type, "nnnn",
1224 self->hits, self->misses, self->maxsize,
1225 PyDict_GET_SIZE(self->cache));
1226 }
1227
1228 static PyObject *
lru_cache_cache_clear(lru_cache_object * self,PyObject * unused)1229 lru_cache_cache_clear(lru_cache_object *self, PyObject *unused)
1230 {
1231 lru_list_elem *list = lru_cache_unlink_list(self);
1232 self->hits = self->misses = 0;
1233 PyDict_Clear(self->cache);
1234 lru_cache_clear_list(list);
1235 Py_RETURN_NONE;
1236 }
1237
1238 static PyObject *
lru_cache_reduce(PyObject * self,PyObject * unused)1239 lru_cache_reduce(PyObject *self, PyObject *unused)
1240 {
1241 return PyObject_GetAttrString(self, "__qualname__");
1242 }
1243
1244 static PyObject *
lru_cache_copy(PyObject * self,PyObject * unused)1245 lru_cache_copy(PyObject *self, PyObject *unused)
1246 {
1247 Py_INCREF(self);
1248 return self;
1249 }
1250
1251 static PyObject *
lru_cache_deepcopy(PyObject * self,PyObject * unused)1252 lru_cache_deepcopy(PyObject *self, PyObject *unused)
1253 {
1254 Py_INCREF(self);
1255 return self;
1256 }
1257
1258 static int
lru_cache_tp_traverse(lru_cache_object * self,visitproc visit,void * arg)1259 lru_cache_tp_traverse(lru_cache_object *self, visitproc visit, void *arg)
1260 {
1261 lru_list_elem *link = self->root.next;
1262 while (link != &self->root) {
1263 lru_list_elem *next = link->next;
1264 Py_VISIT(link->key);
1265 Py_VISIT(link->result);
1266 link = next;
1267 }
1268 Py_VISIT(self->func);
1269 Py_VISIT(self->cache);
1270 Py_VISIT(self->cache_info_type);
1271 Py_VISIT(self->dict);
1272 return 0;
1273 }
1274
1275 static int
lru_cache_tp_clear(lru_cache_object * self)1276 lru_cache_tp_clear(lru_cache_object *self)
1277 {
1278 lru_list_elem *list = lru_cache_unlink_list(self);
1279 Py_CLEAR(self->func);
1280 Py_CLEAR(self->cache);
1281 Py_CLEAR(self->cache_info_type);
1282 Py_CLEAR(self->dict);
1283 lru_cache_clear_list(list);
1284 return 0;
1285 }
1286
1287
1288 PyDoc_STRVAR(lru_cache_doc,
1289 "Create a cached callable that wraps another function.\n\
1290 \n\
1291 user_function: the function being cached\n\
1292 \n\
1293 maxsize: 0 for no caching\n\
1294 None for unlimited cache size\n\
1295 n for a bounded cache\n\
1296 \n\
1297 typed: False cache f(3) and f(3.0) as identical calls\n\
1298 True cache f(3) and f(3.0) as distinct calls\n\
1299 \n\
1300 cache_info_type: namedtuple class with the fields:\n\
1301 hits misses currsize maxsize\n"
1302 );
1303
1304 static PyMethodDef lru_cache_methods[] = {
1305 {"cache_info", (PyCFunction)lru_cache_cache_info, METH_NOARGS},
1306 {"cache_clear", (PyCFunction)lru_cache_cache_clear, METH_NOARGS},
1307 {"__reduce__", (PyCFunction)lru_cache_reduce, METH_NOARGS},
1308 {"__copy__", (PyCFunction)lru_cache_copy, METH_VARARGS},
1309 {"__deepcopy__", (PyCFunction)lru_cache_deepcopy, METH_VARARGS},
1310 {NULL}
1311 };
1312
1313 static PyGetSetDef lru_cache_getsetlist[] = {
1314 {"__dict__", PyObject_GenericGetDict, PyObject_GenericSetDict},
1315 {NULL}
1316 };
1317
1318 static PyTypeObject lru_cache_type = {
1319 PyVarObject_HEAD_INIT(NULL, 0)
1320 "functools._lru_cache_wrapper", /* tp_name */
1321 sizeof(lru_cache_object), /* tp_basicsize */
1322 0, /* tp_itemsize */
1323 /* methods */
1324 (destructor)lru_cache_dealloc, /* tp_dealloc */
1325 0, /* tp_vectorcall_offset */
1326 0, /* tp_getattr */
1327 0, /* tp_setattr */
1328 0, /* tp_as_async */
1329 0, /* tp_repr */
1330 0, /* tp_as_number */
1331 0, /* tp_as_sequence */
1332 0, /* tp_as_mapping */
1333 0, /* tp_hash */
1334 (ternaryfunc)lru_cache_call, /* tp_call */
1335 0, /* tp_str */
1336 0, /* tp_getattro */
1337 0, /* tp_setattro */
1338 0, /* tp_as_buffer */
1339 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE |
1340 Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_METHOD_DESCRIPTOR,
1341 /* tp_flags */
1342 lru_cache_doc, /* tp_doc */
1343 (traverseproc)lru_cache_tp_traverse,/* tp_traverse */
1344 (inquiry)lru_cache_tp_clear, /* tp_clear */
1345 0, /* tp_richcompare */
1346 0, /* tp_weaklistoffset */
1347 0, /* tp_iter */
1348 0, /* tp_iternext */
1349 lru_cache_methods, /* tp_methods */
1350 0, /* tp_members */
1351 lru_cache_getsetlist, /* tp_getset */
1352 0, /* tp_base */
1353 0, /* tp_dict */
1354 lru_cache_descr_get, /* tp_descr_get */
1355 0, /* tp_descr_set */
1356 offsetof(lru_cache_object, dict), /* tp_dictoffset */
1357 0, /* tp_init */
1358 0, /* tp_alloc */
1359 lru_cache_new, /* tp_new */
1360 };
1361
1362 /* module level code ********************************************************/
1363
1364 PyDoc_STRVAR(module_doc,
1365 "Tools that operate on functions.");
1366
1367 static PyMethodDef module_methods[] = {
1368 {"reduce", functools_reduce, METH_VARARGS, functools_reduce_doc},
1369 {"cmp_to_key", (PyCFunction)(void(*)(void))functools_cmp_to_key,
1370 METH_VARARGS | METH_KEYWORDS, functools_cmp_to_key_doc},
1371 {NULL, NULL} /* sentinel */
1372 };
1373
1374 static void
module_free(void * m)1375 module_free(void *m)
1376 {
1377 Py_CLEAR(kwd_mark);
1378 }
1379
1380 static struct PyModuleDef _functoolsmodule = {
1381 PyModuleDef_HEAD_INIT,
1382 "_functools",
1383 module_doc,
1384 -1,
1385 module_methods,
1386 NULL,
1387 NULL,
1388 NULL,
1389 module_free,
1390 };
1391
1392 PyMODINIT_FUNC
PyInit__functools(void)1393 PyInit__functools(void)
1394 {
1395 int i;
1396 PyObject *m;
1397 const char *name;
1398 PyTypeObject *typelist[] = {
1399 &partial_type,
1400 &lru_cache_type,
1401 NULL
1402 };
1403
1404 m = PyModule_Create(&_functoolsmodule);
1405 if (m == NULL)
1406 return NULL;
1407
1408 kwd_mark = _PyObject_CallNoArg((PyObject *)&PyBaseObject_Type);
1409 if (!kwd_mark) {
1410 Py_DECREF(m);
1411 return NULL;
1412 }
1413
1414 for (i=0 ; typelist[i] != NULL ; i++) {
1415 if (PyType_Ready(typelist[i]) < 0) {
1416 Py_DECREF(m);
1417 return NULL;
1418 }
1419 name = _PyType_Name(typelist[i]);
1420 Py_INCREF(typelist[i]);
1421 PyModule_AddObject(m, name, (PyObject *)typelist[i]);
1422 }
1423 return m;
1424 }
1425