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