• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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