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