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