blob: f3ae3b62ae332c54a321afd633bd3b7c247d4768 [file] [log] [blame]
Raymond Hettinger9c323f82005-02-28 19:39:44 +00001#include "Python.h"
Victor Stinner37834132020-10-27 17:12:53 +01002#include "pycore_long.h" // _PyLong_GetZero()
Brandt Bucher226a0122020-12-04 19:45:57 -08003#include "pycore_object.h" // _PyObject_GC_TRACK
Victor Stinner4a21e572020-04-15 02:35:41 +02004#include "pycore_pystate.h" // _PyThreadState_GET()
Victor Stinner384621c2020-06-22 17:27:35 +02005#include "pycore_tuple.h" // _PyTuple_ITEMS()
Victor Stinner4a21e572020-04-15 02:35:41 +02006#include "structmember.h" // PyMemberDef
Raymond Hettinger9c323f82005-02-28 19:39:44 +00007
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00008/* _functools module written and maintained
Raymond Hettinger9c323f82005-02-28 19:39:44 +00009 by Hye-Shik Chang <perky@FreeBSD.org>
10 with adaptations by Raymond Hettinger <python@rcn.com>
Thomas Wouters4d70c3d2006-06-08 14:42:34 +000011 Copyright (c) 2004, 2005, 2006 Python Software Foundation.
Raymond Hettinger9c323f82005-02-28 19:39:44 +000012 All rights reserved.
13*/
14
Hai Shidd391232020-12-29 20:45:07 +080015typedef struct _functools_state {
16 /* this object is used delimit args and keywords in the cache keys */
17 PyObject *kwd_mark;
18 PyTypeObject *partial_type;
19 PyTypeObject *keyobject_type;
20 PyTypeObject *lru_list_elem_type;
21} _functools_state;
22
23static inline _functools_state *
24get_functools_state(PyObject *module)
25{
26 void *state = PyModule_GetState(module);
27 assert(state != NULL);
28 return (_functools_state *)state;
29}
Raymond Hettinger9c323f82005-02-28 19:39:44 +000030
Raymond Hettinger139c2322021-04-21 15:22:22 -070031
32/* partial object **********************************************************/
33
34typedef struct {
35 PyObject_HEAD
36 PyObject *fn;
37 PyObject *args;
38 PyObject *kw;
39 PyObject *dict; /* __dict__ */
40 PyObject *weakreflist; /* List of weak references */
41 vectorcallfunc vectorcall;
42} partialobject;
43
Jeroen Demeyered184c02019-07-13 16:39:18 +020044static void partial_setvectorcall(partialobject *pto);
Hai Shidd391232020-12-29 20:45:07 +080045static struct PyModuleDef _functools_module;
46static PyObject *
47partial_call(partialobject *pto, PyObject *args, PyObject *kwargs);
48
49static inline _functools_state *
50get_functools_state_by_type(PyTypeObject *type)
51{
52 PyObject *module = _PyType_GetModuleByDef(type, &_functools_module);
53 if (module == NULL) {
54 return NULL;
55 }
56 _functools_state *state = get_functools_state(module);
57 return state;
58}
Jeroen Demeyered184c02019-07-13 16:39:18 +020059
Raymond Hettinger9c323f82005-02-28 19:39:44 +000060static PyObject *
61partial_new(PyTypeObject *type, PyObject *args, PyObject *kw)
62{
Alexander Belopolskye49af342015-03-01 15:08:17 -050063 PyObject *func, *pargs, *nargs, *pkw;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000064 partialobject *pto;
Raymond Hettinger9c323f82005-02-28 19:39:44 +000065
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000066 if (PyTuple_GET_SIZE(args) < 1) {
67 PyErr_SetString(PyExc_TypeError,
68 "type 'partial' takes at least one argument");
69 return NULL;
70 }
Raymond Hettinger9c323f82005-02-28 19:39:44 +000071
Serhiy Storchaka38741282016-02-02 18:45:17 +020072 pargs = pkw = NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000073 func = PyTuple_GET_ITEM(args, 0);
Hai Shidd391232020-12-29 20:45:07 +080074 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.
Alexander Belopolskye49af342015-03-01 15:08:17 -050079 partialobject *part = (partialobject *)func;
80 if (part->dict == NULL) {
81 pargs = part->args;
82 pkw = part->kw;
83 func = part->fn;
Serhiy Storchaka38741282016-02-02 18:45:17 +020084 assert(PyTuple_Check(pargs));
85 assert(PyDict_Check(pkw));
Alexander Belopolskye49af342015-03-01 15:08:17 -050086 }
87 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000088 if (!PyCallable_Check(func)) {
89 PyErr_SetString(PyExc_TypeError,
90 "the first argument must be callable");
91 return NULL;
92 }
Raymond Hettinger9c323f82005-02-28 19:39:44 +000093
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000094 /* create partialobject structure */
95 pto = (partialobject *)type->tp_alloc(type, 0);
96 if (pto == NULL)
97 return NULL;
Raymond Hettinger9c323f82005-02-28 19:39:44 +000098
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000099 pto->fn = func;
100 Py_INCREF(func);
Alexander Belopolskye49af342015-03-01 15:08:17 -0500101
102 nargs = PyTuple_GetSlice(args, 1, PY_SSIZE_T_MAX);
103 if (nargs == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000104 Py_DECREF(pto);
105 return NULL;
106 }
Serhiy Storchaka3c749fc2017-03-25 12:10:16 +0200107 if (pargs == NULL) {
Alexander Belopolskye49af342015-03-01 15:08:17 -0500108 pto->args = nargs;
Alexander Belopolskye49af342015-03-01 15:08:17 -0500109 }
110 else {
111 pto->args = PySequence_Concat(pargs, nargs);
Serhiy Storchaka3c749fc2017-03-25 12:10:16 +0200112 Py_DECREF(nargs);
Alexander Belopolskye49af342015-03-01 15:08:17 -0500113 if (pto->args == NULL) {
Alexander Belopolskye49af342015-03-01 15:08:17 -0500114 Py_DECREF(pto);
115 return NULL;
116 }
Serhiy Storchaka38741282016-02-02 18:45:17 +0200117 assert(PyTuple_Check(pto->args));
Alexander Belopolskye49af342015-03-01 15:08:17 -0500118 }
Alexander Belopolskye49af342015-03-01 15:08:17 -0500119
Serhiy Storchaka5ab81d72016-12-16 16:18:57 +0200120 if (pkw == NULL || PyDict_GET_SIZE(pkw) == 0) {
Serhiy Storchaka38741282016-02-02 18:45:17 +0200121 if (kw == NULL) {
122 pto->kw = PyDict_New();
Alexander Belopolskye49af342015-03-01 15:08:17 -0500123 }
Serhiy Storchaka9639e4a2017-02-20 14:04:30 +0200124 else if (Py_REFCNT(kw) == 1) {
Serhiy Storchaka38741282016-02-02 18:45:17 +0200125 Py_INCREF(kw);
126 pto->kw = kw;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000127 }
Serhiy Storchaka9639e4a2017-02-20 14:04:30 +0200128 else {
129 pto->kw = PyDict_Copy(kw);
130 }
Alexander Belopolskye49af342015-03-01 15:08:17 -0500131 }
132 else {
Serhiy Storchaka38741282016-02-02 18:45:17 +0200133 pto->kw = PyDict_Copy(pkw);
134 if (kw != NULL && pto->kw != NULL) {
135 if (PyDict_Merge(pto->kw, kw, 1) != 0) {
Benjamin Petersondae2ef12015-05-09 00:29:08 -0400136 Py_DECREF(pto);
137 return NULL;
138 }
139 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000140 }
Serhiy Storchaka38741282016-02-02 18:45:17 +0200141 if (pto->kw == NULL) {
142 Py_DECREF(pto);
143 return NULL;
144 }
Raymond Hettingerc8b6d1b2005-03-08 06:14:50 +0000145
Jeroen Demeyered184c02019-07-13 16:39:18 +0200146 partial_setvectorcall(pto);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000147 return (PyObject *)pto;
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000148}
149
150static void
151partial_dealloc(partialobject *pto)
152{
Hai Shidd391232020-12-29 20:45:07 +0800153 PyTypeObject *tp = Py_TYPE(pto);
INADA Naokia6296d32017-08-24 14:55:17 +0900154 /* bpo-31095: UnTrack is needed before calling any callbacks */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000155 PyObject_GC_UnTrack(pto);
156 if (pto->weakreflist != NULL)
157 PyObject_ClearWeakRefs((PyObject *) pto);
158 Py_XDECREF(pto->fn);
159 Py_XDECREF(pto->args);
160 Py_XDECREF(pto->kw);
161 Py_XDECREF(pto->dict);
Hai Shidd391232020-12-29 20:45:07 +0800162 tp->tp_free(pto);
163 Py_DECREF(tp);
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000164}
165
Jeroen Demeyered184c02019-07-13 16:39:18 +0200166
167/* Merging keyword arguments using the vectorcall convention is messy, so
168 * if we would need to do that, we stop using vectorcall and fall back
169 * to using partial_call() instead. */
170_Py_NO_INLINE static PyObject *
Victor Stinner7e433732019-11-08 10:05:17 +0100171partial_vectorcall_fallback(PyThreadState *tstate, partialobject *pto,
172 PyObject *const *args, size_t nargsf,
173 PyObject *kwnames)
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000174{
Jeroen Demeyered184c02019-07-13 16:39:18 +0200175 pto->vectorcall = NULL;
176 Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
Victor Stinner7e433732019-11-08 10:05:17 +0100177 return _PyObject_MakeTpCall(tstate, (PyObject *)pto,
178 args, nargs, kwnames);
Jeroen Demeyered184c02019-07-13 16:39:18 +0200179}
180
181static PyObject *
182partial_vectorcall(partialobject *pto, PyObject *const *args,
183 size_t nargsf, PyObject *kwnames)
184{
Victor Stinner7e433732019-11-08 10:05:17 +0100185 PyThreadState *tstate = _PyThreadState_GET();
186
Jeroen Demeyered184c02019-07-13 16:39:18 +0200187 /* pto->kw is mutable, so need to check every time */
188 if (PyDict_GET_SIZE(pto->kw)) {
Victor Stinner7e433732019-11-08 10:05:17 +0100189 return partial_vectorcall_fallback(tstate, pto, args, nargsf, kwnames);
Jeroen Demeyered184c02019-07-13 16:39:18 +0200190 }
191
192 Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
193 Py_ssize_t nargs_total = nargs;
194 if (kwnames != NULL) {
195 nargs_total += PyTuple_GET_SIZE(kwnames);
196 }
197
198 PyObject **pto_args = _PyTuple_ITEMS(pto->args);
199 Py_ssize_t pto_nargs = PyTuple_GET_SIZE(pto->args);
200
201 /* Fast path if we're called without arguments */
202 if (nargs_total == 0) {
Victor Stinner7e433732019-11-08 10:05:17 +0100203 return _PyObject_VectorcallTstate(tstate, pto->fn,
204 pto_args, pto_nargs, NULL);
Jeroen Demeyered184c02019-07-13 16:39:18 +0200205 }
206
207 /* Fast path using PY_VECTORCALL_ARGUMENTS_OFFSET to prepend a single
208 * positional argument */
209 if (pto_nargs == 1 && (nargsf & PY_VECTORCALL_ARGUMENTS_OFFSET)) {
210 PyObject **newargs = (PyObject **)args - 1;
211 PyObject *tmp = newargs[0];
212 newargs[0] = pto_args[0];
Victor Stinner7e433732019-11-08 10:05:17 +0100213 PyObject *ret = _PyObject_VectorcallTstate(tstate, pto->fn,
214 newargs, nargs + 1, kwnames);
Jeroen Demeyered184c02019-07-13 16:39:18 +0200215 newargs[0] = tmp;
216 return ret;
217 }
218
219 Py_ssize_t newnargs_total = pto_nargs + nargs_total;
220
Victor Stinner0f7b0b32017-03-14 21:37:20 +0100221 PyObject *small_stack[_PY_FASTCALL_SMALL_STACK];
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000222 PyObject *ret;
Jeroen Demeyered184c02019-07-13 16:39:18 +0200223 PyObject **stack;
Victor Stinner0f7b0b32017-03-14 21:37:20 +0100224
Jeroen Demeyered184c02019-07-13 16:39:18 +0200225 if (newnargs_total <= (Py_ssize_t)Py_ARRAY_LENGTH(small_stack)) {
226 stack = small_stack;
Victor Stinner0f7b0b32017-03-14 21:37:20 +0100227 }
228 else {
Jeroen Demeyered184c02019-07-13 16:39:18 +0200229 stack = PyMem_Malloc(newnargs_total * sizeof(PyObject *));
230 if (stack == NULL) {
231 PyErr_NoMemory();
232 return NULL;
Victor Stinner0f7b0b32017-03-14 21:37:20 +0100233 }
Victor Stinner0f7b0b32017-03-14 21:37:20 +0100234 }
235
Jeroen Demeyered184c02019-07-13 16:39:18 +0200236 /* Copy to new stack, using borrowed references */
237 memcpy(stack, pto_args, pto_nargs * sizeof(PyObject*));
238 memcpy(stack + pto_nargs, args, nargs_total * sizeof(PyObject*));
239
Victor Stinner7e433732019-11-08 10:05:17 +0100240 ret = _PyObject_VectorcallTstate(tstate, pto->fn,
241 stack, pto_nargs + nargs, kwnames);
Jeroen Demeyered184c02019-07-13 16:39:18 +0200242 if (stack != small_stack) {
243 PyMem_Free(stack);
244 }
Victor Stinner0f7b0b32017-03-14 21:37:20 +0100245 return ret;
246}
247
Jeroen Demeyered184c02019-07-13 16:39:18 +0200248/* Set pto->vectorcall depending on the parameters of the partial object */
249static void
250partial_setvectorcall(partialobject *pto)
Victor Stinner0f7b0b32017-03-14 21:37:20 +0100251{
Petr Viktorinffd97532020-02-11 17:46:57 +0100252 if (PyVectorcall_Function(pto->fn) == NULL) {
Jeroen Demeyered184c02019-07-13 16:39:18 +0200253 /* Don't use vectorcall if the underlying function doesn't support it */
254 pto->vectorcall = NULL;
Victor Stinner0f7b0b32017-03-14 21:37:20 +0100255 }
Jeroen Demeyered184c02019-07-13 16:39:18 +0200256 /* We could have a special case if there are no arguments,
257 * but that is unlikely (why use partial without arguments?),
258 * so we don't optimize that */
259 else {
260 pto->vectorcall = (vectorcallfunc)partial_vectorcall;
261 }
Victor Stinner0f7b0b32017-03-14 21:37:20 +0100262}
263
Jeroen Demeyered184c02019-07-13 16:39:18 +0200264
Victor Stinner0f7b0b32017-03-14 21:37:20 +0100265static PyObject *
266partial_call(partialobject *pto, PyObject *args, PyObject *kwargs)
267{
Jeroen Demeyered184c02019-07-13 16:39:18 +0200268 assert(PyCallable_Check(pto->fn));
269 assert(PyTuple_Check(pto->args));
270 assert(PyDict_Check(pto->kw));
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000271
Jeroen Demeyered184c02019-07-13 16:39:18 +0200272 /* Merge keywords */
273 PyObject *kwargs2;
Serhiy Storchaka5ab81d72016-12-16 16:18:57 +0200274 if (PyDict_GET_SIZE(pto->kw) == 0) {
Victor Stinner0f7b0b32017-03-14 21:37:20 +0100275 /* kwargs can be NULL */
276 kwargs2 = kwargs;
277 Py_XINCREF(kwargs2);
Victor Stinnerf4d28d42016-08-23 16:22:35 +0200278 }
279 else {
Victor Stinner561ca802017-02-23 18:26:43 +0100280 /* bpo-27840, bpo-29318: dictionary of keyword parameters must be
281 copied, because a function using "**kwargs" can modify the
282 dictionary. */
Victor Stinner0f7b0b32017-03-14 21:37:20 +0100283 kwargs2 = PyDict_Copy(pto->kw);
284 if (kwargs2 == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000285 return NULL;
286 }
Victor Stinnerf4d28d42016-08-23 16:22:35 +0200287
Victor Stinner0f7b0b32017-03-14 21:37:20 +0100288 if (kwargs != NULL) {
289 if (PyDict_Merge(kwargs2, kwargs, 1) != 0) {
290 Py_DECREF(kwargs2);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000291 return NULL;
292 }
293 }
294 }
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000295
Jeroen Demeyered184c02019-07-13 16:39:18 +0200296 /* Merge positional arguments */
297 /* Note: tupleconcat() is optimized for empty tuples */
298 PyObject *args2 = PySequence_Concat(pto->args, args);
299 if (args2 == NULL) {
300 Py_XDECREF(kwargs2);
301 return NULL;
302 }
Victor Stinner0f7b0b32017-03-14 21:37:20 +0100303
Jeroen Demeyered184c02019-07-13 16:39:18 +0200304 PyObject *res = PyObject_Call(pto->fn, args2, kwargs2);
305 Py_DECREF(args2);
Victor Stinner0f7b0b32017-03-14 21:37:20 +0100306 Py_XDECREF(kwargs2);
307 return res;
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000308}
309
310static int
311partial_traverse(partialobject *pto, visitproc visit, void *arg)
312{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000313 Py_VISIT(pto->fn);
314 Py_VISIT(pto->args);
315 Py_VISIT(pto->kw);
316 Py_VISIT(pto->dict);
317 return 0;
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000318}
319
320PyDoc_STRVAR(partial_doc,
321"partial(func, *args, **keywords) - new function with partial application\n\
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000322 of the given arguments and keywords.\n");
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000323
324#define OFF(x) offsetof(partialobject, x)
325static PyMemberDef partial_memberlist[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000326 {"func", T_OBJECT, OFF(fn), READONLY,
327 "function object to use in future partial calls"},
328 {"args", T_OBJECT, OFF(args), READONLY,
329 "tuple of arguments to future partial calls"},
330 {"keywords", T_OBJECT, OFF(kw), READONLY,
331 "dictionary of keyword arguments to future partial calls"},
Hai Shidd391232020-12-29 20:45:07 +0800332 {"__weaklistoffset__", T_PYSSIZET,
333 offsetof(partialobject, weakreflist), READONLY},
334 {"__dictoffset__", T_PYSSIZET,
335 offsetof(partialobject, dict), READONLY},
336 {"__vectorcalloffset__", T_PYSSIZET,
337 offsetof(partialobject, vectorcall), READONLY},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000338 {NULL} /* Sentinel */
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000339};
340
Georg Brandlc2fb6c72006-02-21 17:49:57 +0000341static PyGetSetDef partial_getsetlist[] = {
Benjamin Peterson23d7f122012-02-19 20:02:57 -0500342 {"__dict__", PyObject_GenericGetDict, PyObject_GenericSetDict},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000343 {NULL} /* Sentinel */
Raymond Hettingerc8b6d1b2005-03-08 06:14:50 +0000344};
345
Alexander Belopolsky41e422a2010-12-01 20:05:49 +0000346static PyObject *
347partial_repr(partialobject *pto)
348{
Serhiy Storchaka179f9602016-06-12 11:44:06 +0300349 PyObject *result = NULL;
Alexander Belopolsky41e422a2010-12-01 20:05:49 +0000350 PyObject *arglist;
Alexander Belopolsky41e422a2010-12-01 20:05:49 +0000351 Py_ssize_t i, n;
Serhiy Storchaka38741282016-02-02 18:45:17 +0200352 PyObject *key, *value;
Serhiy Storchaka179f9602016-06-12 11:44:06 +0300353 int status;
354
355 status = Py_ReprEnter((PyObject *)pto);
356 if (status != 0) {
357 if (status < 0)
358 return NULL;
Nick Coghlan457fc9a2016-09-10 20:00:02 +1000359 return PyUnicode_FromString("...");
Serhiy Storchaka179f9602016-06-12 11:44:06 +0300360 }
Alexander Belopolsky41e422a2010-12-01 20:05:49 +0000361
362 arglist = PyUnicode_FromString("");
Serhiy Storchaka179f9602016-06-12 11:44:06 +0300363 if (arglist == NULL)
364 goto done;
Alexander Belopolsky41e422a2010-12-01 20:05:49 +0000365 /* Pack positional arguments */
366 assert (PyTuple_Check(pto->args));
367 n = PyTuple_GET_SIZE(pto->args);
368 for (i = 0; i < n; i++) {
Serhiy Storchaka179f9602016-06-12 11:44:06 +0300369 Py_SETREF(arglist, PyUnicode_FromFormat("%U, %R", arglist,
370 PyTuple_GET_ITEM(pto->args, i)));
371 if (arglist == NULL)
372 goto done;
Alexander Belopolsky41e422a2010-12-01 20:05:49 +0000373 }
374 /* Pack keyword arguments */
Serhiy Storchaka38741282016-02-02 18:45:17 +0200375 assert (PyDict_Check(pto->kw));
376 for (i = 0; PyDict_Next(pto->kw, &i, &key, &value);) {
Michael Seifert6c3d5272017-03-15 06:26:33 +0100377 /* Prevent key.__str__ from deleting the value. */
378 Py_INCREF(value);
379 Py_SETREF(arglist, PyUnicode_FromFormat("%U, %S=%R", arglist,
Serhiy Storchaka179f9602016-06-12 11:44:06 +0300380 key, value));
Michael Seifert6c3d5272017-03-15 06:26:33 +0100381 Py_DECREF(value);
Serhiy Storchaka179f9602016-06-12 11:44:06 +0300382 if (arglist == NULL)
383 goto done;
Alexander Belopolsky41e422a2010-12-01 20:05:49 +0000384 }
385 result = PyUnicode_FromFormat("%s(%R%U)", Py_TYPE(pto)->tp_name,
386 pto->fn, arglist);
387 Py_DECREF(arglist);
Serhiy Storchaka179f9602016-06-12 11:44:06 +0300388
389 done:
390 Py_ReprLeave((PyObject *)pto);
Alexander Belopolsky41e422a2010-12-01 20:05:49 +0000391 return result;
392}
393
Jack Diederiche0cbd692009-04-01 04:27:09 +0000394/* Pickle strategy:
395 __reduce__ by itself doesn't support getting kwargs in the unpickle
396 operation so we define a __setstate__ that replaces all the information
397 about the partial. If we only replaced part of it someone would use
Ezio Melotti13925002011-03-16 11:05:33 +0200398 it as a hook to do strange things.
Jack Diederiche0cbd692009-04-01 04:27:09 +0000399 */
400
Antoine Pitrou69f71142009-05-24 21:25:49 +0000401static PyObject *
Jack Diederiche0cbd692009-04-01 04:27:09 +0000402partial_reduce(partialobject *pto, PyObject *unused)
403{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000404 return Py_BuildValue("O(O)(OOOO)", Py_TYPE(pto), pto->fn, pto->fn,
405 pto->args, pto->kw,
406 pto->dict ? pto->dict : Py_None);
Jack Diederiche0cbd692009-04-01 04:27:09 +0000407}
408
Antoine Pitrou69f71142009-05-24 21:25:49 +0000409static PyObject *
Serhiy Storchaka19c4e0d2013-02-04 12:47:24 +0200410partial_setstate(partialobject *pto, PyObject *state)
Jack Diederiche0cbd692009-04-01 04:27:09 +0000411{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000412 PyObject *fn, *fnargs, *kw, *dict;
Serhiy Storchaka38741282016-02-02 18:45:17 +0200413
414 if (!PyTuple_Check(state) ||
415 !PyArg_ParseTuple(state, "OOOO", &fn, &fnargs, &kw, &dict) ||
416 !PyCallable_Check(fn) ||
417 !PyTuple_Check(fnargs) ||
418 (kw != Py_None && !PyDict_Check(kw)))
419 {
420 PyErr_SetString(PyExc_TypeError, "invalid partial state");
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000421 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000422 }
Serhiy Storchaka38741282016-02-02 18:45:17 +0200423
424 if(!PyTuple_CheckExact(fnargs))
425 fnargs = PySequence_Tuple(fnargs);
426 else
427 Py_INCREF(fnargs);
428 if (fnargs == NULL)
429 return NULL;
430
431 if (kw == Py_None)
432 kw = PyDict_New();
433 else if(!PyDict_CheckExact(kw))
434 kw = PyDict_Copy(kw);
435 else
436 Py_INCREF(kw);
437 if (kw == NULL) {
438 Py_DECREF(fnargs);
439 return NULL;
440 }
441
Serhiy Storchaka38741282016-02-02 18:45:17 +0200442 if (dict == Py_None)
443 dict = NULL;
444 else
445 Py_INCREF(dict);
446
Victor Stinner0f7b0b32017-03-14 21:37:20 +0100447 Py_INCREF(fn);
Serhiy Storchaka864b63c2016-04-11 09:53:37 +0300448 Py_SETREF(pto->fn, fn);
449 Py_SETREF(pto->args, fnargs);
450 Py_SETREF(pto->kw, kw);
Serhiy Storchaka48842712016-04-06 09:45:48 +0300451 Py_XSETREF(pto->dict, dict);
Jeroen Demeyered184c02019-07-13 16:39:18 +0200452 partial_setvectorcall(pto);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000453 Py_RETURN_NONE;
Jack Diederiche0cbd692009-04-01 04:27:09 +0000454}
455
456static PyMethodDef partial_methods[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000457 {"__reduce__", (PyCFunction)partial_reduce, METH_NOARGS},
Serhiy Storchaka19c4e0d2013-02-04 12:47:24 +0200458 {"__setstate__", (PyCFunction)partial_setstate, METH_O},
Ethan Smithcecf0492020-04-13 21:53:04 -0700459 {"__class_getitem__", (PyCFunction)Py_GenericAlias,
460 METH_O|METH_CLASS, PyDoc_STR("See PEP 585")},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000461 {NULL, NULL} /* sentinel */
Jack Diederiche0cbd692009-04-01 04:27:09 +0000462};
463
Hai Shidd391232020-12-29 20:45:07 +0800464static PyType_Slot partial_type_slots[] = {
465 {Py_tp_dealloc, partial_dealloc},
466 {Py_tp_repr, partial_repr},
467 {Py_tp_call, partial_call},
468 {Py_tp_getattro, PyObject_GenericGetAttr},
469 {Py_tp_setattro, PyObject_GenericSetAttr},
470 {Py_tp_doc, (void *)partial_doc},
471 {Py_tp_traverse, partial_traverse},
472 {Py_tp_methods, partial_methods},
473 {Py_tp_members, partial_memberlist},
474 {Py_tp_getset, partial_getsetlist},
475 {Py_tp_new, partial_new},
476 {Py_tp_free, PyObject_GC_Del},
477 {0, 0}
478};
479
480static PyType_Spec partial_type_spec = {
481 .name = "functools.partial",
482 .basicsize = sizeof(partialobject),
483 .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
484 Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_VECTORCALL,
485 .slots = partial_type_slots
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000486};
487
488
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700489/* cmp_to_key ***************************************************************/
490
491typedef struct {
Victor Stinner446c8d52011-04-05 12:21:35 +0200492 PyObject_HEAD
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700493 PyObject *cmp;
494 PyObject *object;
495} keyobject;
496
Hai Shidd391232020-12-29 20:45:07 +0800497static int
498keyobject_clear(keyobject *ko)
499{
500 Py_CLEAR(ko->cmp);
501 Py_CLEAR(ko->object);
502 return 0;
503}
504
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700505static void
506keyobject_dealloc(keyobject *ko)
507{
Hai Shidd391232020-12-29 20:45:07 +0800508 PyTypeObject *tp = Py_TYPE(ko);
509 keyobject_clear(ko);
Victor Stinner32bd68c2020-12-01 10:37:39 +0100510 PyObject_Free(ko);
Hai Shidd391232020-12-29 20:45:07 +0800511 Py_DECREF(tp);
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700512}
513
514static int
515keyobject_traverse(keyobject *ko, visitproc visit, void *arg)
516{
517 Py_VISIT(ko->cmp);
Hai Shi47a23fc2020-06-07 20:05:36 +0800518 Py_VISIT(ko->object);
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700519 return 0;
520}
521
522static PyMemberDef keyobject_members[] = {
523 {"obj", T_OBJECT,
524 offsetof(keyobject, object), 0,
525 PyDoc_STR("Value wrapped by a key function.")},
526 {NULL}
527};
528
529static PyObject *
Raymond Hettingera5632862011-04-09 12:57:00 -0700530keyobject_call(keyobject *ko, PyObject *args, PyObject *kwds);
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700531
532static PyObject *
533keyobject_richcompare(PyObject *ko, PyObject *other, int op);
534
Hai Shidd391232020-12-29 20:45:07 +0800535static PyType_Slot keyobject_type_slots[] = {
536 {Py_tp_dealloc, keyobject_dealloc},
537 {Py_tp_call, keyobject_call},
538 {Py_tp_getattro, PyObject_GenericGetAttr},
539 {Py_tp_traverse, keyobject_traverse},
540 {Py_tp_clear, keyobject_clear},
541 {Py_tp_richcompare, keyobject_richcompare},
542 {Py_tp_members, keyobject_members},
543 {0, 0}
544};
545
546static PyType_Spec keyobject_type_spec = {
547 .name = "functools.KeyWrapper",
548 .basicsize = sizeof(keyobject),
549 .flags = Py_TPFLAGS_DEFAULT,
550 .slots = keyobject_type_slots
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700551};
552
553static PyObject *
554keyobject_call(keyobject *ko, PyObject *args, PyObject *kwds)
555{
556 PyObject *object;
557 keyobject *result;
558 static char *kwargs[] = {"obj", NULL};
559
560 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:K", kwargs, &object))
561 return NULL;
Hai Shidd391232020-12-29 20:45:07 +0800562
563 result = PyObject_New(keyobject, Py_TYPE(ko));
564 if (result == NULL) {
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700565 return NULL;
Hai Shidd391232020-12-29 20:45:07 +0800566 }
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700567 Py_INCREF(ko->cmp);
568 result->cmp = ko->cmp;
569 Py_INCREF(object);
570 result->object = object;
571 return (PyObject *)result;
572}
573
574static PyObject *
575keyobject_richcompare(PyObject *ko, PyObject *other, int op)
576{
577 PyObject *res;
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700578 PyObject *x;
579 PyObject *y;
580 PyObject *compare;
581 PyObject *answer;
Victor Stinnerf7a4c482016-08-19 18:52:35 +0200582 PyObject* stack[2];
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700583
Hai Shidd391232020-12-29 20:45:07 +0800584 if (!Py_IS_TYPE(other, Py_TYPE(ko))) {
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700585 PyErr_Format(PyExc_TypeError, "other argument must be K instance");
586 return NULL;
587 }
588 compare = ((keyobject *) ko)->cmp;
589 assert(compare != NULL);
590 x = ((keyobject *) ko)->object;
591 y = ((keyobject *) other)->object;
592 if (!x || !y){
593 PyErr_Format(PyExc_AttributeError, "object");
594 return NULL;
595 }
596
597 /* Call the user's comparison function and translate the 3-way
598 * result into true or false (or error).
599 */
Victor Stinnerf7a4c482016-08-19 18:52:35 +0200600 stack[0] = x;
601 stack[1] = y;
Victor Stinner559bb6a2016-08-22 22:48:54 +0200602 res = _PyObject_FastCall(compare, stack, 2);
Victor Stinnerf7a4c482016-08-19 18:52:35 +0200603 if (res == NULL) {
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700604 return NULL;
Victor Stinnerf7a4c482016-08-19 18:52:35 +0200605 }
606
Victor Stinner37834132020-10-27 17:12:53 +0100607 answer = PyObject_RichCompare(res, _PyLong_GetZero(), op);
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700608 Py_DECREF(res);
609 return answer;
610}
611
612static PyObject *
Victor Stinner446c8d52011-04-05 12:21:35 +0200613functools_cmp_to_key(PyObject *self, PyObject *args, PyObject *kwds)
614{
615 PyObject *cmp;
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700616 static char *kwargs[] = {"mycmp", NULL};
Victor Stinner446c8d52011-04-05 12:21:35 +0200617 keyobject *object;
Hai Shidd391232020-12-29 20:45:07 +0800618 _functools_state *state;
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700619
620 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:cmp_to_key", kwargs, &cmp))
621 return NULL;
Hai Shidd391232020-12-29 20:45:07 +0800622
623 state = get_functools_state(self);
624 object = PyObject_New(keyobject, state->keyobject_type);
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700625 if (!object)
626 return NULL;
627 Py_INCREF(cmp);
628 object->cmp = cmp;
629 object->object = NULL;
630 return (PyObject *)object;
631}
632
633PyDoc_STRVAR(functools_cmp_to_key_doc,
634"Convert a cmp= function into a key= function.");
635
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000636/* reduce (used to be a builtin) ********************************************/
637
638static PyObject *
639functools_reduce(PyObject *self, PyObject *args)
640{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000641 PyObject *seq, *func, *result = NULL, *it;
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000642
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000643 if (!PyArg_UnpackTuple(args, "reduce", 2, 3, &func, &seq, &result))
644 return NULL;
645 if (result != NULL)
646 Py_INCREF(result);
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000647
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000648 it = PyObject_GetIter(seq);
649 if (it == NULL) {
Alexander Belopolskye29e6bf2010-08-16 18:55:46 +0000650 if (PyErr_ExceptionMatches(PyExc_TypeError))
651 PyErr_SetString(PyExc_TypeError,
652 "reduce() arg 2 must support iteration");
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000653 Py_XDECREF(result);
654 return NULL;
655 }
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000656
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000657 if ((args = PyTuple_New(2)) == NULL)
658 goto Fail;
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000659
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000660 for (;;) {
661 PyObject *op2;
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000662
Victor Stinnera93c51e2020-02-07 00:38:59 +0100663 if (Py_REFCNT(args) > 1) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000664 Py_DECREF(args);
665 if ((args = PyTuple_New(2)) == NULL)
666 goto Fail;
667 }
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000668
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000669 op2 = PyIter_Next(it);
670 if (op2 == NULL) {
671 if (PyErr_Occurred())
672 goto Fail;
673 break;
674 }
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000675
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000676 if (result == NULL)
677 result = op2;
678 else {
Sergey Fedoseeve5f62072019-06-02 01:32:18 +0500679 /* Update the args tuple in-place */
Victor Stinnera93c51e2020-02-07 00:38:59 +0100680 assert(Py_REFCNT(args) == 1);
Sergey Fedoseeve5f62072019-06-02 01:32:18 +0500681 Py_XSETREF(_PyTuple_ITEMS(args)[0], result);
682 Py_XSETREF(_PyTuple_ITEMS(args)[1], op2);
683 if ((result = PyObject_Call(func, args, NULL)) == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000684 goto Fail;
Sergey Fedoseeve5f62072019-06-02 01:32:18 +0500685 }
Brandt Bucher226a0122020-12-04 19:45:57 -0800686 // bpo-42536: The GC may have untracked this args tuple. Since we're
687 // recycling it, make sure it's tracked again:
688 if (!_PyObject_GC_IS_TRACKED(args)) {
689 _PyObject_GC_TRACK(args);
690 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000691 }
692 }
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000693
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000694 Py_DECREF(args);
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000695
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000696 if (result == NULL)
697 PyErr_SetString(PyExc_TypeError,
Zackery Spytzcd3c2bd2020-06-28 00:40:54 -0600698 "reduce() of empty iterable with no initial value");
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000699
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000700 Py_DECREF(it);
701 return result;
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000702
703Fail:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000704 Py_XDECREF(args);
705 Py_XDECREF(result);
706 Py_DECREF(it);
707 return NULL;
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000708}
709
710PyDoc_STRVAR(functools_reduce_doc,
Zackery Spytzcd3c2bd2020-06-28 00:40:54 -0600711"reduce(function, iterable[, initial]) -> value\n\
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000712\n\
Zackery Spytzcd3c2bd2020-06-28 00:40:54 -0600713Apply a function of two arguments cumulatively to the items of a sequence\n\
714or iterable, from left to right, so as to reduce the iterable to a single\n\
715value. For example, reduce(lambda x, y: x+y, [1, 2, 3, 4, 5]) calculates\n\
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000716((((1+2)+3)+4)+5). If initial is present, it is placed before the items\n\
Zackery Spytzcd3c2bd2020-06-28 00:40:54 -0600717of the iterable in the calculation, and serves as a default when the\n\
718iterable is empty.");
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000719
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300720/* lru_cache object **********************************************************/
721
Raymond Hettinger2dda72a2019-02-08 18:55:02 -0800722/* There are four principal algorithmic differences from the pure python version:
723
724 1). The C version relies on the GIL instead of having its own reentrant lock.
725
726 2). The prev/next link fields use borrowed references.
727
728 3). For a full cache, the pure python version rotates the location of the
729 root entry so that it never has to move individual links and it can
730 limit updates to just the key and result fields. However, in the C
731 version, links are temporarily removed while the cache dict updates are
732 occurring. Afterwards, they are appended or prepended back into the
733 doubly-linked lists.
734
735 4) In the Python version, the _HashSeq class is used to prevent __hash__
736 from being called more than once. In the C version, the "known hash"
737 variants of dictionary calls as used to the same effect.
738
739*/
740
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300741struct lru_list_elem;
742struct lru_cache_object;
743
744typedef struct lru_list_elem {
745 PyObject_HEAD
746 struct lru_list_elem *prev, *next; /* borrowed links */
Serhiy Storchakab9d98d52015-10-02 12:47:11 +0300747 Py_hash_t hash;
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300748 PyObject *key, *result;
749} lru_list_elem;
750
751static void
752lru_list_elem_dealloc(lru_list_elem *link)
753{
Hai Shidd391232020-12-29 20:45:07 +0800754 PyTypeObject *tp = Py_TYPE(link);
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300755 Py_XDECREF(link->key);
756 Py_XDECREF(link->result);
Victor Stinner32bd68c2020-12-01 10:37:39 +0100757 PyObject_Free(link);
Hai Shidd391232020-12-29 20:45:07 +0800758 Py_DECREF(tp);
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300759}
760
Hai Shidd391232020-12-29 20:45:07 +0800761static PyType_Slot lru_list_elem_type_slots[] = {
762 {Py_tp_dealloc, lru_list_elem_dealloc},
763 {0, 0}
764};
765
766static PyType_Spec lru_list_elem_type_spec = {
767 .name = "functools._lru_list_elem",
768 .basicsize = sizeof(lru_list_elem),
769 .flags = Py_TPFLAGS_DEFAULT,
770 .slots = lru_list_elem_type_slots
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300771};
772
773
774typedef PyObject *(*lru_cache_ternaryfunc)(struct lru_cache_object *, PyObject *, PyObject *);
775
776typedef struct lru_cache_object {
777 lru_list_elem root; /* includes PyObject_HEAD */
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300778 lru_cache_ternaryfunc wrapper;
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300779 int typed;
Raymond Hettingerd8080c02019-01-26 03:02:00 -0500780 PyObject *cache;
781 Py_ssize_t hits;
782 PyObject *func;
783 Py_ssize_t maxsize;
784 Py_ssize_t misses;
Raymond Hettinger139c2322021-04-21 15:22:22 -0700785 /* the kwd_mark is used delimit args and keywords in the cache keys */
786 PyObject *kwd_mark;
787 PyTypeObject *lru_list_elem_type;
Raymond Hettingerd8080c02019-01-26 03:02:00 -0500788 PyObject *cache_info_type;
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300789 PyObject *dict;
Dennis Sweeney1253c3e2020-05-05 17:14:32 -0400790 PyObject *weakreflist;
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300791} lru_cache_object;
792
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300793static PyObject *
Raymond Hettinger139c2322021-04-21 15:22:22 -0700794lru_cache_make_key(PyObject *kwd_mark, PyObject *args,
Hai Shidd391232020-12-29 20:45:07 +0800795 PyObject *kwds, int typed)
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300796{
Raymond Hettingerdda44682017-01-08 18:04:30 -0800797 PyObject *key, *keyword, *value;
798 Py_ssize_t key_size, pos, key_pos, kwds_size;
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300799
Raymond Hettinger14adbd42019-04-20 07:20:44 -1000800 kwds_size = kwds ? PyDict_GET_SIZE(kwds) : 0;
801
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300802 /* short path, key will match args anyway, which is a tuple */
Raymond Hettinger14adbd42019-04-20 07:20:44 -1000803 if (!typed && !kwds_size) {
Raymond Hettingerd8080c02019-01-26 03:02:00 -0500804 if (PyTuple_GET_SIZE(args) == 1) {
805 key = PyTuple_GET_ITEM(args, 0);
806 if (PyUnicode_CheckExact(key) || PyLong_CheckExact(key)) {
807 /* For common scalar keys, save space by
808 dropping the enclosing args tuple */
809 Py_INCREF(key);
810 return key;
811 }
812 }
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300813 Py_INCREF(args);
814 return args;
815 }
816
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300817 key_size = PyTuple_GET_SIZE(args);
Raymond Hettingerdda44682017-01-08 18:04:30 -0800818 if (kwds_size)
819 key_size += kwds_size * 2 + 1;
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300820 if (typed)
Raymond Hettingerdda44682017-01-08 18:04:30 -0800821 key_size += PyTuple_GET_SIZE(args) + kwds_size;
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300822
823 key = PyTuple_New(key_size);
824 if (key == NULL)
Raymond Hettingerdda44682017-01-08 18:04:30 -0800825 return NULL;
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300826
827 key_pos = 0;
828 for (pos = 0; pos < PyTuple_GET_SIZE(args); ++pos) {
829 PyObject *item = PyTuple_GET_ITEM(args, pos);
830 Py_INCREF(item);
831 PyTuple_SET_ITEM(key, key_pos++, item);
832 }
Raymond Hettingerdda44682017-01-08 18:04:30 -0800833 if (kwds_size) {
Raymond Hettinger139c2322021-04-21 15:22:22 -0700834 Py_INCREF(kwd_mark);
835 PyTuple_SET_ITEM(key, key_pos++, kwd_mark);
Raymond Hettingerdda44682017-01-08 18:04:30 -0800836 for (pos = 0; PyDict_Next(kwds, &pos, &keyword, &value);) {
837 Py_INCREF(keyword);
838 PyTuple_SET_ITEM(key, key_pos++, keyword);
839 Py_INCREF(value);
840 PyTuple_SET_ITEM(key, key_pos++, value);
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300841 }
Raymond Hettingerdda44682017-01-08 18:04:30 -0800842 assert(key_pos == PyTuple_GET_SIZE(args) + kwds_size * 2 + 1);
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300843 }
844 if (typed) {
845 for (pos = 0; pos < PyTuple_GET_SIZE(args); ++pos) {
846 PyObject *item = (PyObject *)Py_TYPE(PyTuple_GET_ITEM(args, pos));
847 Py_INCREF(item);
848 PyTuple_SET_ITEM(key, key_pos++, item);
849 }
Raymond Hettingerdda44682017-01-08 18:04:30 -0800850 if (kwds_size) {
851 for (pos = 0; PyDict_Next(kwds, &pos, &keyword, &value);) {
852 PyObject *item = (PyObject *)Py_TYPE(value);
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300853 Py_INCREF(item);
854 PyTuple_SET_ITEM(key, key_pos++, item);
855 }
856 }
857 }
858 assert(key_pos == key_size);
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300859 return key;
860}
861
862static PyObject *
863uncached_lru_cache_wrapper(lru_cache_object *self, PyObject *args, PyObject *kwds)
864{
Raymond Hettingerffdf1c32019-01-31 15:03:38 -0800865 PyObject *result;
866
867 self->misses++;
868 result = PyObject_Call(self->func, args, kwds);
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300869 if (!result)
870 return NULL;
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300871 return result;
872}
873
874static PyObject *
875infinite_lru_cache_wrapper(lru_cache_object *self, PyObject *args, PyObject *kwds)
876{
877 PyObject *result;
Serhiy Storchakab9d98d52015-10-02 12:47:11 +0300878 Py_hash_t hash;
Raymond Hettinger139c2322021-04-21 15:22:22 -0700879 PyObject *key = lru_cache_make_key(self->kwd_mark, args, kwds, self->typed);
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300880 if (!key)
881 return NULL;
Serhiy Storchakab9d98d52015-10-02 12:47:11 +0300882 hash = PyObject_Hash(key);
Yury Selivanov46a02db2016-11-09 18:55:45 -0500883 if (hash == -1) {
884 Py_DECREF(key);
Serhiy Storchakab9d98d52015-10-02 12:47:11 +0300885 return NULL;
Yury Selivanov46a02db2016-11-09 18:55:45 -0500886 }
Serhiy Storchakab9d98d52015-10-02 12:47:11 +0300887 result = _PyDict_GetItem_KnownHash(self->cache, key, hash);
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300888 if (result) {
889 Py_INCREF(result);
890 self->hits++;
891 Py_DECREF(key);
892 return result;
893 }
894 if (PyErr_Occurred()) {
895 Py_DECREF(key);
896 return NULL;
897 }
Raymond Hettingerffdf1c32019-01-31 15:03:38 -0800898 self->misses++;
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300899 result = PyObject_Call(self->func, args, kwds);
900 if (!result) {
901 Py_DECREF(key);
902 return NULL;
903 }
Serhiy Storchakab9d98d52015-10-02 12:47:11 +0300904 if (_PyDict_SetItem_KnownHash(self->cache, key, result, hash) < 0) {
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300905 Py_DECREF(result);
906 Py_DECREF(key);
907 return NULL;
908 }
909 Py_DECREF(key);
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300910 return result;
911}
912
913static void
Raymond Hettingerd8080c02019-01-26 03:02:00 -0500914lru_cache_extract_link(lru_list_elem *link)
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300915{
Raymond Hettingerd8080c02019-01-26 03:02:00 -0500916 lru_list_elem *link_prev = link->prev;
917 lru_list_elem *link_next = link->next;
918 link_prev->next = link->next;
919 link_next->prev = link->prev;
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300920}
921
922static void
923lru_cache_append_link(lru_cache_object *self, lru_list_elem *link)
924{
925 lru_list_elem *root = &self->root;
926 lru_list_elem *last = root->prev;
927 last->next = root->prev = link;
928 link->prev = last;
929 link->next = root;
930}
931
Raymond Hettingerd8080c02019-01-26 03:02:00 -0500932static void
933lru_cache_prepend_link(lru_cache_object *self, lru_list_elem *link)
934{
935 lru_list_elem *root = &self->root;
936 lru_list_elem *first = root->next;
937 first->prev = root->next = link;
938 link->prev = root;
939 link->next = first;
940}
941
942/* General note on reentrancy:
943
944 There are four dictionary calls in the bounded_lru_cache_wrapper():
945 1) The initial check for a cache match. 2) The post user-function
946 check for a cache match. 3) The deletion of the oldest entry.
947 4) The addition of the newest entry.
948
949 In all four calls, we have a known hash which lets use avoid a call
950 to __hash__(). That leaves only __eq__ as a possible source of a
951 reentrant call.
952
953 The __eq__ method call is always made for a cache hit (dict access #1).
954 Accordingly, we have make sure not modify the cache state prior to
955 this call.
956
957 The __eq__ method call is never made for the deletion (dict access #3)
958 because it is an identity match.
959
960 For the other two accesses (#2 and #4), calls to __eq__ only occur
961 when some other entry happens to have an exactly matching hash (all
962 64-bits). Though rare, this can happen, so we have to make sure to
963 either call it at the top of its code path before any cache
964 state modifications (dict access #2) or be prepared to restore
965 invariants at the end of the code path (dict access #4).
966
967 Another possible source of reentrancy is a decref which can trigger
968 arbitrary code execution. To make the code easier to reason about,
969 the decrefs are deferred to the end of the each possible code path
970 so that we know the cache is a consistent state.
971 */
972
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300973static PyObject *
974bounded_lru_cache_wrapper(lru_cache_object *self, PyObject *args, PyObject *kwds)
975{
976 lru_list_elem *link;
Raymond Hettingerd8080c02019-01-26 03:02:00 -0500977 PyObject *key, *result, *testresult;
Serhiy Storchakab9d98d52015-10-02 12:47:11 +0300978 Py_hash_t hash;
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300979
Raymond Hettinger139c2322021-04-21 15:22:22 -0700980 key = lru_cache_make_key(self->kwd_mark, args, kwds, self->typed);
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300981 if (!key)
982 return NULL;
Serhiy Storchakab9d98d52015-10-02 12:47:11 +0300983 hash = PyObject_Hash(key);
Yury Selivanov46a02db2016-11-09 18:55:45 -0500984 if (hash == -1) {
985 Py_DECREF(key);
Serhiy Storchakab9d98d52015-10-02 12:47:11 +0300986 return NULL;
Yury Selivanov46a02db2016-11-09 18:55:45 -0500987 }
Serhiy Storchakab9d98d52015-10-02 12:47:11 +0300988 link = (lru_list_elem *)_PyDict_GetItem_KnownHash(self->cache, key, hash);
Raymond Hettingerd8080c02019-01-26 03:02:00 -0500989 if (link != NULL) {
990 lru_cache_extract_link(link);
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300991 lru_cache_append_link(self, link);
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300992 result = link->result;
Raymond Hettingerd8080c02019-01-26 03:02:00 -0500993 self->hits++;
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300994 Py_INCREF(result);
995 Py_DECREF(key);
996 return result;
997 }
998 if (PyErr_Occurred()) {
999 Py_DECREF(key);
1000 return NULL;
1001 }
Raymond Hettingerd8080c02019-01-26 03:02:00 -05001002 self->misses++;
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001003 result = PyObject_Call(self->func, args, kwds);
1004 if (!result) {
1005 Py_DECREF(key);
1006 return NULL;
1007 }
Raymond Hettingerd8080c02019-01-26 03:02:00 -05001008 testresult = _PyDict_GetItem_KnownHash(self->cache, key, hash);
1009 if (testresult != NULL) {
1010 /* Getting here means that this same key was added to the cache
1011 during the PyObject_Call(). Since the link update is already
1012 done, we need only return the computed result. */
1013 Py_DECREF(key);
1014 return result;
1015 }
1016 if (PyErr_Occurred()) {
1017 /* This is an unusual case since this same lookup
1018 did not previously trigger an error during lookup.
1019 Treat it the same as an error in user function
1020 and return with the error set. */
1021 Py_DECREF(key);
1022 Py_DECREF(result);
1023 return NULL;
1024 }
1025 /* This is the normal case. The new key wasn't found before
1026 user function call and it is still not there. So we
1027 proceed normally and update the cache with the new result. */
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001028
Raymond Hettingerd8080c02019-01-26 03:02:00 -05001029 assert(self->maxsize > 0);
1030 if (PyDict_GET_SIZE(self->cache) < self->maxsize ||
1031 self->root.next == &self->root)
1032 {
1033 /* Cache is not full, so put the result in a new link */
INADA Naoki3070b712017-12-26 02:03:24 +09001034 link = (lru_list_elem *)PyObject_New(lru_list_elem,
Raymond Hettinger139c2322021-04-21 15:22:22 -07001035 self->lru_list_elem_type);
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001036 if (link == NULL) {
1037 Py_DECREF(key);
1038 Py_DECREF(result);
1039 return NULL;
1040 }
1041
Serhiy Storchakab9d98d52015-10-02 12:47:11 +03001042 link->hash = hash;
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001043 link->key = key;
1044 link->result = result;
Raymond Hettingerd8080c02019-01-26 03:02:00 -05001045 /* What is really needed here is a SetItem variant with a "no clobber"
1046 option. If the __eq__ call triggers a reentrant call that adds
1047 this same key, then this setitem call will update the cache dict
1048 with this new link, leaving the old link as an orphan (i.e. not
1049 having a cache dict entry that refers to it). */
Serhiy Storchakab9d98d52015-10-02 12:47:11 +03001050 if (_PyDict_SetItem_KnownHash(self->cache, key, (PyObject *)link,
1051 hash) < 0) {
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001052 Py_DECREF(link);
1053 return NULL;
1054 }
1055 lru_cache_append_link(self, link);
1056 Py_INCREF(result); /* for return */
Raymond Hettingerd8080c02019-01-26 03:02:00 -05001057 return result;
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001058 }
Raymond Hettingerd8080c02019-01-26 03:02:00 -05001059 /* Since the cache is full, we need to evict an old key and add
1060 a new key. Rather than free the old link and allocate a new
1061 one, we reuse the link for the new key and result and move it
1062 to front of the cache to mark it as recently used.
1063
1064 We try to assure all code paths (including errors) leave all
1065 of the links in place. Either the link is successfully
1066 updated and moved or it is restored to its old position.
1067 However if an unrecoverable error is found, it doesn't
1068 make sense to reinsert the link, so we leave it out
1069 and the cache will no longer register as full.
1070 */
1071 PyObject *oldkey, *oldresult, *popresult;
1072
1073 /* Extract the oldest item. */
1074 assert(self->root.next != &self->root);
1075 link = self->root.next;
1076 lru_cache_extract_link(link);
1077 /* Remove it from the cache.
Raymond Hettinger2dda72a2019-02-08 18:55:02 -08001078 The cache dict holds one reference to the link.
1079 We created one other reference when the link was created.
1080 The linked list only has borrowed references. */
Raymond Hettingerd8080c02019-01-26 03:02:00 -05001081 popresult = _PyDict_Pop_KnownHash(self->cache, link->key,
1082 link->hash, Py_None);
1083 if (popresult == Py_None) {
1084 /* Getting here means that the user function call or another
1085 thread has already removed the old key from the dictionary.
Raymond Hettinger2dda72a2019-02-08 18:55:02 -08001086 This link is now an orphan. Since we don't want to leave the
Raymond Hettingerd8080c02019-01-26 03:02:00 -05001087 cache in an inconsistent state, we don't restore the link. */
1088 Py_DECREF(popresult);
1089 Py_DECREF(link);
1090 Py_DECREF(key);
1091 return result;
1092 }
1093 if (popresult == NULL) {
1094 /* An error arose while trying to remove the oldest key (the one
1095 being evicted) from the cache. We restore the link to its
1096 original position as the oldest link. Then we allow the
1097 error propagate upward; treating it the same as an error
1098 arising in the user function. */
1099 lru_cache_prepend_link(self, link);
1100 Py_DECREF(key);
1101 Py_DECREF(result);
1102 return NULL;
1103 }
1104 /* Keep a reference to the old key and old result to prevent their
1105 ref counts from going to zero during the update. That will
1106 prevent potentially arbitrary object clean-up code (i.e. __del__)
1107 from running while we're still adjusting the links. */
1108 oldkey = link->key;
1109 oldresult = link->result;
1110
1111 link->hash = hash;
1112 link->key = key;
1113 link->result = result;
1114 /* Note: The link is being added to the cache dict without the
1115 prev and next fields set to valid values. We have to wait
1116 for successful insertion in the cache dict before adding the
1117 link to the linked list. Otherwise, the potentially reentrant
Raymond Hettinger2dda72a2019-02-08 18:55:02 -08001118 __eq__ call could cause the then orphan link to be visited. */
Raymond Hettingerd8080c02019-01-26 03:02:00 -05001119 if (_PyDict_SetItem_KnownHash(self->cache, key, (PyObject *)link,
1120 hash) < 0) {
1121 /* Somehow the cache dict update failed. We no longer can
1122 restore the old link. Let the error propagate upward and
1123 leave the cache short one link. */
1124 Py_DECREF(popresult);
1125 Py_DECREF(link);
1126 Py_DECREF(oldkey);
1127 Py_DECREF(oldresult);
1128 return NULL;
1129 }
1130 lru_cache_append_link(self, link);
1131 Py_INCREF(result); /* for return */
1132 Py_DECREF(popresult);
1133 Py_DECREF(oldkey);
1134 Py_DECREF(oldresult);
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001135 return result;
1136}
1137
1138static PyObject *
1139lru_cache_new(PyTypeObject *type, PyObject *args, PyObject *kw)
1140{
Serhiy Storchaka374164c2015-07-25 12:10:21 +03001141 PyObject *func, *maxsize_O, *cache_info_type, *cachedict;
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001142 int typed;
1143 lru_cache_object *obj;
1144 Py_ssize_t maxsize;
1145 PyObject *(*wrapper)(lru_cache_object *, PyObject *, PyObject *);
Raymond Hettinger139c2322021-04-21 15:22:22 -07001146 _functools_state *state;
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001147 static char *keywords[] = {"user_function", "maxsize", "typed",
1148 "cache_info_type", NULL};
1149
1150 if (!PyArg_ParseTupleAndKeywords(args, kw, "OOpO:lru_cache", keywords,
1151 &func, &maxsize_O, &typed,
1152 &cache_info_type)) {
1153 return NULL;
1154 }
1155
1156 if (!PyCallable_Check(func)) {
1157 PyErr_SetString(PyExc_TypeError,
1158 "the first argument must be callable");
1159 return NULL;
1160 }
1161
Raymond Hettinger139c2322021-04-21 15:22:22 -07001162 state = get_functools_state_by_type(type);
1163 if (state == NULL) {
1164 return NULL;
1165 }
1166
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001167 /* select the caching function, and make/inc maxsize_O */
1168 if (maxsize_O == Py_None) {
1169 wrapper = infinite_lru_cache_wrapper;
1170 /* use this only to initialize lru_cache_object attribute maxsize */
1171 maxsize = -1;
1172 } else if (PyIndex_Check(maxsize_O)) {
1173 maxsize = PyNumber_AsSsize_t(maxsize_O, PyExc_OverflowError);
1174 if (maxsize == -1 && PyErr_Occurred())
1175 return NULL;
Raymond Hettingerd8080c02019-01-26 03:02:00 -05001176 if (maxsize < 0) {
1177 maxsize = 0;
1178 }
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001179 if (maxsize == 0)
1180 wrapper = uncached_lru_cache_wrapper;
1181 else
1182 wrapper = bounded_lru_cache_wrapper;
1183 } else {
1184 PyErr_SetString(PyExc_TypeError, "maxsize should be integer or None");
1185 return NULL;
1186 }
1187
Serhiy Storchaka374164c2015-07-25 12:10:21 +03001188 if (!(cachedict = PyDict_New()))
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001189 return NULL;
1190
Serhiy Storchaka374164c2015-07-25 12:10:21 +03001191 obj = (lru_cache_object *)type->tp_alloc(type, 0);
1192 if (obj == NULL) {
1193 Py_DECREF(cachedict);
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001194 return NULL;
1195 }
1196
1197 obj->root.prev = &obj->root;
1198 obj->root.next = &obj->root;
Raymond Hettingerd8080c02019-01-26 03:02:00 -05001199 obj->wrapper = wrapper;
1200 obj->typed = typed;
1201 obj->cache = cachedict;
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001202 Py_INCREF(func);
1203 obj->func = func;
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001204 obj->misses = obj->hits = 0;
Raymond Hettingerd8080c02019-01-26 03:02:00 -05001205 obj->maxsize = maxsize;
Raymond Hettinger139c2322021-04-21 15:22:22 -07001206 Py_INCREF(state->kwd_mark);
1207 obj->kwd_mark = state->kwd_mark;
1208 Py_INCREF(state->lru_list_elem_type);
1209 obj->lru_list_elem_type = state->lru_list_elem_type;
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001210 Py_INCREF(cache_info_type);
1211 obj->cache_info_type = cache_info_type;
Raymond Hettingerbba760e2020-04-20 13:47:12 -07001212 obj->dict = NULL;
Dennis Sweeney1253c3e2020-05-05 17:14:32 -04001213 obj->weakreflist = NULL;
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001214 return (PyObject *)obj;
1215}
1216
1217static lru_list_elem *
1218lru_cache_unlink_list(lru_cache_object *self)
1219{
1220 lru_list_elem *root = &self->root;
1221 lru_list_elem *link = root->next;
1222 if (link == root)
1223 return NULL;
1224 root->prev->next = NULL;
1225 root->next = root->prev = root;
1226 return link;
1227}
1228
1229static void
1230lru_cache_clear_list(lru_list_elem *link)
1231{
1232 while (link != NULL) {
1233 lru_list_elem *next = link->next;
1234 Py_DECREF(link);
1235 link = next;
1236 }
1237}
1238
Hai Shidd391232020-12-29 20:45:07 +08001239static int
1240lru_cache_tp_clear(lru_cache_object *self)
1241{
1242 lru_list_elem *list = lru_cache_unlink_list(self);
1243 Py_CLEAR(self->func);
1244 Py_CLEAR(self->cache);
Raymond Hettinger139c2322021-04-21 15:22:22 -07001245 Py_CLEAR(self->kwd_mark);
1246 Py_CLEAR(self->lru_list_elem_type);
Hai Shidd391232020-12-29 20:45:07 +08001247 Py_CLEAR(self->cache_info_type);
1248 Py_CLEAR(self->dict);
1249 lru_cache_clear_list(list);
1250 return 0;
1251}
1252
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001253static void
1254lru_cache_dealloc(lru_cache_object *obj)
1255{
Hai Shidd391232020-12-29 20:45:07 +08001256 PyTypeObject *tp = Py_TYPE(obj);
INADA Naokia6296d32017-08-24 14:55:17 +09001257 /* bpo-31095: UnTrack is needed before calling any callbacks */
1258 PyObject_GC_UnTrack(obj);
Hai Shidd391232020-12-29 20:45:07 +08001259 if (obj->weakreflist != NULL) {
Dennis Sweeney1253c3e2020-05-05 17:14:32 -04001260 PyObject_ClearWeakRefs((PyObject*)obj);
Hai Shidd391232020-12-29 20:45:07 +08001261 }
INADA Naokia6296d32017-08-24 14:55:17 +09001262
Hai Shidd391232020-12-29 20:45:07 +08001263 lru_cache_tp_clear(obj);
1264 tp->tp_free(obj);
1265 Py_DECREF(tp);
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001266}
1267
1268static PyObject *
1269lru_cache_call(lru_cache_object *self, PyObject *args, PyObject *kwds)
1270{
1271 return self->wrapper(self, args, kwds);
1272}
1273
1274static PyObject *
Serhiy Storchakae7070f02015-06-08 11:19:24 +03001275lru_cache_descr_get(PyObject *self, PyObject *obj, PyObject *type)
1276{
1277 if (obj == Py_None || obj == NULL) {
1278 Py_INCREF(self);
1279 return self;
1280 }
1281 return PyMethod_New(self, obj);
1282}
1283
1284static PyObject *
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001285lru_cache_cache_info(lru_cache_object *self, PyObject *unused)
1286{
Raymond Hettingerd8080c02019-01-26 03:02:00 -05001287 if (self->maxsize == -1) {
1288 return PyObject_CallFunction(self->cache_info_type, "nnOn",
1289 self->hits, self->misses, Py_None,
1290 PyDict_GET_SIZE(self->cache));
1291 }
1292 return PyObject_CallFunction(self->cache_info_type, "nnnn",
1293 self->hits, self->misses, self->maxsize,
Serhiy Storchaka5ab81d72016-12-16 16:18:57 +02001294 PyDict_GET_SIZE(self->cache));
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001295}
1296
1297static PyObject *
1298lru_cache_cache_clear(lru_cache_object *self, PyObject *unused)
1299{
1300 lru_list_elem *list = lru_cache_unlink_list(self);
1301 self->hits = self->misses = 0;
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001302 PyDict_Clear(self->cache);
1303 lru_cache_clear_list(list);
1304 Py_RETURN_NONE;
1305}
1306
Serhiy Storchaka45120f22015-10-24 09:49:56 +03001307static PyObject *
1308lru_cache_reduce(PyObject *self, PyObject *unused)
1309{
1310 return PyObject_GetAttrString(self, "__qualname__");
1311}
1312
Serhiy Storchakae4d65e32015-12-28 23:58:07 +02001313static PyObject *
1314lru_cache_copy(PyObject *self, PyObject *unused)
1315{
1316 Py_INCREF(self);
1317 return self;
1318}
1319
1320static PyObject *
1321lru_cache_deepcopy(PyObject *self, PyObject *unused)
1322{
1323 Py_INCREF(self);
1324 return self;
1325}
1326
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001327static int
1328lru_cache_tp_traverse(lru_cache_object *self, visitproc visit, void *arg)
1329{
1330 lru_list_elem *link = self->root.next;
1331 while (link != &self->root) {
1332 lru_list_elem *next = link->next;
INADA Naoki3070b712017-12-26 02:03:24 +09001333 Py_VISIT(link->key);
1334 Py_VISIT(link->result);
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001335 link = next;
1336 }
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001337 Py_VISIT(self->func);
1338 Py_VISIT(self->cache);
Raymond Hettinger139c2322021-04-21 15:22:22 -07001339 Py_VISIT(self->kwd_mark);
1340 Py_VISIT(self->lru_list_elem_type);
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001341 Py_VISIT(self->cache_info_type);
1342 Py_VISIT(self->dict);
1343 return 0;
1344}
1345
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001346
1347PyDoc_STRVAR(lru_cache_doc,
1348"Create a cached callable that wraps another function.\n\
1349\n\
1350user_function: the function being cached\n\
1351\n\
1352maxsize: 0 for no caching\n\
1353 None for unlimited cache size\n\
1354 n for a bounded cache\n\
1355\n\
1356typed: False cache f(3) and f(3.0) as identical calls\n\
1357 True cache f(3) and f(3.0) as distinct calls\n\
1358\n\
1359cache_info_type: namedtuple class with the fields:\n\
1360 hits misses currsize maxsize\n"
1361);
1362
1363static PyMethodDef lru_cache_methods[] = {
1364 {"cache_info", (PyCFunction)lru_cache_cache_info, METH_NOARGS},
1365 {"cache_clear", (PyCFunction)lru_cache_cache_clear, METH_NOARGS},
Serhiy Storchaka45120f22015-10-24 09:49:56 +03001366 {"__reduce__", (PyCFunction)lru_cache_reduce, METH_NOARGS},
Serhiy Storchakae4d65e32015-12-28 23:58:07 +02001367 {"__copy__", (PyCFunction)lru_cache_copy, METH_VARARGS},
1368 {"__deepcopy__", (PyCFunction)lru_cache_deepcopy, METH_VARARGS},
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001369 {NULL}
1370};
1371
1372static PyGetSetDef lru_cache_getsetlist[] = {
1373 {"__dict__", PyObject_GenericGetDict, PyObject_GenericSetDict},
1374 {NULL}
1375};
1376
Hai Shidd391232020-12-29 20:45:07 +08001377static PyMemberDef lru_cache_memberlist[] = {
1378 {"__dictoffset__", T_PYSSIZET,
1379 offsetof(lru_cache_object, dict), READONLY},
1380 {"__weaklistoffset__", T_PYSSIZET,
1381 offsetof(lru_cache_object, weakreflist), READONLY},
1382 {NULL} /* Sentinel */
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001383};
1384
Hai Shidd391232020-12-29 20:45:07 +08001385static PyType_Slot lru_cache_type_slots[] = {
1386 {Py_tp_dealloc, lru_cache_dealloc},
1387 {Py_tp_call, lru_cache_call},
1388 {Py_tp_doc, (void *)lru_cache_doc},
1389 {Py_tp_traverse, lru_cache_tp_traverse},
1390 {Py_tp_clear, lru_cache_tp_clear},
1391 {Py_tp_methods, lru_cache_methods},
1392 {Py_tp_members, lru_cache_memberlist},
1393 {Py_tp_getset, lru_cache_getsetlist},
1394 {Py_tp_descr_get, lru_cache_descr_get},
1395 {Py_tp_new, lru_cache_new},
1396 {0, 0}
1397};
1398
1399static PyType_Spec lru_cache_type_spec = {
1400 .name = "functools._lru_cache_wrapper",
1401 .basicsize = sizeof(lru_cache_object),
1402 .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
1403 Py_TPFLAGS_METHOD_DESCRIPTOR,
1404 .slots = lru_cache_type_slots
1405};
1406
1407
Raymond Hettinger9c323f82005-02-28 19:39:44 +00001408/* module level code ********************************************************/
1409
Paulo Henrique Silva7dd549e2020-03-24 23:19:58 -03001410PyDoc_STRVAR(_functools_doc,
Thomas Wouters4d70c3d2006-06-08 14:42:34 +00001411"Tools that operate on functions.");
Raymond Hettinger9c323f82005-02-28 19:39:44 +00001412
Paulo Henrique Silva7dd549e2020-03-24 23:19:58 -03001413static PyMethodDef _functools_methods[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001414 {"reduce", functools_reduce, METH_VARARGS, functools_reduce_doc},
Serhiy Storchaka62be7422018-11-27 13:27:31 +02001415 {"cmp_to_key", (PyCFunction)(void(*)(void))functools_cmp_to_key,
Victor Stinner446c8d52011-04-05 12:21:35 +02001416 METH_VARARGS | METH_KEYWORDS, functools_cmp_to_key_doc},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001417 {NULL, NULL} /* sentinel */
Raymond Hettinger9c323f82005-02-28 19:39:44 +00001418};
1419
Paulo Henrique Silva7dd549e2020-03-24 23:19:58 -03001420static int
1421_functools_exec(PyObject *module)
Raymond Hettinger9c323f82005-02-28 19:39:44 +00001422{
Hai Shidd391232020-12-29 20:45:07 +08001423 _functools_state *state = get_functools_state(module);
1424 state->kwd_mark = _PyObject_CallNoArg((PyObject *)&PyBaseObject_Type);
1425 if (state->kwd_mark == NULL) {
1426 return -1;
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001427 }
1428
Hai Shidd391232020-12-29 20:45:07 +08001429 state->partial_type = (PyTypeObject *)PyType_FromModuleAndSpec(module,
1430 &partial_type_spec, NULL);
1431 if (state->partial_type == NULL) {
1432 return -1;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001433 }
Hai Shidd391232020-12-29 20:45:07 +08001434 if (PyModule_AddType(module, state->partial_type) < 0) {
1435 return -1;
1436 }
1437
1438 PyObject *lru_cache_type = PyType_FromModuleAndSpec(module,
1439 &lru_cache_type_spec, NULL);
1440 if (lru_cache_type == NULL) {
1441 return -1;
1442 }
1443 if (PyModule_AddType(module, (PyTypeObject *)lru_cache_type) < 0) {
1444 Py_DECREF(lru_cache_type);
1445 return -1;
1446 }
Victor Stinnerba0e49a2020-12-30 02:24:43 +01001447 Py_DECREF(lru_cache_type);
Hai Shidd391232020-12-29 20:45:07 +08001448
1449 state->keyobject_type = (PyTypeObject *)PyType_FromModuleAndSpec(module,
1450 &keyobject_type_spec, NULL);
1451 if (state->keyobject_type == NULL) {
1452 return -1;
1453 }
1454 if (PyModule_AddType(module, state->keyobject_type) < 0) {
1455 return -1;
1456 }
1457
1458 state->lru_list_elem_type = (PyTypeObject *)PyType_FromModuleAndSpec(
1459 module, &lru_list_elem_type_spec, NULL);
1460 if (state->lru_list_elem_type == NULL) {
1461 return -1;
1462 }
1463 if (PyModule_AddType(module, state->lru_list_elem_type) < 0) {
1464 return -1;
1465 }
1466
Paulo Henrique Silva7dd549e2020-03-24 23:19:58 -03001467 return 0;
1468}
1469
Hai Shidd391232020-12-29 20:45:07 +08001470static int
1471_functools_traverse(PyObject *module, visitproc visit, void *arg)
1472{
1473 _functools_state *state = get_functools_state(module);
1474 Py_VISIT(state->kwd_mark);
1475 Py_VISIT(state->partial_type);
1476 Py_VISIT(state->keyobject_type);
1477 Py_VISIT(state->lru_list_elem_type);
1478 return 0;
1479}
1480
1481static int
1482_functools_clear(PyObject *module)
1483{
1484 _functools_state *state = get_functools_state(module);
1485 Py_CLEAR(state->kwd_mark);
1486 Py_CLEAR(state->partial_type);
1487 Py_CLEAR(state->keyobject_type);
1488 Py_CLEAR(state->lru_list_elem_type);
1489 return 0;
1490}
1491
1492static void
1493_functools_free(void *module)
1494{
1495 _functools_clear((PyObject *)module);
1496}
1497
Paulo Henrique Silva7dd549e2020-03-24 23:19:58 -03001498static struct PyModuleDef_Slot _functools_slots[] = {
1499 {Py_mod_exec, _functools_exec},
1500 {0, NULL}
1501};
1502
1503static struct PyModuleDef _functools_module = {
1504 PyModuleDef_HEAD_INIT,
Hai Shidd391232020-12-29 20:45:07 +08001505 .m_name = "_functools",
1506 .m_doc = _functools_doc,
1507 .m_size = sizeof(_functools_state),
1508 .m_methods = _functools_methods,
1509 .m_slots = _functools_slots,
1510 .m_traverse = _functools_traverse,
1511 .m_clear = _functools_clear,
1512 .m_free = _functools_free,
Paulo Henrique Silva7dd549e2020-03-24 23:19:58 -03001513};
1514
1515PyMODINIT_FUNC
1516PyInit__functools(void)
1517{
1518 return PyModuleDef_Init(&_functools_module);
Raymond Hettinger9c323f82005-02-28 19:39:44 +00001519}