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