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