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