blob: 621b721d011df73db56994bd9be890732141a069 [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
15/* partial object **********************************************************/
16
17typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000018 PyObject_HEAD
19 PyObject *fn;
20 PyObject *args;
21 PyObject *kw;
Jeroen Demeyered184c02019-07-13 16:39:18 +020022 PyObject *dict; /* __dict__ */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000023 PyObject *weakreflist; /* List of weak references */
Jeroen Demeyered184c02019-07-13 16:39:18 +020024 vectorcallfunc vectorcall;
Raymond Hettinger9c323f82005-02-28 19:39:44 +000025} partialobject;
26
27static PyTypeObject partial_type;
28
Jeroen Demeyered184c02019-07-13 16:39:18 +020029static void partial_setvectorcall(partialobject *pto);
30
Raymond Hettinger9c323f82005-02-28 19:39:44 +000031static PyObject *
32partial_new(PyTypeObject *type, PyObject *args, PyObject *kw)
33{
Alexander Belopolskye49af342015-03-01 15:08:17 -050034 PyObject *func, *pargs, *nargs, *pkw;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000035 partialobject *pto;
Raymond Hettinger9c323f82005-02-28 19:39:44 +000036
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000037 if (PyTuple_GET_SIZE(args) < 1) {
38 PyErr_SetString(PyExc_TypeError,
39 "type 'partial' takes at least one argument");
40 return NULL;
41 }
Raymond Hettinger9c323f82005-02-28 19:39:44 +000042
Serhiy Storchaka38741282016-02-02 18:45:17 +020043 pargs = pkw = NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000044 func = PyTuple_GET_ITEM(args, 0);
Dong-hee Na1b55b652020-02-17 19:09:15 +090045 if (Py_IS_TYPE(func, &partial_type) && type == &partial_type) {
Alexander Belopolskye49af342015-03-01 15:08:17 -050046 partialobject *part = (partialobject *)func;
47 if (part->dict == NULL) {
48 pargs = part->args;
49 pkw = part->kw;
50 func = part->fn;
Serhiy Storchaka38741282016-02-02 18:45:17 +020051 assert(PyTuple_Check(pargs));
52 assert(PyDict_Check(pkw));
Alexander Belopolskye49af342015-03-01 15:08:17 -050053 }
54 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000055 if (!PyCallable_Check(func)) {
56 PyErr_SetString(PyExc_TypeError,
57 "the first argument must be callable");
58 return NULL;
59 }
Raymond Hettinger9c323f82005-02-28 19:39:44 +000060
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000061 /* create partialobject structure */
62 pto = (partialobject *)type->tp_alloc(type, 0);
63 if (pto == NULL)
64 return NULL;
Raymond Hettinger9c323f82005-02-28 19:39:44 +000065
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000066 pto->fn = func;
67 Py_INCREF(func);
Alexander Belopolskye49af342015-03-01 15:08:17 -050068
69 nargs = PyTuple_GetSlice(args, 1, PY_SSIZE_T_MAX);
70 if (nargs == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000071 Py_DECREF(pto);
72 return NULL;
73 }
Serhiy Storchaka3c749fc2017-03-25 12:10:16 +020074 if (pargs == NULL) {
Alexander Belopolskye49af342015-03-01 15:08:17 -050075 pto->args = nargs;
Alexander Belopolskye49af342015-03-01 15:08:17 -050076 }
77 else {
78 pto->args = PySequence_Concat(pargs, nargs);
Serhiy Storchaka3c749fc2017-03-25 12:10:16 +020079 Py_DECREF(nargs);
Alexander Belopolskye49af342015-03-01 15:08:17 -050080 if (pto->args == NULL) {
Alexander Belopolskye49af342015-03-01 15:08:17 -050081 Py_DECREF(pto);
82 return NULL;
83 }
Serhiy Storchaka38741282016-02-02 18:45:17 +020084 assert(PyTuple_Check(pto->args));
Alexander Belopolskye49af342015-03-01 15:08:17 -050085 }
Alexander Belopolskye49af342015-03-01 15:08:17 -050086
Serhiy Storchaka5ab81d72016-12-16 16:18:57 +020087 if (pkw == NULL || PyDict_GET_SIZE(pkw) == 0) {
Serhiy Storchaka38741282016-02-02 18:45:17 +020088 if (kw == NULL) {
89 pto->kw = PyDict_New();
Alexander Belopolskye49af342015-03-01 15:08:17 -050090 }
Serhiy Storchaka9639e4a2017-02-20 14:04:30 +020091 else if (Py_REFCNT(kw) == 1) {
Serhiy Storchaka38741282016-02-02 18:45:17 +020092 Py_INCREF(kw);
93 pto->kw = kw;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000094 }
Serhiy Storchaka9639e4a2017-02-20 14:04:30 +020095 else {
96 pto->kw = PyDict_Copy(kw);
97 }
Alexander Belopolskye49af342015-03-01 15:08:17 -050098 }
99 else {
Serhiy Storchaka38741282016-02-02 18:45:17 +0200100 pto->kw = PyDict_Copy(pkw);
101 if (kw != NULL && pto->kw != NULL) {
102 if (PyDict_Merge(pto->kw, kw, 1) != 0) {
Benjamin Petersondae2ef12015-05-09 00:29:08 -0400103 Py_DECREF(pto);
104 return NULL;
105 }
106 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000107 }
Serhiy Storchaka38741282016-02-02 18:45:17 +0200108 if (pto->kw == NULL) {
109 Py_DECREF(pto);
110 return NULL;
111 }
Raymond Hettingerc8b6d1b2005-03-08 06:14:50 +0000112
Jeroen Demeyered184c02019-07-13 16:39:18 +0200113 partial_setvectorcall(pto);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000114 return (PyObject *)pto;
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000115}
116
117static void
118partial_dealloc(partialobject *pto)
119{
INADA Naokia6296d32017-08-24 14:55:17 +0900120 /* bpo-31095: UnTrack is needed before calling any callbacks */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000121 PyObject_GC_UnTrack(pto);
122 if (pto->weakreflist != NULL)
123 PyObject_ClearWeakRefs((PyObject *) pto);
124 Py_XDECREF(pto->fn);
125 Py_XDECREF(pto->args);
126 Py_XDECREF(pto->kw);
127 Py_XDECREF(pto->dict);
128 Py_TYPE(pto)->tp_free(pto);
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000129}
130
Jeroen Demeyered184c02019-07-13 16:39:18 +0200131
132/* Merging keyword arguments using the vectorcall convention is messy, so
133 * if we would need to do that, we stop using vectorcall and fall back
134 * to using partial_call() instead. */
135_Py_NO_INLINE static PyObject *
Victor Stinner7e433732019-11-08 10:05:17 +0100136partial_vectorcall_fallback(PyThreadState *tstate, partialobject *pto,
137 PyObject *const *args, size_t nargsf,
138 PyObject *kwnames)
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000139{
Jeroen Demeyered184c02019-07-13 16:39:18 +0200140 pto->vectorcall = NULL;
141 Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
Victor Stinner7e433732019-11-08 10:05:17 +0100142 return _PyObject_MakeTpCall(tstate, (PyObject *)pto,
143 args, nargs, kwnames);
Jeroen Demeyered184c02019-07-13 16:39:18 +0200144}
145
146static PyObject *
147partial_vectorcall(partialobject *pto, PyObject *const *args,
148 size_t nargsf, PyObject *kwnames)
149{
Victor Stinner7e433732019-11-08 10:05:17 +0100150 PyThreadState *tstate = _PyThreadState_GET();
151
Jeroen Demeyered184c02019-07-13 16:39:18 +0200152 /* pto->kw is mutable, so need to check every time */
153 if (PyDict_GET_SIZE(pto->kw)) {
Victor Stinner7e433732019-11-08 10:05:17 +0100154 return partial_vectorcall_fallback(tstate, pto, args, nargsf, kwnames);
Jeroen Demeyered184c02019-07-13 16:39:18 +0200155 }
156
157 Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
158 Py_ssize_t nargs_total = nargs;
159 if (kwnames != NULL) {
160 nargs_total += PyTuple_GET_SIZE(kwnames);
161 }
162
163 PyObject **pto_args = _PyTuple_ITEMS(pto->args);
164 Py_ssize_t pto_nargs = PyTuple_GET_SIZE(pto->args);
165
166 /* Fast path if we're called without arguments */
167 if (nargs_total == 0) {
Victor Stinner7e433732019-11-08 10:05:17 +0100168 return _PyObject_VectorcallTstate(tstate, pto->fn,
169 pto_args, pto_nargs, NULL);
Jeroen Demeyered184c02019-07-13 16:39:18 +0200170 }
171
172 /* Fast path using PY_VECTORCALL_ARGUMENTS_OFFSET to prepend a single
173 * positional argument */
174 if (pto_nargs == 1 && (nargsf & PY_VECTORCALL_ARGUMENTS_OFFSET)) {
175 PyObject **newargs = (PyObject **)args - 1;
176 PyObject *tmp = newargs[0];
177 newargs[0] = pto_args[0];
Victor Stinner7e433732019-11-08 10:05:17 +0100178 PyObject *ret = _PyObject_VectorcallTstate(tstate, pto->fn,
179 newargs, nargs + 1, kwnames);
Jeroen Demeyered184c02019-07-13 16:39:18 +0200180 newargs[0] = tmp;
181 return ret;
182 }
183
184 Py_ssize_t newnargs_total = pto_nargs + nargs_total;
185
Victor Stinner0f7b0b32017-03-14 21:37:20 +0100186 PyObject *small_stack[_PY_FASTCALL_SMALL_STACK];
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000187 PyObject *ret;
Jeroen Demeyered184c02019-07-13 16:39:18 +0200188 PyObject **stack;
Victor Stinner0f7b0b32017-03-14 21:37:20 +0100189
Jeroen Demeyered184c02019-07-13 16:39:18 +0200190 if (newnargs_total <= (Py_ssize_t)Py_ARRAY_LENGTH(small_stack)) {
191 stack = small_stack;
Victor Stinner0f7b0b32017-03-14 21:37:20 +0100192 }
193 else {
Jeroen Demeyered184c02019-07-13 16:39:18 +0200194 stack = PyMem_Malloc(newnargs_total * sizeof(PyObject *));
195 if (stack == NULL) {
196 PyErr_NoMemory();
197 return NULL;
Victor Stinner0f7b0b32017-03-14 21:37:20 +0100198 }
Victor Stinner0f7b0b32017-03-14 21:37:20 +0100199 }
200
Jeroen Demeyered184c02019-07-13 16:39:18 +0200201 /* Copy to new stack, using borrowed references */
202 memcpy(stack, pto_args, pto_nargs * sizeof(PyObject*));
203 memcpy(stack + pto_nargs, args, nargs_total * sizeof(PyObject*));
204
Victor Stinner7e433732019-11-08 10:05:17 +0100205 ret = _PyObject_VectorcallTstate(tstate, pto->fn,
206 stack, pto_nargs + nargs, kwnames);
Jeroen Demeyered184c02019-07-13 16:39:18 +0200207 if (stack != small_stack) {
208 PyMem_Free(stack);
209 }
Victor Stinner0f7b0b32017-03-14 21:37:20 +0100210 return ret;
211}
212
Jeroen Demeyered184c02019-07-13 16:39:18 +0200213/* Set pto->vectorcall depending on the parameters of the partial object */
214static void
215partial_setvectorcall(partialobject *pto)
Victor Stinner0f7b0b32017-03-14 21:37:20 +0100216{
Petr Viktorinffd97532020-02-11 17:46:57 +0100217 if (PyVectorcall_Function(pto->fn) == NULL) {
Jeroen Demeyered184c02019-07-13 16:39:18 +0200218 /* Don't use vectorcall if the underlying function doesn't support it */
219 pto->vectorcall = NULL;
Victor Stinner0f7b0b32017-03-14 21:37:20 +0100220 }
Jeroen Demeyered184c02019-07-13 16:39:18 +0200221 /* We could have a special case if there are no arguments,
222 * but that is unlikely (why use partial without arguments?),
223 * so we don't optimize that */
224 else {
225 pto->vectorcall = (vectorcallfunc)partial_vectorcall;
226 }
Victor Stinner0f7b0b32017-03-14 21:37:20 +0100227}
228
Jeroen Demeyered184c02019-07-13 16:39:18 +0200229
Victor Stinner0f7b0b32017-03-14 21:37:20 +0100230static PyObject *
231partial_call(partialobject *pto, PyObject *args, PyObject *kwargs)
232{
Jeroen Demeyered184c02019-07-13 16:39:18 +0200233 assert(PyCallable_Check(pto->fn));
234 assert(PyTuple_Check(pto->args));
235 assert(PyDict_Check(pto->kw));
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000236
Jeroen Demeyered184c02019-07-13 16:39:18 +0200237 /* Merge keywords */
238 PyObject *kwargs2;
Serhiy Storchaka5ab81d72016-12-16 16:18:57 +0200239 if (PyDict_GET_SIZE(pto->kw) == 0) {
Victor Stinner0f7b0b32017-03-14 21:37:20 +0100240 /* kwargs can be NULL */
241 kwargs2 = kwargs;
242 Py_XINCREF(kwargs2);
Victor Stinnerf4d28d42016-08-23 16:22:35 +0200243 }
244 else {
Victor Stinner561ca802017-02-23 18:26:43 +0100245 /* bpo-27840, bpo-29318: dictionary of keyword parameters must be
246 copied, because a function using "**kwargs" can modify the
247 dictionary. */
Victor Stinner0f7b0b32017-03-14 21:37:20 +0100248 kwargs2 = PyDict_Copy(pto->kw);
249 if (kwargs2 == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000250 return NULL;
251 }
Victor Stinnerf4d28d42016-08-23 16:22:35 +0200252
Victor Stinner0f7b0b32017-03-14 21:37:20 +0100253 if (kwargs != NULL) {
254 if (PyDict_Merge(kwargs2, kwargs, 1) != 0) {
255 Py_DECREF(kwargs2);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000256 return NULL;
257 }
258 }
259 }
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000260
Jeroen Demeyered184c02019-07-13 16:39:18 +0200261 /* Merge positional arguments */
262 /* Note: tupleconcat() is optimized for empty tuples */
263 PyObject *args2 = PySequence_Concat(pto->args, args);
264 if (args2 == NULL) {
265 Py_XDECREF(kwargs2);
266 return NULL;
267 }
Victor Stinner0f7b0b32017-03-14 21:37:20 +0100268
Jeroen Demeyered184c02019-07-13 16:39:18 +0200269 PyObject *res = PyObject_Call(pto->fn, args2, kwargs2);
270 Py_DECREF(args2);
Victor Stinner0f7b0b32017-03-14 21:37:20 +0100271 Py_XDECREF(kwargs2);
272 return res;
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000273}
274
275static int
276partial_traverse(partialobject *pto, visitproc visit, void *arg)
277{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000278 Py_VISIT(pto->fn);
279 Py_VISIT(pto->args);
280 Py_VISIT(pto->kw);
281 Py_VISIT(pto->dict);
282 return 0;
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000283}
284
285PyDoc_STRVAR(partial_doc,
286"partial(func, *args, **keywords) - new function with partial application\n\
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000287 of the given arguments and keywords.\n");
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000288
289#define OFF(x) offsetof(partialobject, x)
290static PyMemberDef partial_memberlist[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000291 {"func", T_OBJECT, OFF(fn), READONLY,
292 "function object to use in future partial calls"},
293 {"args", T_OBJECT, OFF(args), READONLY,
294 "tuple of arguments to future partial calls"},
295 {"keywords", T_OBJECT, OFF(kw), READONLY,
296 "dictionary of keyword arguments to future partial calls"},
297 {NULL} /* Sentinel */
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000298};
299
Georg Brandlc2fb6c72006-02-21 17:49:57 +0000300static PyGetSetDef partial_getsetlist[] = {
Benjamin Peterson23d7f122012-02-19 20:02:57 -0500301 {"__dict__", PyObject_GenericGetDict, PyObject_GenericSetDict},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000302 {NULL} /* Sentinel */
Raymond Hettingerc8b6d1b2005-03-08 06:14:50 +0000303};
304
Alexander Belopolsky41e422a2010-12-01 20:05:49 +0000305static PyObject *
306partial_repr(partialobject *pto)
307{
Serhiy Storchaka179f9602016-06-12 11:44:06 +0300308 PyObject *result = NULL;
Alexander Belopolsky41e422a2010-12-01 20:05:49 +0000309 PyObject *arglist;
Alexander Belopolsky41e422a2010-12-01 20:05:49 +0000310 Py_ssize_t i, n;
Serhiy Storchaka38741282016-02-02 18:45:17 +0200311 PyObject *key, *value;
Serhiy Storchaka179f9602016-06-12 11:44:06 +0300312 int status;
313
314 status = Py_ReprEnter((PyObject *)pto);
315 if (status != 0) {
316 if (status < 0)
317 return NULL;
Nick Coghlan457fc9a2016-09-10 20:00:02 +1000318 return PyUnicode_FromString("...");
Serhiy Storchaka179f9602016-06-12 11:44:06 +0300319 }
Alexander Belopolsky41e422a2010-12-01 20:05:49 +0000320
321 arglist = PyUnicode_FromString("");
Serhiy Storchaka179f9602016-06-12 11:44:06 +0300322 if (arglist == NULL)
323 goto done;
Alexander Belopolsky41e422a2010-12-01 20:05:49 +0000324 /* Pack positional arguments */
325 assert (PyTuple_Check(pto->args));
326 n = PyTuple_GET_SIZE(pto->args);
327 for (i = 0; i < n; i++) {
Serhiy Storchaka179f9602016-06-12 11:44:06 +0300328 Py_SETREF(arglist, PyUnicode_FromFormat("%U, %R", arglist,
329 PyTuple_GET_ITEM(pto->args, i)));
330 if (arglist == NULL)
331 goto done;
Alexander Belopolsky41e422a2010-12-01 20:05:49 +0000332 }
333 /* Pack keyword arguments */
Serhiy Storchaka38741282016-02-02 18:45:17 +0200334 assert (PyDict_Check(pto->kw));
335 for (i = 0; PyDict_Next(pto->kw, &i, &key, &value);) {
Michael Seifert6c3d5272017-03-15 06:26:33 +0100336 /* Prevent key.__str__ from deleting the value. */
337 Py_INCREF(value);
338 Py_SETREF(arglist, PyUnicode_FromFormat("%U, %S=%R", arglist,
Serhiy Storchaka179f9602016-06-12 11:44:06 +0300339 key, value));
Michael Seifert6c3d5272017-03-15 06:26:33 +0100340 Py_DECREF(value);
Serhiy Storchaka179f9602016-06-12 11:44:06 +0300341 if (arglist == NULL)
342 goto done;
Alexander Belopolsky41e422a2010-12-01 20:05:49 +0000343 }
344 result = PyUnicode_FromFormat("%s(%R%U)", Py_TYPE(pto)->tp_name,
345 pto->fn, arglist);
346 Py_DECREF(arglist);
Serhiy Storchaka179f9602016-06-12 11:44:06 +0300347
348 done:
349 Py_ReprLeave((PyObject *)pto);
Alexander Belopolsky41e422a2010-12-01 20:05:49 +0000350 return result;
351}
352
Jack Diederiche0cbd692009-04-01 04:27:09 +0000353/* Pickle strategy:
354 __reduce__ by itself doesn't support getting kwargs in the unpickle
355 operation so we define a __setstate__ that replaces all the information
356 about the partial. If we only replaced part of it someone would use
Ezio Melotti13925002011-03-16 11:05:33 +0200357 it as a hook to do strange things.
Jack Diederiche0cbd692009-04-01 04:27:09 +0000358 */
359
Antoine Pitrou69f71142009-05-24 21:25:49 +0000360static PyObject *
Jack Diederiche0cbd692009-04-01 04:27:09 +0000361partial_reduce(partialobject *pto, PyObject *unused)
362{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000363 return Py_BuildValue("O(O)(OOOO)", Py_TYPE(pto), pto->fn, pto->fn,
364 pto->args, pto->kw,
365 pto->dict ? pto->dict : Py_None);
Jack Diederiche0cbd692009-04-01 04:27:09 +0000366}
367
Antoine Pitrou69f71142009-05-24 21:25:49 +0000368static PyObject *
Serhiy Storchaka19c4e0d2013-02-04 12:47:24 +0200369partial_setstate(partialobject *pto, PyObject *state)
Jack Diederiche0cbd692009-04-01 04:27:09 +0000370{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000371 PyObject *fn, *fnargs, *kw, *dict;
Serhiy Storchaka38741282016-02-02 18:45:17 +0200372
373 if (!PyTuple_Check(state) ||
374 !PyArg_ParseTuple(state, "OOOO", &fn, &fnargs, &kw, &dict) ||
375 !PyCallable_Check(fn) ||
376 !PyTuple_Check(fnargs) ||
377 (kw != Py_None && !PyDict_Check(kw)))
378 {
379 PyErr_SetString(PyExc_TypeError, "invalid partial state");
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000380 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000381 }
Serhiy Storchaka38741282016-02-02 18:45:17 +0200382
383 if(!PyTuple_CheckExact(fnargs))
384 fnargs = PySequence_Tuple(fnargs);
385 else
386 Py_INCREF(fnargs);
387 if (fnargs == NULL)
388 return NULL;
389
390 if (kw == Py_None)
391 kw = PyDict_New();
392 else if(!PyDict_CheckExact(kw))
393 kw = PyDict_Copy(kw);
394 else
395 Py_INCREF(kw);
396 if (kw == NULL) {
397 Py_DECREF(fnargs);
398 return NULL;
399 }
400
Serhiy Storchaka38741282016-02-02 18:45:17 +0200401 if (dict == Py_None)
402 dict = NULL;
403 else
404 Py_INCREF(dict);
405
Victor Stinner0f7b0b32017-03-14 21:37:20 +0100406 Py_INCREF(fn);
Serhiy Storchaka864b63c2016-04-11 09:53:37 +0300407 Py_SETREF(pto->fn, fn);
408 Py_SETREF(pto->args, fnargs);
409 Py_SETREF(pto->kw, kw);
Serhiy Storchaka48842712016-04-06 09:45:48 +0300410 Py_XSETREF(pto->dict, dict);
Jeroen Demeyered184c02019-07-13 16:39:18 +0200411 partial_setvectorcall(pto);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000412 Py_RETURN_NONE;
Jack Diederiche0cbd692009-04-01 04:27:09 +0000413}
414
415static PyMethodDef partial_methods[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000416 {"__reduce__", (PyCFunction)partial_reduce, METH_NOARGS},
Serhiy Storchaka19c4e0d2013-02-04 12:47:24 +0200417 {"__setstate__", (PyCFunction)partial_setstate, METH_O},
Ethan Smithcecf0492020-04-13 21:53:04 -0700418 {"__class_getitem__", (PyCFunction)Py_GenericAlias,
419 METH_O|METH_CLASS, PyDoc_STR("See PEP 585")},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000420 {NULL, NULL} /* sentinel */
Jack Diederiche0cbd692009-04-01 04:27:09 +0000421};
422
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000423static PyTypeObject partial_type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000424 PyVarObject_HEAD_INIT(NULL, 0)
425 "functools.partial", /* tp_name */
426 sizeof(partialobject), /* tp_basicsize */
427 0, /* tp_itemsize */
428 /* methods */
429 (destructor)partial_dealloc, /* tp_dealloc */
Jeroen Demeyered184c02019-07-13 16:39:18 +0200430 offsetof(partialobject, vectorcall),/* tp_vectorcall_offset */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000431 0, /* tp_getattr */
432 0, /* tp_setattr */
Jeroen Demeyer530f5062019-05-31 04:13:39 +0200433 0, /* tp_as_async */
Alexander Belopolsky41e422a2010-12-01 20:05:49 +0000434 (reprfunc)partial_repr, /* tp_repr */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000435 0, /* tp_as_number */
436 0, /* tp_as_sequence */
437 0, /* tp_as_mapping */
438 0, /* tp_hash */
439 (ternaryfunc)partial_call, /* tp_call */
440 0, /* tp_str */
441 PyObject_GenericGetAttr, /* tp_getattro */
442 PyObject_GenericSetAttr, /* tp_setattro */
443 0, /* tp_as_buffer */
444 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
Jeroen Demeyered184c02019-07-13 16:39:18 +0200445 Py_TPFLAGS_BASETYPE |
Petr Viktorinffd97532020-02-11 17:46:57 +0100446 Py_TPFLAGS_HAVE_VECTORCALL, /* tp_flags */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000447 partial_doc, /* tp_doc */
448 (traverseproc)partial_traverse, /* tp_traverse */
449 0, /* tp_clear */
450 0, /* tp_richcompare */
451 offsetof(partialobject, weakreflist), /* tp_weaklistoffset */
452 0, /* tp_iter */
453 0, /* tp_iternext */
454 partial_methods, /* tp_methods */
455 partial_memberlist, /* tp_members */
456 partial_getsetlist, /* tp_getset */
457 0, /* tp_base */
458 0, /* tp_dict */
459 0, /* tp_descr_get */
460 0, /* tp_descr_set */
461 offsetof(partialobject, dict), /* tp_dictoffset */
462 0, /* tp_init */
463 0, /* tp_alloc */
464 partial_new, /* tp_new */
465 PyObject_GC_Del, /* tp_free */
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000466};
467
468
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700469/* cmp_to_key ***************************************************************/
470
471typedef struct {
Victor Stinner446c8d52011-04-05 12:21:35 +0200472 PyObject_HEAD
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700473 PyObject *cmp;
474 PyObject *object;
475} keyobject;
476
477static void
478keyobject_dealloc(keyobject *ko)
479{
480 Py_DECREF(ko->cmp);
481 Py_XDECREF(ko->object);
Victor Stinner32bd68c2020-12-01 10:37:39 +0100482 PyObject_Free(ko);
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700483}
484
485static int
486keyobject_traverse(keyobject *ko, visitproc visit, void *arg)
487{
488 Py_VISIT(ko->cmp);
Hai Shi47a23fc2020-06-07 20:05:36 +0800489 Py_VISIT(ko->object);
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700490 return 0;
491}
492
Benjamin Peterson3bd97292011-04-05 17:25:14 -0500493static int
494keyobject_clear(keyobject *ko)
495{
496 Py_CLEAR(ko->cmp);
497 if (ko->object)
498 Py_CLEAR(ko->object);
499 return 0;
500}
501
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700502static PyMemberDef keyobject_members[] = {
503 {"obj", T_OBJECT,
504 offsetof(keyobject, object), 0,
505 PyDoc_STR("Value wrapped by a key function.")},
506 {NULL}
507};
508
509static PyObject *
Raymond Hettingera5632862011-04-09 12:57:00 -0700510keyobject_call(keyobject *ko, PyObject *args, PyObject *kwds);
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700511
512static PyObject *
513keyobject_richcompare(PyObject *ko, PyObject *other, int op);
514
515static PyTypeObject keyobject_type = {
516 PyVarObject_HEAD_INIT(&PyType_Type, 0)
517 "functools.KeyWrapper", /* tp_name */
518 sizeof(keyobject), /* tp_basicsize */
519 0, /* tp_itemsize */
520 /* methods */
521 (destructor)keyobject_dealloc, /* tp_dealloc */
Jeroen Demeyer530f5062019-05-31 04:13:39 +0200522 0, /* tp_vectorcall_offset */
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700523 0, /* tp_getattr */
524 0, /* tp_setattr */
Jeroen Demeyer530f5062019-05-31 04:13:39 +0200525 0, /* tp_as_async */
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700526 0, /* tp_repr */
527 0, /* tp_as_number */
528 0, /* tp_as_sequence */
529 0, /* tp_as_mapping */
530 0, /* tp_hash */
531 (ternaryfunc)keyobject_call, /* tp_call */
532 0, /* tp_str */
533 PyObject_GenericGetAttr, /* tp_getattro */
534 0, /* tp_setattro */
535 0, /* tp_as_buffer */
536 Py_TPFLAGS_DEFAULT, /* tp_flags */
537 0, /* tp_doc */
538 (traverseproc)keyobject_traverse, /* tp_traverse */
Benjamin Peterson3bd97292011-04-05 17:25:14 -0500539 (inquiry)keyobject_clear, /* tp_clear */
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700540 keyobject_richcompare, /* tp_richcompare */
541 0, /* tp_weaklistoffset */
542 0, /* tp_iter */
543 0, /* tp_iternext */
544 0, /* tp_methods */
545 keyobject_members, /* tp_members */
546 0, /* tp_getset */
547};
548
549static PyObject *
550keyobject_call(keyobject *ko, PyObject *args, PyObject *kwds)
551{
552 PyObject *object;
553 keyobject *result;
554 static char *kwargs[] = {"obj", NULL};
555
556 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:K", kwargs, &object))
557 return NULL;
558 result = PyObject_New(keyobject, &keyobject_type);
559 if (!result)
560 return NULL;
561 Py_INCREF(ko->cmp);
562 result->cmp = ko->cmp;
563 Py_INCREF(object);
564 result->object = object;
565 return (PyObject *)result;
566}
567
568static PyObject *
569keyobject_richcompare(PyObject *ko, PyObject *other, int op)
570{
571 PyObject *res;
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700572 PyObject *x;
573 PyObject *y;
574 PyObject *compare;
575 PyObject *answer;
Victor Stinnerf7a4c482016-08-19 18:52:35 +0200576 PyObject* stack[2];
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700577
Andy Lester55728702020-03-06 16:53:17 -0600578 if (!Py_IS_TYPE(other, &keyobject_type)) {
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700579 PyErr_Format(PyExc_TypeError, "other argument must be K instance");
580 return NULL;
581 }
582 compare = ((keyobject *) ko)->cmp;
583 assert(compare != NULL);
584 x = ((keyobject *) ko)->object;
585 y = ((keyobject *) other)->object;
586 if (!x || !y){
587 PyErr_Format(PyExc_AttributeError, "object");
588 return NULL;
589 }
590
591 /* Call the user's comparison function and translate the 3-way
592 * result into true or false (or error).
593 */
Victor Stinnerf7a4c482016-08-19 18:52:35 +0200594 stack[0] = x;
595 stack[1] = y;
Victor Stinner559bb6a2016-08-22 22:48:54 +0200596 res = _PyObject_FastCall(compare, stack, 2);
Victor Stinnerf7a4c482016-08-19 18:52:35 +0200597 if (res == NULL) {
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700598 return NULL;
Victor Stinnerf7a4c482016-08-19 18:52:35 +0200599 }
600
Victor Stinner37834132020-10-27 17:12:53 +0100601 answer = PyObject_RichCompare(res, _PyLong_GetZero(), op);
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700602 Py_DECREF(res);
603 return answer;
604}
605
606static PyObject *
Victor Stinner446c8d52011-04-05 12:21:35 +0200607functools_cmp_to_key(PyObject *self, PyObject *args, PyObject *kwds)
608{
609 PyObject *cmp;
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700610 static char *kwargs[] = {"mycmp", NULL};
Victor Stinner446c8d52011-04-05 12:21:35 +0200611 keyobject *object;
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700612
613 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:cmp_to_key", kwargs, &cmp))
614 return NULL;
Victor Stinner446c8d52011-04-05 12:21:35 +0200615 object = PyObject_New(keyobject, &keyobject_type);
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700616 if (!object)
617 return NULL;
618 Py_INCREF(cmp);
619 object->cmp = cmp;
620 object->object = NULL;
621 return (PyObject *)object;
622}
623
624PyDoc_STRVAR(functools_cmp_to_key_doc,
625"Convert a cmp= function into a key= function.");
626
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000627/* reduce (used to be a builtin) ********************************************/
628
629static PyObject *
630functools_reduce(PyObject *self, PyObject *args)
631{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000632 PyObject *seq, *func, *result = NULL, *it;
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000633
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000634 if (!PyArg_UnpackTuple(args, "reduce", 2, 3, &func, &seq, &result))
635 return NULL;
636 if (result != NULL)
637 Py_INCREF(result);
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000638
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000639 it = PyObject_GetIter(seq);
640 if (it == NULL) {
Alexander Belopolskye29e6bf2010-08-16 18:55:46 +0000641 if (PyErr_ExceptionMatches(PyExc_TypeError))
642 PyErr_SetString(PyExc_TypeError,
643 "reduce() arg 2 must support iteration");
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000644 Py_XDECREF(result);
645 return NULL;
646 }
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000647
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000648 if ((args = PyTuple_New(2)) == NULL)
649 goto Fail;
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000650
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000651 for (;;) {
652 PyObject *op2;
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000653
Victor Stinnera93c51e2020-02-07 00:38:59 +0100654 if (Py_REFCNT(args) > 1) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000655 Py_DECREF(args);
656 if ((args = PyTuple_New(2)) == NULL)
657 goto Fail;
658 }
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000659
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000660 op2 = PyIter_Next(it);
661 if (op2 == NULL) {
662 if (PyErr_Occurred())
663 goto Fail;
664 break;
665 }
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000666
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000667 if (result == NULL)
668 result = op2;
669 else {
Sergey Fedoseeve5f62072019-06-02 01:32:18 +0500670 /* Update the args tuple in-place */
Victor Stinnera93c51e2020-02-07 00:38:59 +0100671 assert(Py_REFCNT(args) == 1);
Sergey Fedoseeve5f62072019-06-02 01:32:18 +0500672 Py_XSETREF(_PyTuple_ITEMS(args)[0], result);
673 Py_XSETREF(_PyTuple_ITEMS(args)[1], op2);
674 if ((result = PyObject_Call(func, args, NULL)) == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000675 goto Fail;
Sergey Fedoseeve5f62072019-06-02 01:32:18 +0500676 }
Brandt Bucher226a0122020-12-04 19:45:57 -0800677 // bpo-42536: The GC may have untracked this args tuple. Since we're
678 // recycling it, make sure it's tracked again:
679 if (!_PyObject_GC_IS_TRACKED(args)) {
680 _PyObject_GC_TRACK(args);
681 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000682 }
683 }
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000684
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000685 Py_DECREF(args);
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000686
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000687 if (result == NULL)
688 PyErr_SetString(PyExc_TypeError,
Zackery Spytzcd3c2bd2020-06-28 00:40:54 -0600689 "reduce() of empty iterable with no initial value");
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000690
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000691 Py_DECREF(it);
692 return result;
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000693
694Fail:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000695 Py_XDECREF(args);
696 Py_XDECREF(result);
697 Py_DECREF(it);
698 return NULL;
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000699}
700
701PyDoc_STRVAR(functools_reduce_doc,
Zackery Spytzcd3c2bd2020-06-28 00:40:54 -0600702"reduce(function, iterable[, initial]) -> value\n\
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000703\n\
Zackery Spytzcd3c2bd2020-06-28 00:40:54 -0600704Apply a function of two arguments cumulatively to the items of a sequence\n\
705or iterable, from left to right, so as to reduce the iterable to a single\n\
706value. For example, reduce(lambda x, y: x+y, [1, 2, 3, 4, 5]) calculates\n\
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000707((((1+2)+3)+4)+5). If initial is present, it is placed before the items\n\
Zackery Spytzcd3c2bd2020-06-28 00:40:54 -0600708of the iterable in the calculation, and serves as a default when the\n\
709iterable is empty.");
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000710
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300711/* lru_cache object **********************************************************/
712
Raymond Hettinger2dda72a2019-02-08 18:55:02 -0800713/* There are four principal algorithmic differences from the pure python version:
714
715 1). The C version relies on the GIL instead of having its own reentrant lock.
716
717 2). The prev/next link fields use borrowed references.
718
719 3). For a full cache, the pure python version rotates the location of the
720 root entry so that it never has to move individual links and it can
721 limit updates to just the key and result fields. However, in the C
722 version, links are temporarily removed while the cache dict updates are
723 occurring. Afterwards, they are appended or prepended back into the
724 doubly-linked lists.
725
726 4) In the Python version, the _HashSeq class is used to prevent __hash__
727 from being called more than once. In the C version, the "known hash"
728 variants of dictionary calls as used to the same effect.
729
730*/
731
732
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300733/* this object is used delimit args and keywords in the cache keys */
734static PyObject *kwd_mark = NULL;
735
736struct lru_list_elem;
737struct lru_cache_object;
738
739typedef struct lru_list_elem {
740 PyObject_HEAD
741 struct lru_list_elem *prev, *next; /* borrowed links */
Serhiy Storchakab9d98d52015-10-02 12:47:11 +0300742 Py_hash_t hash;
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300743 PyObject *key, *result;
744} lru_list_elem;
745
746static void
747lru_list_elem_dealloc(lru_list_elem *link)
748{
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300749 Py_XDECREF(link->key);
750 Py_XDECREF(link->result);
Victor Stinner32bd68c2020-12-01 10:37:39 +0100751 PyObject_Free(link);
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300752}
753
754static PyTypeObject lru_list_elem_type = {
755 PyVarObject_HEAD_INIT(&PyType_Type, 0)
756 "functools._lru_list_elem", /* tp_name */
757 sizeof(lru_list_elem), /* tp_basicsize */
758 0, /* tp_itemsize */
759 /* methods */
760 (destructor)lru_list_elem_dealloc, /* tp_dealloc */
Jeroen Demeyer530f5062019-05-31 04:13:39 +0200761 0, /* tp_vectorcall_offset */
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300762 0, /* tp_getattr */
763 0, /* tp_setattr */
Jeroen Demeyer530f5062019-05-31 04:13:39 +0200764 0, /* tp_as_async */
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300765 0, /* tp_repr */
766 0, /* tp_as_number */
767 0, /* tp_as_sequence */
768 0, /* tp_as_mapping */
769 0, /* tp_hash */
770 0, /* tp_call */
771 0, /* tp_str */
772 0, /* tp_getattro */
773 0, /* tp_setattro */
774 0, /* tp_as_buffer */
INADA Naoki3070b712017-12-26 02:03:24 +0900775 Py_TPFLAGS_DEFAULT, /* tp_flags */
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300776};
777
778
779typedef PyObject *(*lru_cache_ternaryfunc)(struct lru_cache_object *, PyObject *, PyObject *);
780
781typedef struct lru_cache_object {
782 lru_list_elem root; /* includes PyObject_HEAD */
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300783 lru_cache_ternaryfunc wrapper;
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300784 int typed;
Raymond Hettingerd8080c02019-01-26 03:02:00 -0500785 PyObject *cache;
786 Py_ssize_t hits;
787 PyObject *func;
788 Py_ssize_t maxsize;
789 Py_ssize_t misses;
790 PyObject *cache_info_type;
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300791 PyObject *dict;
Dennis Sweeney1253c3e2020-05-05 17:14:32 -0400792 PyObject *weakreflist;
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300793} lru_cache_object;
794
795static PyTypeObject lru_cache_type;
796
797static PyObject *
798lru_cache_make_key(PyObject *args, PyObject *kwds, int typed)
799{
Raymond Hettingerdda44682017-01-08 18:04:30 -0800800 PyObject *key, *keyword, *value;
801 Py_ssize_t key_size, pos, key_pos, kwds_size;
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300802
Raymond Hettinger14adbd42019-04-20 07:20:44 -1000803 kwds_size = kwds ? PyDict_GET_SIZE(kwds) : 0;
804
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300805 /* short path, key will match args anyway, which is a tuple */
Raymond Hettinger14adbd42019-04-20 07:20:44 -1000806 if (!typed && !kwds_size) {
Raymond Hettingerd8080c02019-01-26 03:02:00 -0500807 if (PyTuple_GET_SIZE(args) == 1) {
808 key = PyTuple_GET_ITEM(args, 0);
809 if (PyUnicode_CheckExact(key) || PyLong_CheckExact(key)) {
810 /* For common scalar keys, save space by
811 dropping the enclosing args tuple */
812 Py_INCREF(key);
813 return key;
814 }
815 }
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300816 Py_INCREF(args);
817 return args;
818 }
819
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300820 key_size = PyTuple_GET_SIZE(args);
Raymond Hettingerdda44682017-01-08 18:04:30 -0800821 if (kwds_size)
822 key_size += kwds_size * 2 + 1;
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300823 if (typed)
Raymond Hettingerdda44682017-01-08 18:04:30 -0800824 key_size += PyTuple_GET_SIZE(args) + kwds_size;
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300825
826 key = PyTuple_New(key_size);
827 if (key == NULL)
Raymond Hettingerdda44682017-01-08 18:04:30 -0800828 return NULL;
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300829
830 key_pos = 0;
831 for (pos = 0; pos < PyTuple_GET_SIZE(args); ++pos) {
832 PyObject *item = PyTuple_GET_ITEM(args, pos);
833 Py_INCREF(item);
834 PyTuple_SET_ITEM(key, key_pos++, item);
835 }
Raymond Hettingerdda44682017-01-08 18:04:30 -0800836 if (kwds_size) {
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300837 Py_INCREF(kwd_mark);
838 PyTuple_SET_ITEM(key, key_pos++, kwd_mark);
Raymond Hettingerdda44682017-01-08 18:04:30 -0800839 for (pos = 0; PyDict_Next(kwds, &pos, &keyword, &value);) {
840 Py_INCREF(keyword);
841 PyTuple_SET_ITEM(key, key_pos++, keyword);
842 Py_INCREF(value);
843 PyTuple_SET_ITEM(key, key_pos++, value);
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300844 }
Raymond Hettingerdda44682017-01-08 18:04:30 -0800845 assert(key_pos == PyTuple_GET_SIZE(args) + kwds_size * 2 + 1);
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300846 }
847 if (typed) {
848 for (pos = 0; pos < PyTuple_GET_SIZE(args); ++pos) {
849 PyObject *item = (PyObject *)Py_TYPE(PyTuple_GET_ITEM(args, pos));
850 Py_INCREF(item);
851 PyTuple_SET_ITEM(key, key_pos++, item);
852 }
Raymond Hettingerdda44682017-01-08 18:04:30 -0800853 if (kwds_size) {
854 for (pos = 0; PyDict_Next(kwds, &pos, &keyword, &value);) {
855 PyObject *item = (PyObject *)Py_TYPE(value);
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300856 Py_INCREF(item);
857 PyTuple_SET_ITEM(key, key_pos++, item);
858 }
859 }
860 }
861 assert(key_pos == key_size);
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300862 return key;
863}
864
865static PyObject *
866uncached_lru_cache_wrapper(lru_cache_object *self, PyObject *args, PyObject *kwds)
867{
Raymond Hettingerffdf1c32019-01-31 15:03:38 -0800868 PyObject *result;
869
870 self->misses++;
871 result = PyObject_Call(self->func, args, kwds);
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300872 if (!result)
873 return NULL;
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300874 return result;
875}
876
877static PyObject *
878infinite_lru_cache_wrapper(lru_cache_object *self, PyObject *args, PyObject *kwds)
879{
880 PyObject *result;
Serhiy Storchakab9d98d52015-10-02 12:47:11 +0300881 Py_hash_t hash;
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300882 PyObject *key = lru_cache_make_key(args, kwds, self->typed);
883 if (!key)
884 return NULL;
Serhiy Storchakab9d98d52015-10-02 12:47:11 +0300885 hash = PyObject_Hash(key);
Yury Selivanov46a02db2016-11-09 18:55:45 -0500886 if (hash == -1) {
887 Py_DECREF(key);
Serhiy Storchakab9d98d52015-10-02 12:47:11 +0300888 return NULL;
Yury Selivanov46a02db2016-11-09 18:55:45 -0500889 }
Serhiy Storchakab9d98d52015-10-02 12:47:11 +0300890 result = _PyDict_GetItem_KnownHash(self->cache, key, hash);
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300891 if (result) {
892 Py_INCREF(result);
893 self->hits++;
894 Py_DECREF(key);
895 return result;
896 }
897 if (PyErr_Occurred()) {
898 Py_DECREF(key);
899 return NULL;
900 }
Raymond Hettingerffdf1c32019-01-31 15:03:38 -0800901 self->misses++;
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300902 result = PyObject_Call(self->func, args, kwds);
903 if (!result) {
904 Py_DECREF(key);
905 return NULL;
906 }
Serhiy Storchakab9d98d52015-10-02 12:47:11 +0300907 if (_PyDict_SetItem_KnownHash(self->cache, key, result, hash) < 0) {
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300908 Py_DECREF(result);
909 Py_DECREF(key);
910 return NULL;
911 }
912 Py_DECREF(key);
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300913 return result;
914}
915
916static void
Raymond Hettingerd8080c02019-01-26 03:02:00 -0500917lru_cache_extract_link(lru_list_elem *link)
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300918{
Raymond Hettingerd8080c02019-01-26 03:02:00 -0500919 lru_list_elem *link_prev = link->prev;
920 lru_list_elem *link_next = link->next;
921 link_prev->next = link->next;
922 link_next->prev = link->prev;
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300923}
924
925static void
926lru_cache_append_link(lru_cache_object *self, lru_list_elem *link)
927{
928 lru_list_elem *root = &self->root;
929 lru_list_elem *last = root->prev;
930 last->next = root->prev = link;
931 link->prev = last;
932 link->next = root;
933}
934
Raymond Hettingerd8080c02019-01-26 03:02:00 -0500935static void
936lru_cache_prepend_link(lru_cache_object *self, lru_list_elem *link)
937{
938 lru_list_elem *root = &self->root;
939 lru_list_elem *first = root->next;
940 first->prev = root->next = link;
941 link->prev = root;
942 link->next = first;
943}
944
945/* General note on reentrancy:
946
947 There are four dictionary calls in the bounded_lru_cache_wrapper():
948 1) The initial check for a cache match. 2) The post user-function
949 check for a cache match. 3) The deletion of the oldest entry.
950 4) The addition of the newest entry.
951
952 In all four calls, we have a known hash which lets use avoid a call
953 to __hash__(). That leaves only __eq__ as a possible source of a
954 reentrant call.
955
956 The __eq__ method call is always made for a cache hit (dict access #1).
957 Accordingly, we have make sure not modify the cache state prior to
958 this call.
959
960 The __eq__ method call is never made for the deletion (dict access #3)
961 because it is an identity match.
962
963 For the other two accesses (#2 and #4), calls to __eq__ only occur
964 when some other entry happens to have an exactly matching hash (all
965 64-bits). Though rare, this can happen, so we have to make sure to
966 either call it at the top of its code path before any cache
967 state modifications (dict access #2) or be prepared to restore
968 invariants at the end of the code path (dict access #4).
969
970 Another possible source of reentrancy is a decref which can trigger
971 arbitrary code execution. To make the code easier to reason about,
972 the decrefs are deferred to the end of the each possible code path
973 so that we know the cache is a consistent state.
974 */
975
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300976static PyObject *
977bounded_lru_cache_wrapper(lru_cache_object *self, PyObject *args, PyObject *kwds)
978{
979 lru_list_elem *link;
Raymond Hettingerd8080c02019-01-26 03:02:00 -0500980 PyObject *key, *result, *testresult;
Serhiy Storchakab9d98d52015-10-02 12:47:11 +0300981 Py_hash_t hash;
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300982
983 key = lru_cache_make_key(args, kwds, self->typed);
984 if (!key)
985 return NULL;
Serhiy Storchakab9d98d52015-10-02 12:47:11 +0300986 hash = PyObject_Hash(key);
Yury Selivanov46a02db2016-11-09 18:55:45 -0500987 if (hash == -1) {
988 Py_DECREF(key);
Serhiy Storchakab9d98d52015-10-02 12:47:11 +0300989 return NULL;
Yury Selivanov46a02db2016-11-09 18:55:45 -0500990 }
Serhiy Storchakab9d98d52015-10-02 12:47:11 +0300991 link = (lru_list_elem *)_PyDict_GetItem_KnownHash(self->cache, key, hash);
Raymond Hettingerd8080c02019-01-26 03:02:00 -0500992 if (link != NULL) {
993 lru_cache_extract_link(link);
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300994 lru_cache_append_link(self, link);
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300995 result = link->result;
Raymond Hettingerd8080c02019-01-26 03:02:00 -0500996 self->hits++;
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300997 Py_INCREF(result);
998 Py_DECREF(key);
999 return result;
1000 }
1001 if (PyErr_Occurred()) {
1002 Py_DECREF(key);
1003 return NULL;
1004 }
Raymond Hettingerd8080c02019-01-26 03:02:00 -05001005 self->misses++;
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001006 result = PyObject_Call(self->func, args, kwds);
1007 if (!result) {
1008 Py_DECREF(key);
1009 return NULL;
1010 }
Raymond Hettingerd8080c02019-01-26 03:02:00 -05001011 testresult = _PyDict_GetItem_KnownHash(self->cache, key, hash);
1012 if (testresult != NULL) {
1013 /* Getting here means that this same key was added to the cache
1014 during the PyObject_Call(). Since the link update is already
1015 done, we need only return the computed result. */
1016 Py_DECREF(key);
1017 return result;
1018 }
1019 if (PyErr_Occurred()) {
1020 /* This is an unusual case since this same lookup
1021 did not previously trigger an error during lookup.
1022 Treat it the same as an error in user function
1023 and return with the error set. */
1024 Py_DECREF(key);
1025 Py_DECREF(result);
1026 return NULL;
1027 }
1028 /* This is the normal case. The new key wasn't found before
1029 user function call and it is still not there. So we
1030 proceed normally and update the cache with the new result. */
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001031
Raymond Hettingerd8080c02019-01-26 03:02:00 -05001032 assert(self->maxsize > 0);
1033 if (PyDict_GET_SIZE(self->cache) < self->maxsize ||
1034 self->root.next == &self->root)
1035 {
1036 /* Cache is not full, so put the result in a new link */
INADA Naoki3070b712017-12-26 02:03:24 +09001037 link = (lru_list_elem *)PyObject_New(lru_list_elem,
1038 &lru_list_elem_type);
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001039 if (link == NULL) {
1040 Py_DECREF(key);
1041 Py_DECREF(result);
1042 return NULL;
1043 }
1044
Serhiy Storchakab9d98d52015-10-02 12:47:11 +03001045 link->hash = hash;
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001046 link->key = key;
1047 link->result = result;
Raymond Hettingerd8080c02019-01-26 03:02:00 -05001048 /* What is really needed here is a SetItem variant with a "no clobber"
1049 option. If the __eq__ call triggers a reentrant call that adds
1050 this same key, then this setitem call will update the cache dict
1051 with this new link, leaving the old link as an orphan (i.e. not
1052 having a cache dict entry that refers to it). */
Serhiy Storchakab9d98d52015-10-02 12:47:11 +03001053 if (_PyDict_SetItem_KnownHash(self->cache, key, (PyObject *)link,
1054 hash) < 0) {
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001055 Py_DECREF(link);
1056 return NULL;
1057 }
1058 lru_cache_append_link(self, link);
1059 Py_INCREF(result); /* for return */
Raymond Hettingerd8080c02019-01-26 03:02:00 -05001060 return result;
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001061 }
Raymond Hettingerd8080c02019-01-26 03:02:00 -05001062 /* Since the cache is full, we need to evict an old key and add
1063 a new key. Rather than free the old link and allocate a new
1064 one, we reuse the link for the new key and result and move it
1065 to front of the cache to mark it as recently used.
1066
1067 We try to assure all code paths (including errors) leave all
1068 of the links in place. Either the link is successfully
1069 updated and moved or it is restored to its old position.
1070 However if an unrecoverable error is found, it doesn't
1071 make sense to reinsert the link, so we leave it out
1072 and the cache will no longer register as full.
1073 */
1074 PyObject *oldkey, *oldresult, *popresult;
1075
1076 /* Extract the oldest item. */
1077 assert(self->root.next != &self->root);
1078 link = self->root.next;
1079 lru_cache_extract_link(link);
1080 /* Remove it from the cache.
Raymond Hettinger2dda72a2019-02-08 18:55:02 -08001081 The cache dict holds one reference to the link.
1082 We created one other reference when the link was created.
1083 The linked list only has borrowed references. */
Raymond Hettingerd8080c02019-01-26 03:02:00 -05001084 popresult = _PyDict_Pop_KnownHash(self->cache, link->key,
1085 link->hash, Py_None);
1086 if (popresult == Py_None) {
1087 /* Getting here means that the user function call or another
1088 thread has already removed the old key from the dictionary.
Raymond Hettinger2dda72a2019-02-08 18:55:02 -08001089 This link is now an orphan. Since we don't want to leave the
Raymond Hettingerd8080c02019-01-26 03:02:00 -05001090 cache in an inconsistent state, we don't restore the link. */
1091 Py_DECREF(popresult);
1092 Py_DECREF(link);
1093 Py_DECREF(key);
1094 return result;
1095 }
1096 if (popresult == NULL) {
1097 /* An error arose while trying to remove the oldest key (the one
1098 being evicted) from the cache. We restore the link to its
1099 original position as the oldest link. Then we allow the
1100 error propagate upward; treating it the same as an error
1101 arising in the user function. */
1102 lru_cache_prepend_link(self, link);
1103 Py_DECREF(key);
1104 Py_DECREF(result);
1105 return NULL;
1106 }
1107 /* Keep a reference to the old key and old result to prevent their
1108 ref counts from going to zero during the update. That will
1109 prevent potentially arbitrary object clean-up code (i.e. __del__)
1110 from running while we're still adjusting the links. */
1111 oldkey = link->key;
1112 oldresult = link->result;
1113
1114 link->hash = hash;
1115 link->key = key;
1116 link->result = result;
1117 /* Note: The link is being added to the cache dict without the
1118 prev and next fields set to valid values. We have to wait
1119 for successful insertion in the cache dict before adding the
1120 link to the linked list. Otherwise, the potentially reentrant
Raymond Hettinger2dda72a2019-02-08 18:55:02 -08001121 __eq__ call could cause the then orphan link to be visited. */
Raymond Hettingerd8080c02019-01-26 03:02:00 -05001122 if (_PyDict_SetItem_KnownHash(self->cache, key, (PyObject *)link,
1123 hash) < 0) {
1124 /* Somehow the cache dict update failed. We no longer can
1125 restore the old link. Let the error propagate upward and
1126 leave the cache short one link. */
1127 Py_DECREF(popresult);
1128 Py_DECREF(link);
1129 Py_DECREF(oldkey);
1130 Py_DECREF(oldresult);
1131 return NULL;
1132 }
1133 lru_cache_append_link(self, link);
1134 Py_INCREF(result); /* for return */
1135 Py_DECREF(popresult);
1136 Py_DECREF(oldkey);
1137 Py_DECREF(oldresult);
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001138 return result;
1139}
1140
1141static PyObject *
1142lru_cache_new(PyTypeObject *type, PyObject *args, PyObject *kw)
1143{
Serhiy Storchaka374164c2015-07-25 12:10:21 +03001144 PyObject *func, *maxsize_O, *cache_info_type, *cachedict;
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001145 int typed;
1146 lru_cache_object *obj;
1147 Py_ssize_t maxsize;
1148 PyObject *(*wrapper)(lru_cache_object *, PyObject *, PyObject *);
1149 static char *keywords[] = {"user_function", "maxsize", "typed",
1150 "cache_info_type", NULL};
1151
1152 if (!PyArg_ParseTupleAndKeywords(args, kw, "OOpO:lru_cache", keywords,
1153 &func, &maxsize_O, &typed,
1154 &cache_info_type)) {
1155 return NULL;
1156 }
1157
1158 if (!PyCallable_Check(func)) {
1159 PyErr_SetString(PyExc_TypeError,
1160 "the first argument must be callable");
1161 return NULL;
1162 }
1163
1164 /* select the caching function, and make/inc maxsize_O */
1165 if (maxsize_O == Py_None) {
1166 wrapper = infinite_lru_cache_wrapper;
1167 /* use this only to initialize lru_cache_object attribute maxsize */
1168 maxsize = -1;
1169 } else if (PyIndex_Check(maxsize_O)) {
1170 maxsize = PyNumber_AsSsize_t(maxsize_O, PyExc_OverflowError);
1171 if (maxsize == -1 && PyErr_Occurred())
1172 return NULL;
Raymond Hettingerd8080c02019-01-26 03:02:00 -05001173 if (maxsize < 0) {
1174 maxsize = 0;
1175 }
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001176 if (maxsize == 0)
1177 wrapper = uncached_lru_cache_wrapper;
1178 else
1179 wrapper = bounded_lru_cache_wrapper;
1180 } else {
1181 PyErr_SetString(PyExc_TypeError, "maxsize should be integer or None");
1182 return NULL;
1183 }
1184
Serhiy Storchaka374164c2015-07-25 12:10:21 +03001185 if (!(cachedict = PyDict_New()))
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001186 return NULL;
1187
Serhiy Storchaka374164c2015-07-25 12:10:21 +03001188 obj = (lru_cache_object *)type->tp_alloc(type, 0);
1189 if (obj == NULL) {
1190 Py_DECREF(cachedict);
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001191 return NULL;
1192 }
1193
1194 obj->root.prev = &obj->root;
1195 obj->root.next = &obj->root;
Raymond Hettingerd8080c02019-01-26 03:02:00 -05001196 obj->wrapper = wrapper;
1197 obj->typed = typed;
1198 obj->cache = cachedict;
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001199 Py_INCREF(func);
1200 obj->func = func;
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001201 obj->misses = obj->hits = 0;
Raymond Hettingerd8080c02019-01-26 03:02:00 -05001202 obj->maxsize = maxsize;
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001203 Py_INCREF(cache_info_type);
1204 obj->cache_info_type = cache_info_type;
Raymond Hettingerbba760e2020-04-20 13:47:12 -07001205 obj->dict = NULL;
Dennis Sweeney1253c3e2020-05-05 17:14:32 -04001206 obj->weakreflist = NULL;
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001207 return (PyObject *)obj;
1208}
1209
1210static lru_list_elem *
1211lru_cache_unlink_list(lru_cache_object *self)
1212{
1213 lru_list_elem *root = &self->root;
1214 lru_list_elem *link = root->next;
1215 if (link == root)
1216 return NULL;
1217 root->prev->next = NULL;
1218 root->next = root->prev = root;
1219 return link;
1220}
1221
1222static void
1223lru_cache_clear_list(lru_list_elem *link)
1224{
1225 while (link != NULL) {
1226 lru_list_elem *next = link->next;
1227 Py_DECREF(link);
1228 link = next;
1229 }
1230}
1231
1232static void
1233lru_cache_dealloc(lru_cache_object *obj)
1234{
INADA Naokia6296d32017-08-24 14:55:17 +09001235 lru_list_elem *list;
1236 /* bpo-31095: UnTrack is needed before calling any callbacks */
1237 PyObject_GC_UnTrack(obj);
Dennis Sweeney1253c3e2020-05-05 17:14:32 -04001238 if (obj->weakreflist != NULL)
1239 PyObject_ClearWeakRefs((PyObject*)obj);
INADA Naokia6296d32017-08-24 14:55:17 +09001240
1241 list = lru_cache_unlink_list(obj);
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001242 Py_XDECREF(obj->cache);
Raymond Hettingerd8080c02019-01-26 03:02:00 -05001243 Py_XDECREF(obj->func);
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001244 Py_XDECREF(obj->cache_info_type);
Raymond Hettingerd8080c02019-01-26 03:02:00 -05001245 Py_XDECREF(obj->dict);
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001246 lru_cache_clear_list(list);
1247 Py_TYPE(obj)->tp_free(obj);
1248}
1249
1250static PyObject *
1251lru_cache_call(lru_cache_object *self, PyObject *args, PyObject *kwds)
1252{
1253 return self->wrapper(self, args, kwds);
1254}
1255
1256static PyObject *
Serhiy Storchakae7070f02015-06-08 11:19:24 +03001257lru_cache_descr_get(PyObject *self, PyObject *obj, PyObject *type)
1258{
1259 if (obj == Py_None || obj == NULL) {
1260 Py_INCREF(self);
1261 return self;
1262 }
1263 return PyMethod_New(self, obj);
1264}
1265
1266static PyObject *
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001267lru_cache_cache_info(lru_cache_object *self, PyObject *unused)
1268{
Raymond Hettingerd8080c02019-01-26 03:02:00 -05001269 if (self->maxsize == -1) {
1270 return PyObject_CallFunction(self->cache_info_type, "nnOn",
1271 self->hits, self->misses, Py_None,
1272 PyDict_GET_SIZE(self->cache));
1273 }
1274 return PyObject_CallFunction(self->cache_info_type, "nnnn",
1275 self->hits, self->misses, self->maxsize,
Serhiy Storchaka5ab81d72016-12-16 16:18:57 +02001276 PyDict_GET_SIZE(self->cache));
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001277}
1278
1279static PyObject *
1280lru_cache_cache_clear(lru_cache_object *self, PyObject *unused)
1281{
1282 lru_list_elem *list = lru_cache_unlink_list(self);
1283 self->hits = self->misses = 0;
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001284 PyDict_Clear(self->cache);
1285 lru_cache_clear_list(list);
1286 Py_RETURN_NONE;
1287}
1288
Serhiy Storchaka45120f22015-10-24 09:49:56 +03001289static PyObject *
1290lru_cache_reduce(PyObject *self, PyObject *unused)
1291{
1292 return PyObject_GetAttrString(self, "__qualname__");
1293}
1294
Serhiy Storchakae4d65e32015-12-28 23:58:07 +02001295static PyObject *
1296lru_cache_copy(PyObject *self, PyObject *unused)
1297{
1298 Py_INCREF(self);
1299 return self;
1300}
1301
1302static PyObject *
1303lru_cache_deepcopy(PyObject *self, PyObject *unused)
1304{
1305 Py_INCREF(self);
1306 return self;
1307}
1308
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001309static int
1310lru_cache_tp_traverse(lru_cache_object *self, visitproc visit, void *arg)
1311{
1312 lru_list_elem *link = self->root.next;
1313 while (link != &self->root) {
1314 lru_list_elem *next = link->next;
INADA Naoki3070b712017-12-26 02:03:24 +09001315 Py_VISIT(link->key);
1316 Py_VISIT(link->result);
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001317 link = next;
1318 }
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001319 Py_VISIT(self->func);
1320 Py_VISIT(self->cache);
1321 Py_VISIT(self->cache_info_type);
1322 Py_VISIT(self->dict);
1323 return 0;
1324}
1325
1326static int
1327lru_cache_tp_clear(lru_cache_object *self)
1328{
1329 lru_list_elem *list = lru_cache_unlink_list(self);
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001330 Py_CLEAR(self->func);
1331 Py_CLEAR(self->cache);
1332 Py_CLEAR(self->cache_info_type);
1333 Py_CLEAR(self->dict);
1334 lru_cache_clear_list(list);
1335 return 0;
1336}
1337
1338
1339PyDoc_STRVAR(lru_cache_doc,
1340"Create a cached callable that wraps another function.\n\
1341\n\
1342user_function: the function being cached\n\
1343\n\
1344maxsize: 0 for no caching\n\
1345 None for unlimited cache size\n\
1346 n for a bounded cache\n\
1347\n\
1348typed: False cache f(3) and f(3.0) as identical calls\n\
1349 True cache f(3) and f(3.0) as distinct calls\n\
1350\n\
1351cache_info_type: namedtuple class with the fields:\n\
1352 hits misses currsize maxsize\n"
1353);
1354
1355static PyMethodDef lru_cache_methods[] = {
1356 {"cache_info", (PyCFunction)lru_cache_cache_info, METH_NOARGS},
1357 {"cache_clear", (PyCFunction)lru_cache_cache_clear, METH_NOARGS},
Serhiy Storchaka45120f22015-10-24 09:49:56 +03001358 {"__reduce__", (PyCFunction)lru_cache_reduce, METH_NOARGS},
Serhiy Storchakae4d65e32015-12-28 23:58:07 +02001359 {"__copy__", (PyCFunction)lru_cache_copy, METH_VARARGS},
1360 {"__deepcopy__", (PyCFunction)lru_cache_deepcopy, METH_VARARGS},
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001361 {NULL}
1362};
1363
1364static PyGetSetDef lru_cache_getsetlist[] = {
1365 {"__dict__", PyObject_GenericGetDict, PyObject_GenericSetDict},
1366 {NULL}
1367};
1368
1369static PyTypeObject lru_cache_type = {
1370 PyVarObject_HEAD_INIT(NULL, 0)
1371 "functools._lru_cache_wrapper", /* tp_name */
1372 sizeof(lru_cache_object), /* tp_basicsize */
1373 0, /* tp_itemsize */
1374 /* methods */
1375 (destructor)lru_cache_dealloc, /* tp_dealloc */
Jeroen Demeyer530f5062019-05-31 04:13:39 +02001376 0, /* tp_vectorcall_offset */
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001377 0, /* tp_getattr */
1378 0, /* tp_setattr */
Jeroen Demeyer530f5062019-05-31 04:13:39 +02001379 0, /* tp_as_async */
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001380 0, /* tp_repr */
1381 0, /* tp_as_number */
1382 0, /* tp_as_sequence */
1383 0, /* tp_as_mapping */
1384 0, /* tp_hash */
1385 (ternaryfunc)lru_cache_call, /* tp_call */
1386 0, /* tp_str */
1387 0, /* tp_getattro */
1388 0, /* tp_setattro */
1389 0, /* tp_as_buffer */
Jeroen Demeyereb65e242019-05-28 14:42:53 +02001390 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE |
1391 Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_METHOD_DESCRIPTOR,
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001392 /* tp_flags */
1393 lru_cache_doc, /* tp_doc */
1394 (traverseproc)lru_cache_tp_traverse,/* tp_traverse */
1395 (inquiry)lru_cache_tp_clear, /* tp_clear */
1396 0, /* tp_richcompare */
Dennis Sweeney1253c3e2020-05-05 17:14:32 -04001397 offsetof(lru_cache_object, weakreflist),
1398 /* tp_weaklistoffset */
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001399 0, /* tp_iter */
1400 0, /* tp_iternext */
1401 lru_cache_methods, /* tp_methods */
1402 0, /* tp_members */
1403 lru_cache_getsetlist, /* tp_getset */
1404 0, /* tp_base */
1405 0, /* tp_dict */
Serhiy Storchakae7070f02015-06-08 11:19:24 +03001406 lru_cache_descr_get, /* tp_descr_get */
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001407 0, /* tp_descr_set */
1408 offsetof(lru_cache_object, dict), /* tp_dictoffset */
1409 0, /* tp_init */
1410 0, /* tp_alloc */
1411 lru_cache_new, /* tp_new */
1412};
1413
Raymond Hettinger9c323f82005-02-28 19:39:44 +00001414/* module level code ********************************************************/
1415
Paulo Henrique Silva7dd549e2020-03-24 23:19:58 -03001416PyDoc_STRVAR(_functools_doc,
Thomas Wouters4d70c3d2006-06-08 14:42:34 +00001417"Tools that operate on functions.");
Raymond Hettinger9c323f82005-02-28 19:39:44 +00001418
Paulo Henrique Silva7dd549e2020-03-24 23:19:58 -03001419static PyMethodDef _functools_methods[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001420 {"reduce", functools_reduce, METH_VARARGS, functools_reduce_doc},
Serhiy Storchaka62be7422018-11-27 13:27:31 +02001421 {"cmp_to_key", (PyCFunction)(void(*)(void))functools_cmp_to_key,
Victor Stinner446c8d52011-04-05 12:21:35 +02001422 METH_VARARGS | METH_KEYWORDS, functools_cmp_to_key_doc},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001423 {NULL, NULL} /* sentinel */
Raymond Hettinger9c323f82005-02-28 19:39:44 +00001424};
1425
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001426static void
Paulo Henrique Silva7dd549e2020-03-24 23:19:58 -03001427_functools_free(void *m)
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001428{
Paulo Henrique Silvaeacc0742020-04-01 12:06:21 -03001429 // FIXME: Do not clear kwd_mark to avoid NULL pointer dereferencing if we have
1430 // other modules instances that could use it. Will fix when PEP-573 land
1431 // and we could move kwd_mark to a per-module state.
1432 // Py_CLEAR(kwd_mark);
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001433}
Martin v. Löwis1a214512008-06-11 05:26:20 +00001434
Paulo Henrique Silva7dd549e2020-03-24 23:19:58 -03001435static int
1436_functools_exec(PyObject *module)
Raymond Hettinger9c323f82005-02-28 19:39:44 +00001437{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001438 PyTypeObject *typelist[] = {
1439 &partial_type,
Dong-hee Na05e4a292020-03-23 01:17:34 +09001440 &lru_cache_type
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001441 };
Raymond Hettinger9c323f82005-02-28 19:39:44 +00001442
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001443 if (!kwd_mark) {
Paulo Henrique Silvab09ae3f2020-03-26 09:47:45 -03001444 kwd_mark = _PyObject_CallNoArg((PyObject *)&PyBaseObject_Type);
1445 if (!kwd_mark) {
1446 return -1;
1447 }
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001448 }
1449
Dong-hee Na05e4a292020-03-23 01:17:34 +09001450 for (size_t i = 0; i < Py_ARRAY_LENGTH(typelist); i++) {
Paulo Henrique Silva7dd549e2020-03-24 23:19:58 -03001451 if (PyModule_AddType(module, typelist[i]) < 0) {
1452 return -1;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001453 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001454 }
Paulo Henrique Silva7dd549e2020-03-24 23:19:58 -03001455 return 0;
1456}
1457
1458static struct PyModuleDef_Slot _functools_slots[] = {
1459 {Py_mod_exec, _functools_exec},
1460 {0, NULL}
1461};
1462
1463static struct PyModuleDef _functools_module = {
1464 PyModuleDef_HEAD_INIT,
1465 "_functools",
1466 _functools_doc,
1467 0,
1468 _functools_methods,
1469 _functools_slots,
1470 NULL,
1471 NULL,
1472 _functools_free,
1473};
1474
1475PyMODINIT_FUNC
1476PyInit__functools(void)
1477{
1478 return PyModuleDef_Init(&_functools_module);
Raymond Hettinger9c323f82005-02-28 19:39:44 +00001479}