blob: 9fad21fc33213c2d950c4eac2e6687ce28f9afdc [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()
Victor Stinner4a21e572020-04-15 02:35:41 +02003#include "pycore_pystate.h" // _PyThreadState_GET()
Victor Stinner384621c2020-06-22 17:27:35 +02004#include "pycore_tuple.h" // _PyTuple_ITEMS()
Victor Stinner4a21e572020-04-15 02:35:41 +02005#include "structmember.h" // PyMemberDef
Raymond Hettinger9c323f82005-02-28 19:39:44 +00006
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00007/* _functools module written and maintained
Raymond Hettinger9c323f82005-02-28 19:39:44 +00008 by Hye-Shik Chang <perky@FreeBSD.org>
9 with adaptations by Raymond Hettinger <python@rcn.com>
Thomas Wouters4d70c3d2006-06-08 14:42:34 +000010 Copyright (c) 2004, 2005, 2006 Python Software Foundation.
Raymond Hettinger9c323f82005-02-28 19:39:44 +000011 All rights reserved.
12*/
13
14/* partial object **********************************************************/
15
16typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000017 PyObject_HEAD
18 PyObject *fn;
19 PyObject *args;
20 PyObject *kw;
Jeroen Demeyered184c02019-07-13 16:39:18 +020021 PyObject *dict; /* __dict__ */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000022 PyObject *weakreflist; /* List of weak references */
Jeroen Demeyered184c02019-07-13 16:39:18 +020023 vectorcallfunc vectorcall;
Raymond Hettinger9c323f82005-02-28 19:39:44 +000024} partialobject;
25
26static PyTypeObject partial_type;
27
Jeroen Demeyered184c02019-07-13 16:39:18 +020028static void partial_setvectorcall(partialobject *pto);
29
Raymond Hettinger9c323f82005-02-28 19:39:44 +000030static PyObject *
31partial_new(PyTypeObject *type, PyObject *args, PyObject *kw)
32{
Alexander Belopolskye49af342015-03-01 15:08:17 -050033 PyObject *func, *pargs, *nargs, *pkw;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000034 partialobject *pto;
Raymond Hettinger9c323f82005-02-28 19:39:44 +000035
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000036 if (PyTuple_GET_SIZE(args) < 1) {
37 PyErr_SetString(PyExc_TypeError,
38 "type 'partial' takes at least one argument");
39 return NULL;
40 }
Raymond Hettinger9c323f82005-02-28 19:39:44 +000041
Serhiy Storchaka38741282016-02-02 18:45:17 +020042 pargs = pkw = NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000043 func = PyTuple_GET_ITEM(args, 0);
Dong-hee Na1b55b652020-02-17 19:09:15 +090044 if (Py_IS_TYPE(func, &partial_type) && type == &partial_type) {
Alexander Belopolskye49af342015-03-01 15:08:17 -050045 partialobject *part = (partialobject *)func;
46 if (part->dict == NULL) {
47 pargs = part->args;
48 pkw = part->kw;
49 func = part->fn;
Serhiy Storchaka38741282016-02-02 18:45:17 +020050 assert(PyTuple_Check(pargs));
51 assert(PyDict_Check(pkw));
Alexander Belopolskye49af342015-03-01 15:08:17 -050052 }
53 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000054 if (!PyCallable_Check(func)) {
55 PyErr_SetString(PyExc_TypeError,
56 "the first argument must be callable");
57 return NULL;
58 }
Raymond Hettinger9c323f82005-02-28 19:39:44 +000059
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000060 /* create partialobject structure */
61 pto = (partialobject *)type->tp_alloc(type, 0);
62 if (pto == NULL)
63 return NULL;
Raymond Hettinger9c323f82005-02-28 19:39:44 +000064
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000065 pto->fn = func;
66 Py_INCREF(func);
Alexander Belopolskye49af342015-03-01 15:08:17 -050067
68 nargs = PyTuple_GetSlice(args, 1, PY_SSIZE_T_MAX);
69 if (nargs == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000070 Py_DECREF(pto);
71 return NULL;
72 }
Serhiy Storchaka3c749fc2017-03-25 12:10:16 +020073 if (pargs == NULL) {
Alexander Belopolskye49af342015-03-01 15:08:17 -050074 pto->args = nargs;
Alexander Belopolskye49af342015-03-01 15:08:17 -050075 }
76 else {
77 pto->args = PySequence_Concat(pargs, nargs);
Serhiy Storchaka3c749fc2017-03-25 12:10:16 +020078 Py_DECREF(nargs);
Alexander Belopolskye49af342015-03-01 15:08:17 -050079 if (pto->args == NULL) {
Alexander Belopolskye49af342015-03-01 15:08:17 -050080 Py_DECREF(pto);
81 return NULL;
82 }
Serhiy Storchaka38741282016-02-02 18:45:17 +020083 assert(PyTuple_Check(pto->args));
Alexander Belopolskye49af342015-03-01 15:08:17 -050084 }
Alexander Belopolskye49af342015-03-01 15:08:17 -050085
Serhiy Storchaka5ab81d72016-12-16 16:18:57 +020086 if (pkw == NULL || PyDict_GET_SIZE(pkw) == 0) {
Serhiy Storchaka38741282016-02-02 18:45:17 +020087 if (kw == NULL) {
88 pto->kw = PyDict_New();
Alexander Belopolskye49af342015-03-01 15:08:17 -050089 }
Serhiy Storchaka9639e4a2017-02-20 14:04:30 +020090 else if (Py_REFCNT(kw) == 1) {
Serhiy Storchaka38741282016-02-02 18:45:17 +020091 Py_INCREF(kw);
92 pto->kw = kw;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000093 }
Serhiy Storchaka9639e4a2017-02-20 14:04:30 +020094 else {
95 pto->kw = PyDict_Copy(kw);
96 }
Alexander Belopolskye49af342015-03-01 15:08:17 -050097 }
98 else {
Serhiy Storchaka38741282016-02-02 18:45:17 +020099 pto->kw = PyDict_Copy(pkw);
100 if (kw != NULL && pto->kw != NULL) {
101 if (PyDict_Merge(pto->kw, kw, 1) != 0) {
Benjamin Petersondae2ef12015-05-09 00:29:08 -0400102 Py_DECREF(pto);
103 return NULL;
104 }
105 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000106 }
Serhiy Storchaka38741282016-02-02 18:45:17 +0200107 if (pto->kw == NULL) {
108 Py_DECREF(pto);
109 return NULL;
110 }
Raymond Hettingerc8b6d1b2005-03-08 06:14:50 +0000111
Jeroen Demeyered184c02019-07-13 16:39:18 +0200112 partial_setvectorcall(pto);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000113 return (PyObject *)pto;
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000114}
115
116static void
117partial_dealloc(partialobject *pto)
118{
INADA Naokia6296d32017-08-24 14:55:17 +0900119 /* bpo-31095: UnTrack is needed before calling any callbacks */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000120 PyObject_GC_UnTrack(pto);
121 if (pto->weakreflist != NULL)
122 PyObject_ClearWeakRefs((PyObject *) pto);
123 Py_XDECREF(pto->fn);
124 Py_XDECREF(pto->args);
125 Py_XDECREF(pto->kw);
126 Py_XDECREF(pto->dict);
127 Py_TYPE(pto)->tp_free(pto);
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000128}
129
Jeroen Demeyered184c02019-07-13 16:39:18 +0200130
131/* Merging keyword arguments using the vectorcall convention is messy, so
132 * if we would need to do that, we stop using vectorcall and fall back
133 * to using partial_call() instead. */
134_Py_NO_INLINE static PyObject *
Victor Stinner7e433732019-11-08 10:05:17 +0100135partial_vectorcall_fallback(PyThreadState *tstate, partialobject *pto,
136 PyObject *const *args, size_t nargsf,
137 PyObject *kwnames)
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000138{
Jeroen Demeyered184c02019-07-13 16:39:18 +0200139 pto->vectorcall = NULL;
140 Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
Victor Stinner7e433732019-11-08 10:05:17 +0100141 return _PyObject_MakeTpCall(tstate, (PyObject *)pto,
142 args, nargs, kwnames);
Jeroen Demeyered184c02019-07-13 16:39:18 +0200143}
144
145static PyObject *
146partial_vectorcall(partialobject *pto, PyObject *const *args,
147 size_t nargsf, PyObject *kwnames)
148{
Victor Stinner7e433732019-11-08 10:05:17 +0100149 PyThreadState *tstate = _PyThreadState_GET();
150
Jeroen Demeyered184c02019-07-13 16:39:18 +0200151 /* pto->kw is mutable, so need to check every time */
152 if (PyDict_GET_SIZE(pto->kw)) {
Victor Stinner7e433732019-11-08 10:05:17 +0100153 return partial_vectorcall_fallback(tstate, pto, args, nargsf, kwnames);
Jeroen Demeyered184c02019-07-13 16:39:18 +0200154 }
155
156 Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
157 Py_ssize_t nargs_total = nargs;
158 if (kwnames != NULL) {
159 nargs_total += PyTuple_GET_SIZE(kwnames);
160 }
161
162 PyObject **pto_args = _PyTuple_ITEMS(pto->args);
163 Py_ssize_t pto_nargs = PyTuple_GET_SIZE(pto->args);
164
165 /* Fast path if we're called without arguments */
166 if (nargs_total == 0) {
Victor Stinner7e433732019-11-08 10:05:17 +0100167 return _PyObject_VectorcallTstate(tstate, pto->fn,
168 pto_args, pto_nargs, NULL);
Jeroen Demeyered184c02019-07-13 16:39:18 +0200169 }
170
171 /* Fast path using PY_VECTORCALL_ARGUMENTS_OFFSET to prepend a single
172 * positional argument */
173 if (pto_nargs == 1 && (nargsf & PY_VECTORCALL_ARGUMENTS_OFFSET)) {
174 PyObject **newargs = (PyObject **)args - 1;
175 PyObject *tmp = newargs[0];
176 newargs[0] = pto_args[0];
Victor Stinner7e433732019-11-08 10:05:17 +0100177 PyObject *ret = _PyObject_VectorcallTstate(tstate, pto->fn,
178 newargs, nargs + 1, kwnames);
Jeroen Demeyered184c02019-07-13 16:39:18 +0200179 newargs[0] = tmp;
180 return ret;
181 }
182
183 Py_ssize_t newnargs_total = pto_nargs + nargs_total;
184
Victor Stinner0f7b0b32017-03-14 21:37:20 +0100185 PyObject *small_stack[_PY_FASTCALL_SMALL_STACK];
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000186 PyObject *ret;
Jeroen Demeyered184c02019-07-13 16:39:18 +0200187 PyObject **stack;
Victor Stinner0f7b0b32017-03-14 21:37:20 +0100188
Jeroen Demeyered184c02019-07-13 16:39:18 +0200189 if (newnargs_total <= (Py_ssize_t)Py_ARRAY_LENGTH(small_stack)) {
190 stack = small_stack;
Victor Stinner0f7b0b32017-03-14 21:37:20 +0100191 }
192 else {
Jeroen Demeyered184c02019-07-13 16:39:18 +0200193 stack = PyMem_Malloc(newnargs_total * sizeof(PyObject *));
194 if (stack == NULL) {
195 PyErr_NoMemory();
196 return NULL;
Victor Stinner0f7b0b32017-03-14 21:37:20 +0100197 }
Victor Stinner0f7b0b32017-03-14 21:37:20 +0100198 }
199
Jeroen Demeyered184c02019-07-13 16:39:18 +0200200 /* Copy to new stack, using borrowed references */
201 memcpy(stack, pto_args, pto_nargs * sizeof(PyObject*));
202 memcpy(stack + pto_nargs, args, nargs_total * sizeof(PyObject*));
203
Victor Stinner7e433732019-11-08 10:05:17 +0100204 ret = _PyObject_VectorcallTstate(tstate, pto->fn,
205 stack, pto_nargs + nargs, kwnames);
Jeroen Demeyered184c02019-07-13 16:39:18 +0200206 if (stack != small_stack) {
207 PyMem_Free(stack);
208 }
Victor Stinner0f7b0b32017-03-14 21:37:20 +0100209 return ret;
210}
211
Jeroen Demeyered184c02019-07-13 16:39:18 +0200212/* Set pto->vectorcall depending on the parameters of the partial object */
213static void
214partial_setvectorcall(partialobject *pto)
Victor Stinner0f7b0b32017-03-14 21:37:20 +0100215{
Petr Viktorinffd97532020-02-11 17:46:57 +0100216 if (PyVectorcall_Function(pto->fn) == NULL) {
Jeroen Demeyered184c02019-07-13 16:39:18 +0200217 /* Don't use vectorcall if the underlying function doesn't support it */
218 pto->vectorcall = NULL;
Victor Stinner0f7b0b32017-03-14 21:37:20 +0100219 }
Jeroen Demeyered184c02019-07-13 16:39:18 +0200220 /* We could have a special case if there are no arguments,
221 * but that is unlikely (why use partial without arguments?),
222 * so we don't optimize that */
223 else {
224 pto->vectorcall = (vectorcallfunc)partial_vectorcall;
225 }
Victor Stinner0f7b0b32017-03-14 21:37:20 +0100226}
227
Jeroen Demeyered184c02019-07-13 16:39:18 +0200228
Victor Stinner0f7b0b32017-03-14 21:37:20 +0100229static PyObject *
230partial_call(partialobject *pto, PyObject *args, PyObject *kwargs)
231{
Jeroen Demeyered184c02019-07-13 16:39:18 +0200232 assert(PyCallable_Check(pto->fn));
233 assert(PyTuple_Check(pto->args));
234 assert(PyDict_Check(pto->kw));
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000235
Jeroen Demeyered184c02019-07-13 16:39:18 +0200236 /* Merge keywords */
237 PyObject *kwargs2;
Serhiy Storchaka5ab81d72016-12-16 16:18:57 +0200238 if (PyDict_GET_SIZE(pto->kw) == 0) {
Victor Stinner0f7b0b32017-03-14 21:37:20 +0100239 /* kwargs can be NULL */
240 kwargs2 = kwargs;
241 Py_XINCREF(kwargs2);
Victor Stinnerf4d28d42016-08-23 16:22:35 +0200242 }
243 else {
Victor Stinner561ca802017-02-23 18:26:43 +0100244 /* bpo-27840, bpo-29318: dictionary of keyword parameters must be
245 copied, because a function using "**kwargs" can modify the
246 dictionary. */
Victor Stinner0f7b0b32017-03-14 21:37:20 +0100247 kwargs2 = PyDict_Copy(pto->kw);
248 if (kwargs2 == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000249 return NULL;
250 }
Victor Stinnerf4d28d42016-08-23 16:22:35 +0200251
Victor Stinner0f7b0b32017-03-14 21:37:20 +0100252 if (kwargs != NULL) {
253 if (PyDict_Merge(kwargs2, kwargs, 1) != 0) {
254 Py_DECREF(kwargs2);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000255 return NULL;
256 }
257 }
258 }
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000259
Jeroen Demeyered184c02019-07-13 16:39:18 +0200260 /* Merge positional arguments */
261 /* Note: tupleconcat() is optimized for empty tuples */
262 PyObject *args2 = PySequence_Concat(pto->args, args);
263 if (args2 == NULL) {
264 Py_XDECREF(kwargs2);
265 return NULL;
266 }
Victor Stinner0f7b0b32017-03-14 21:37:20 +0100267
Jeroen Demeyered184c02019-07-13 16:39:18 +0200268 PyObject *res = PyObject_Call(pto->fn, args2, kwargs2);
269 Py_DECREF(args2);
Victor Stinner0f7b0b32017-03-14 21:37:20 +0100270 Py_XDECREF(kwargs2);
271 return res;
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000272}
273
274static int
275partial_traverse(partialobject *pto, visitproc visit, void *arg)
276{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000277 Py_VISIT(pto->fn);
278 Py_VISIT(pto->args);
279 Py_VISIT(pto->kw);
280 Py_VISIT(pto->dict);
281 return 0;
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000282}
283
284PyDoc_STRVAR(partial_doc,
285"partial(func, *args, **keywords) - new function with partial application\n\
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000286 of the given arguments and keywords.\n");
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000287
288#define OFF(x) offsetof(partialobject, x)
289static PyMemberDef partial_memberlist[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000290 {"func", T_OBJECT, OFF(fn), READONLY,
291 "function object to use in future partial calls"},
292 {"args", T_OBJECT, OFF(args), READONLY,
293 "tuple of arguments to future partial calls"},
294 {"keywords", T_OBJECT, OFF(kw), READONLY,
295 "dictionary of keyword arguments to future partial calls"},
296 {NULL} /* Sentinel */
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000297};
298
Georg Brandlc2fb6c72006-02-21 17:49:57 +0000299static PyGetSetDef partial_getsetlist[] = {
Benjamin Peterson23d7f122012-02-19 20:02:57 -0500300 {"__dict__", PyObject_GenericGetDict, PyObject_GenericSetDict},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000301 {NULL} /* Sentinel */
Raymond Hettingerc8b6d1b2005-03-08 06:14:50 +0000302};
303
Alexander Belopolsky41e422a2010-12-01 20:05:49 +0000304static PyObject *
305partial_repr(partialobject *pto)
306{
Serhiy Storchaka179f9602016-06-12 11:44:06 +0300307 PyObject *result = NULL;
Alexander Belopolsky41e422a2010-12-01 20:05:49 +0000308 PyObject *arglist;
Alexander Belopolsky41e422a2010-12-01 20:05:49 +0000309 Py_ssize_t i, n;
Serhiy Storchaka38741282016-02-02 18:45:17 +0200310 PyObject *key, *value;
Serhiy Storchaka179f9602016-06-12 11:44:06 +0300311 int status;
312
313 status = Py_ReprEnter((PyObject *)pto);
314 if (status != 0) {
315 if (status < 0)
316 return NULL;
Nick Coghlan457fc9a2016-09-10 20:00:02 +1000317 return PyUnicode_FromString("...");
Serhiy Storchaka179f9602016-06-12 11:44:06 +0300318 }
Alexander Belopolsky41e422a2010-12-01 20:05:49 +0000319
320 arglist = PyUnicode_FromString("");
Serhiy Storchaka179f9602016-06-12 11:44:06 +0300321 if (arglist == NULL)
322 goto done;
Alexander Belopolsky41e422a2010-12-01 20:05:49 +0000323 /* Pack positional arguments */
324 assert (PyTuple_Check(pto->args));
325 n = PyTuple_GET_SIZE(pto->args);
326 for (i = 0; i < n; i++) {
Serhiy Storchaka179f9602016-06-12 11:44:06 +0300327 Py_SETREF(arglist, PyUnicode_FromFormat("%U, %R", arglist,
328 PyTuple_GET_ITEM(pto->args, i)));
329 if (arglist == NULL)
330 goto done;
Alexander Belopolsky41e422a2010-12-01 20:05:49 +0000331 }
332 /* Pack keyword arguments */
Serhiy Storchaka38741282016-02-02 18:45:17 +0200333 assert (PyDict_Check(pto->kw));
334 for (i = 0; PyDict_Next(pto->kw, &i, &key, &value);) {
Michael Seifert6c3d5272017-03-15 06:26:33 +0100335 /* Prevent key.__str__ from deleting the value. */
336 Py_INCREF(value);
337 Py_SETREF(arglist, PyUnicode_FromFormat("%U, %S=%R", arglist,
Serhiy Storchaka179f9602016-06-12 11:44:06 +0300338 key, value));
Michael Seifert6c3d5272017-03-15 06:26:33 +0100339 Py_DECREF(value);
Serhiy Storchaka179f9602016-06-12 11:44:06 +0300340 if (arglist == NULL)
341 goto done;
Alexander Belopolsky41e422a2010-12-01 20:05:49 +0000342 }
343 result = PyUnicode_FromFormat("%s(%R%U)", Py_TYPE(pto)->tp_name,
344 pto->fn, arglist);
345 Py_DECREF(arglist);
Serhiy Storchaka179f9602016-06-12 11:44:06 +0300346
347 done:
348 Py_ReprLeave((PyObject *)pto);
Alexander Belopolsky41e422a2010-12-01 20:05:49 +0000349 return result;
350}
351
Jack Diederiche0cbd692009-04-01 04:27:09 +0000352/* Pickle strategy:
353 __reduce__ by itself doesn't support getting kwargs in the unpickle
354 operation so we define a __setstate__ that replaces all the information
355 about the partial. If we only replaced part of it someone would use
Ezio Melotti13925002011-03-16 11:05:33 +0200356 it as a hook to do strange things.
Jack Diederiche0cbd692009-04-01 04:27:09 +0000357 */
358
Antoine Pitrou69f71142009-05-24 21:25:49 +0000359static PyObject *
Jack Diederiche0cbd692009-04-01 04:27:09 +0000360partial_reduce(partialobject *pto, PyObject *unused)
361{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000362 return Py_BuildValue("O(O)(OOOO)", Py_TYPE(pto), pto->fn, pto->fn,
363 pto->args, pto->kw,
364 pto->dict ? pto->dict : Py_None);
Jack Diederiche0cbd692009-04-01 04:27:09 +0000365}
366
Antoine Pitrou69f71142009-05-24 21:25:49 +0000367static PyObject *
Serhiy Storchaka19c4e0d2013-02-04 12:47:24 +0200368partial_setstate(partialobject *pto, PyObject *state)
Jack Diederiche0cbd692009-04-01 04:27:09 +0000369{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000370 PyObject *fn, *fnargs, *kw, *dict;
Serhiy Storchaka38741282016-02-02 18:45:17 +0200371
372 if (!PyTuple_Check(state) ||
373 !PyArg_ParseTuple(state, "OOOO", &fn, &fnargs, &kw, &dict) ||
374 !PyCallable_Check(fn) ||
375 !PyTuple_Check(fnargs) ||
376 (kw != Py_None && !PyDict_Check(kw)))
377 {
378 PyErr_SetString(PyExc_TypeError, "invalid partial state");
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000379 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000380 }
Serhiy Storchaka38741282016-02-02 18:45:17 +0200381
382 if(!PyTuple_CheckExact(fnargs))
383 fnargs = PySequence_Tuple(fnargs);
384 else
385 Py_INCREF(fnargs);
386 if (fnargs == NULL)
387 return NULL;
388
389 if (kw == Py_None)
390 kw = PyDict_New();
391 else if(!PyDict_CheckExact(kw))
392 kw = PyDict_Copy(kw);
393 else
394 Py_INCREF(kw);
395 if (kw == NULL) {
396 Py_DECREF(fnargs);
397 return NULL;
398 }
399
Serhiy Storchaka38741282016-02-02 18:45:17 +0200400 if (dict == Py_None)
401 dict = NULL;
402 else
403 Py_INCREF(dict);
404
Victor Stinner0f7b0b32017-03-14 21:37:20 +0100405 Py_INCREF(fn);
Serhiy Storchaka864b63c2016-04-11 09:53:37 +0300406 Py_SETREF(pto->fn, fn);
407 Py_SETREF(pto->args, fnargs);
408 Py_SETREF(pto->kw, kw);
Serhiy Storchaka48842712016-04-06 09:45:48 +0300409 Py_XSETREF(pto->dict, dict);
Jeroen Demeyered184c02019-07-13 16:39:18 +0200410 partial_setvectorcall(pto);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000411 Py_RETURN_NONE;
Jack Diederiche0cbd692009-04-01 04:27:09 +0000412}
413
414static PyMethodDef partial_methods[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000415 {"__reduce__", (PyCFunction)partial_reduce, METH_NOARGS},
Serhiy Storchaka19c4e0d2013-02-04 12:47:24 +0200416 {"__setstate__", (PyCFunction)partial_setstate, METH_O},
Ethan Smithcecf0492020-04-13 21:53:04 -0700417 {"__class_getitem__", (PyCFunction)Py_GenericAlias,
418 METH_O|METH_CLASS, PyDoc_STR("See PEP 585")},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000419 {NULL, NULL} /* sentinel */
Jack Diederiche0cbd692009-04-01 04:27:09 +0000420};
421
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000422static PyTypeObject partial_type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000423 PyVarObject_HEAD_INIT(NULL, 0)
424 "functools.partial", /* tp_name */
425 sizeof(partialobject), /* tp_basicsize */
426 0, /* tp_itemsize */
427 /* methods */
428 (destructor)partial_dealloc, /* tp_dealloc */
Jeroen Demeyered184c02019-07-13 16:39:18 +0200429 offsetof(partialobject, vectorcall),/* tp_vectorcall_offset */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000430 0, /* tp_getattr */
431 0, /* tp_setattr */
Jeroen Demeyer530f5062019-05-31 04:13:39 +0200432 0, /* tp_as_async */
Alexander Belopolsky41e422a2010-12-01 20:05:49 +0000433 (reprfunc)partial_repr, /* tp_repr */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000434 0, /* tp_as_number */
435 0, /* tp_as_sequence */
436 0, /* tp_as_mapping */
437 0, /* tp_hash */
438 (ternaryfunc)partial_call, /* tp_call */
439 0, /* tp_str */
440 PyObject_GenericGetAttr, /* tp_getattro */
441 PyObject_GenericSetAttr, /* tp_setattro */
442 0, /* tp_as_buffer */
443 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
Jeroen Demeyered184c02019-07-13 16:39:18 +0200444 Py_TPFLAGS_BASETYPE |
Petr Viktorinffd97532020-02-11 17:46:57 +0100445 Py_TPFLAGS_HAVE_VECTORCALL, /* tp_flags */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000446 partial_doc, /* tp_doc */
447 (traverseproc)partial_traverse, /* tp_traverse */
448 0, /* tp_clear */
449 0, /* tp_richcompare */
450 offsetof(partialobject, weakreflist), /* tp_weaklistoffset */
451 0, /* tp_iter */
452 0, /* tp_iternext */
453 partial_methods, /* tp_methods */
454 partial_memberlist, /* tp_members */
455 partial_getsetlist, /* tp_getset */
456 0, /* tp_base */
457 0, /* tp_dict */
458 0, /* tp_descr_get */
459 0, /* tp_descr_set */
460 offsetof(partialobject, dict), /* tp_dictoffset */
461 0, /* tp_init */
462 0, /* tp_alloc */
463 partial_new, /* tp_new */
464 PyObject_GC_Del, /* tp_free */
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000465};
466
467
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700468/* cmp_to_key ***************************************************************/
469
470typedef struct {
Victor Stinner446c8d52011-04-05 12:21:35 +0200471 PyObject_HEAD
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700472 PyObject *cmp;
473 PyObject *object;
474} keyobject;
475
476static void
477keyobject_dealloc(keyobject *ko)
478{
479 Py_DECREF(ko->cmp);
480 Py_XDECREF(ko->object);
481 PyObject_FREE(ko);
482}
483
484static int
485keyobject_traverse(keyobject *ko, visitproc visit, void *arg)
486{
487 Py_VISIT(ko->cmp);
Hai Shi47a23fc2020-06-07 20:05:36 +0800488 Py_VISIT(ko->object);
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700489 return 0;
490}
491
Benjamin Peterson3bd97292011-04-05 17:25:14 -0500492static int
493keyobject_clear(keyobject *ko)
494{
495 Py_CLEAR(ko->cmp);
496 if (ko->object)
497 Py_CLEAR(ko->object);
498 return 0;
499}
500
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700501static PyMemberDef keyobject_members[] = {
502 {"obj", T_OBJECT,
503 offsetof(keyobject, object), 0,
504 PyDoc_STR("Value wrapped by a key function.")},
505 {NULL}
506};
507
508static PyObject *
Raymond Hettingera5632862011-04-09 12:57:00 -0700509keyobject_call(keyobject *ko, PyObject *args, PyObject *kwds);
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700510
511static PyObject *
512keyobject_richcompare(PyObject *ko, PyObject *other, int op);
513
514static PyTypeObject keyobject_type = {
515 PyVarObject_HEAD_INIT(&PyType_Type, 0)
516 "functools.KeyWrapper", /* tp_name */
517 sizeof(keyobject), /* tp_basicsize */
518 0, /* tp_itemsize */
519 /* methods */
520 (destructor)keyobject_dealloc, /* tp_dealloc */
Jeroen Demeyer530f5062019-05-31 04:13:39 +0200521 0, /* tp_vectorcall_offset */
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700522 0, /* tp_getattr */
523 0, /* tp_setattr */
Jeroen Demeyer530f5062019-05-31 04:13:39 +0200524 0, /* tp_as_async */
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700525 0, /* tp_repr */
526 0, /* tp_as_number */
527 0, /* tp_as_sequence */
528 0, /* tp_as_mapping */
529 0, /* tp_hash */
530 (ternaryfunc)keyobject_call, /* tp_call */
531 0, /* tp_str */
532 PyObject_GenericGetAttr, /* tp_getattro */
533 0, /* tp_setattro */
534 0, /* tp_as_buffer */
535 Py_TPFLAGS_DEFAULT, /* tp_flags */
536 0, /* tp_doc */
537 (traverseproc)keyobject_traverse, /* tp_traverse */
Benjamin Peterson3bd97292011-04-05 17:25:14 -0500538 (inquiry)keyobject_clear, /* tp_clear */
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700539 keyobject_richcompare, /* tp_richcompare */
540 0, /* tp_weaklistoffset */
541 0, /* tp_iter */
542 0, /* tp_iternext */
543 0, /* tp_methods */
544 keyobject_members, /* tp_members */
545 0, /* tp_getset */
546};
547
548static PyObject *
549keyobject_call(keyobject *ko, PyObject *args, PyObject *kwds)
550{
551 PyObject *object;
552 keyobject *result;
553 static char *kwargs[] = {"obj", NULL};
554
555 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:K", kwargs, &object))
556 return NULL;
557 result = PyObject_New(keyobject, &keyobject_type);
558 if (!result)
559 return NULL;
560 Py_INCREF(ko->cmp);
561 result->cmp = ko->cmp;
562 Py_INCREF(object);
563 result->object = object;
564 return (PyObject *)result;
565}
566
567static PyObject *
568keyobject_richcompare(PyObject *ko, PyObject *other, int op)
569{
570 PyObject *res;
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700571 PyObject *x;
572 PyObject *y;
573 PyObject *compare;
574 PyObject *answer;
Victor Stinnerf7a4c482016-08-19 18:52:35 +0200575 PyObject* stack[2];
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700576
Andy Lester55728702020-03-06 16:53:17 -0600577 if (!Py_IS_TYPE(other, &keyobject_type)) {
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700578 PyErr_Format(PyExc_TypeError, "other argument must be K instance");
579 return NULL;
580 }
581 compare = ((keyobject *) ko)->cmp;
582 assert(compare != NULL);
583 x = ((keyobject *) ko)->object;
584 y = ((keyobject *) other)->object;
585 if (!x || !y){
586 PyErr_Format(PyExc_AttributeError, "object");
587 return NULL;
588 }
589
590 /* Call the user's comparison function and translate the 3-way
591 * result into true or false (or error).
592 */
Victor Stinnerf7a4c482016-08-19 18:52:35 +0200593 stack[0] = x;
594 stack[1] = y;
Victor Stinner559bb6a2016-08-22 22:48:54 +0200595 res = _PyObject_FastCall(compare, stack, 2);
Victor Stinnerf7a4c482016-08-19 18:52:35 +0200596 if (res == NULL) {
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700597 return NULL;
Victor Stinnerf7a4c482016-08-19 18:52:35 +0200598 }
599
Victor Stinner37834132020-10-27 17:12:53 +0100600 answer = PyObject_RichCompare(res, _PyLong_GetZero(), op);
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700601 Py_DECREF(res);
602 return answer;
603}
604
605static PyObject *
Victor Stinner446c8d52011-04-05 12:21:35 +0200606functools_cmp_to_key(PyObject *self, PyObject *args, PyObject *kwds)
607{
608 PyObject *cmp;
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700609 static char *kwargs[] = {"mycmp", NULL};
Victor Stinner446c8d52011-04-05 12:21:35 +0200610 keyobject *object;
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700611
612 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:cmp_to_key", kwargs, &cmp))
613 return NULL;
Victor Stinner446c8d52011-04-05 12:21:35 +0200614 object = PyObject_New(keyobject, &keyobject_type);
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700615 if (!object)
616 return NULL;
617 Py_INCREF(cmp);
618 object->cmp = cmp;
619 object->object = NULL;
620 return (PyObject *)object;
621}
622
623PyDoc_STRVAR(functools_cmp_to_key_doc,
624"Convert a cmp= function into a key= function.");
625
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000626/* reduce (used to be a builtin) ********************************************/
627
628static PyObject *
629functools_reduce(PyObject *self, PyObject *args)
630{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000631 PyObject *seq, *func, *result = NULL, *it;
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000632
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000633 if (!PyArg_UnpackTuple(args, "reduce", 2, 3, &func, &seq, &result))
634 return NULL;
635 if (result != NULL)
636 Py_INCREF(result);
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000637
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000638 it = PyObject_GetIter(seq);
639 if (it == NULL) {
Alexander Belopolskye29e6bf2010-08-16 18:55:46 +0000640 if (PyErr_ExceptionMatches(PyExc_TypeError))
641 PyErr_SetString(PyExc_TypeError,
642 "reduce() arg 2 must support iteration");
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000643 Py_XDECREF(result);
644 return NULL;
645 }
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000646
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000647 if ((args = PyTuple_New(2)) == NULL)
648 goto Fail;
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000649
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000650 for (;;) {
651 PyObject *op2;
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000652
Victor Stinnera93c51e2020-02-07 00:38:59 +0100653 if (Py_REFCNT(args) > 1) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000654 Py_DECREF(args);
655 if ((args = PyTuple_New(2)) == NULL)
656 goto Fail;
657 }
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000658
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000659 op2 = PyIter_Next(it);
660 if (op2 == NULL) {
661 if (PyErr_Occurred())
662 goto Fail;
663 break;
664 }
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000665
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000666 if (result == NULL)
667 result = op2;
668 else {
Sergey Fedoseeve5f62072019-06-02 01:32:18 +0500669 /* Update the args tuple in-place */
Victor Stinnera93c51e2020-02-07 00:38:59 +0100670 assert(Py_REFCNT(args) == 1);
Sergey Fedoseeve5f62072019-06-02 01:32:18 +0500671 Py_XSETREF(_PyTuple_ITEMS(args)[0], result);
672 Py_XSETREF(_PyTuple_ITEMS(args)[1], op2);
673 if ((result = PyObject_Call(func, args, NULL)) == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000674 goto Fail;
Sergey Fedoseeve5f62072019-06-02 01:32:18 +0500675 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000676 }
677 }
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000678
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000679 Py_DECREF(args);
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000680
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000681 if (result == NULL)
682 PyErr_SetString(PyExc_TypeError,
Zackery Spytzcd3c2bd2020-06-28 00:40:54 -0600683 "reduce() of empty iterable with no initial value");
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000684
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000685 Py_DECREF(it);
686 return result;
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000687
688Fail:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000689 Py_XDECREF(args);
690 Py_XDECREF(result);
691 Py_DECREF(it);
692 return NULL;
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000693}
694
695PyDoc_STRVAR(functools_reduce_doc,
Zackery Spytzcd3c2bd2020-06-28 00:40:54 -0600696"reduce(function, iterable[, initial]) -> value\n\
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000697\n\
Zackery Spytzcd3c2bd2020-06-28 00:40:54 -0600698Apply a function of two arguments cumulatively to the items of a sequence\n\
699or iterable, from left to right, so as to reduce the iterable to a single\n\
700value. For example, reduce(lambda x, y: x+y, [1, 2, 3, 4, 5]) calculates\n\
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000701((((1+2)+3)+4)+5). If initial is present, it is placed before the items\n\
Zackery Spytzcd3c2bd2020-06-28 00:40:54 -0600702of the iterable in the calculation, and serves as a default when the\n\
703iterable is empty.");
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000704
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300705/* lru_cache object **********************************************************/
706
Raymond Hettinger2dda72a2019-02-08 18:55:02 -0800707/* There are four principal algorithmic differences from the pure python version:
708
709 1). The C version relies on the GIL instead of having its own reentrant lock.
710
711 2). The prev/next link fields use borrowed references.
712
713 3). For a full cache, the pure python version rotates the location of the
714 root entry so that it never has to move individual links and it can
715 limit updates to just the key and result fields. However, in the C
716 version, links are temporarily removed while the cache dict updates are
717 occurring. Afterwards, they are appended or prepended back into the
718 doubly-linked lists.
719
720 4) In the Python version, the _HashSeq class is used to prevent __hash__
721 from being called more than once. In the C version, the "known hash"
722 variants of dictionary calls as used to the same effect.
723
724*/
725
726
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300727/* this object is used delimit args and keywords in the cache keys */
728static PyObject *kwd_mark = NULL;
729
730struct lru_list_elem;
731struct lru_cache_object;
732
733typedef struct lru_list_elem {
734 PyObject_HEAD
735 struct lru_list_elem *prev, *next; /* borrowed links */
Serhiy Storchakab9d98d52015-10-02 12:47:11 +0300736 Py_hash_t hash;
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300737 PyObject *key, *result;
738} lru_list_elem;
739
740static void
741lru_list_elem_dealloc(lru_list_elem *link)
742{
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300743 Py_XDECREF(link->key);
744 Py_XDECREF(link->result);
INADA Naoki3070b712017-12-26 02:03:24 +0900745 PyObject_Del(link);
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300746}
747
748static PyTypeObject lru_list_elem_type = {
749 PyVarObject_HEAD_INIT(&PyType_Type, 0)
750 "functools._lru_list_elem", /* tp_name */
751 sizeof(lru_list_elem), /* tp_basicsize */
752 0, /* tp_itemsize */
753 /* methods */
754 (destructor)lru_list_elem_dealloc, /* tp_dealloc */
Jeroen Demeyer530f5062019-05-31 04:13:39 +0200755 0, /* tp_vectorcall_offset */
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300756 0, /* tp_getattr */
757 0, /* tp_setattr */
Jeroen Demeyer530f5062019-05-31 04:13:39 +0200758 0, /* tp_as_async */
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300759 0, /* tp_repr */
760 0, /* tp_as_number */
761 0, /* tp_as_sequence */
762 0, /* tp_as_mapping */
763 0, /* tp_hash */
764 0, /* tp_call */
765 0, /* tp_str */
766 0, /* tp_getattro */
767 0, /* tp_setattro */
768 0, /* tp_as_buffer */
INADA Naoki3070b712017-12-26 02:03:24 +0900769 Py_TPFLAGS_DEFAULT, /* tp_flags */
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300770};
771
772
773typedef PyObject *(*lru_cache_ternaryfunc)(struct lru_cache_object *, PyObject *, PyObject *);
774
775typedef struct lru_cache_object {
776 lru_list_elem root; /* includes PyObject_HEAD */
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300777 lru_cache_ternaryfunc wrapper;
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300778 int typed;
Raymond Hettingerd8080c02019-01-26 03:02:00 -0500779 PyObject *cache;
780 Py_ssize_t hits;
781 PyObject *func;
782 Py_ssize_t maxsize;
783 Py_ssize_t misses;
784 PyObject *cache_info_type;
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300785 PyObject *dict;
Dennis Sweeney1253c3e2020-05-05 17:14:32 -0400786 PyObject *weakreflist;
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300787} lru_cache_object;
788
789static PyTypeObject lru_cache_type;
790
791static PyObject *
792lru_cache_make_key(PyObject *args, PyObject *kwds, int typed)
793{
Raymond Hettingerdda44682017-01-08 18:04:30 -0800794 PyObject *key, *keyword, *value;
795 Py_ssize_t key_size, pos, key_pos, kwds_size;
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300796
Raymond Hettinger14adbd42019-04-20 07:20:44 -1000797 kwds_size = kwds ? PyDict_GET_SIZE(kwds) : 0;
798
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300799 /* short path, key will match args anyway, which is a tuple */
Raymond Hettinger14adbd42019-04-20 07:20:44 -1000800 if (!typed && !kwds_size) {
Raymond Hettingerd8080c02019-01-26 03:02:00 -0500801 if (PyTuple_GET_SIZE(args) == 1) {
802 key = PyTuple_GET_ITEM(args, 0);
803 if (PyUnicode_CheckExact(key) || PyLong_CheckExact(key)) {
804 /* For common scalar keys, save space by
805 dropping the enclosing args tuple */
806 Py_INCREF(key);
807 return key;
808 }
809 }
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300810 Py_INCREF(args);
811 return args;
812 }
813
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300814 key_size = PyTuple_GET_SIZE(args);
Raymond Hettingerdda44682017-01-08 18:04:30 -0800815 if (kwds_size)
816 key_size += kwds_size * 2 + 1;
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300817 if (typed)
Raymond Hettingerdda44682017-01-08 18:04:30 -0800818 key_size += PyTuple_GET_SIZE(args) + kwds_size;
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300819
820 key = PyTuple_New(key_size);
821 if (key == NULL)
Raymond Hettingerdda44682017-01-08 18:04:30 -0800822 return NULL;
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300823
824 key_pos = 0;
825 for (pos = 0; pos < PyTuple_GET_SIZE(args); ++pos) {
826 PyObject *item = PyTuple_GET_ITEM(args, pos);
827 Py_INCREF(item);
828 PyTuple_SET_ITEM(key, key_pos++, item);
829 }
Raymond Hettingerdda44682017-01-08 18:04:30 -0800830 if (kwds_size) {
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300831 Py_INCREF(kwd_mark);
832 PyTuple_SET_ITEM(key, key_pos++, kwd_mark);
Raymond Hettingerdda44682017-01-08 18:04:30 -0800833 for (pos = 0; PyDict_Next(kwds, &pos, &keyword, &value);) {
834 Py_INCREF(keyword);
835 PyTuple_SET_ITEM(key, key_pos++, keyword);
836 Py_INCREF(value);
837 PyTuple_SET_ITEM(key, key_pos++, value);
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300838 }
Raymond Hettingerdda44682017-01-08 18:04:30 -0800839 assert(key_pos == PyTuple_GET_SIZE(args) + kwds_size * 2 + 1);
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300840 }
841 if (typed) {
842 for (pos = 0; pos < PyTuple_GET_SIZE(args); ++pos) {
843 PyObject *item = (PyObject *)Py_TYPE(PyTuple_GET_ITEM(args, pos));
844 Py_INCREF(item);
845 PyTuple_SET_ITEM(key, key_pos++, item);
846 }
Raymond Hettingerdda44682017-01-08 18:04:30 -0800847 if (kwds_size) {
848 for (pos = 0; PyDict_Next(kwds, &pos, &keyword, &value);) {
849 PyObject *item = (PyObject *)Py_TYPE(value);
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300850 Py_INCREF(item);
851 PyTuple_SET_ITEM(key, key_pos++, item);
852 }
853 }
854 }
855 assert(key_pos == key_size);
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300856 return key;
857}
858
859static PyObject *
860uncached_lru_cache_wrapper(lru_cache_object *self, PyObject *args, PyObject *kwds)
861{
Raymond Hettingerffdf1c32019-01-31 15:03:38 -0800862 PyObject *result;
863
864 self->misses++;
865 result = PyObject_Call(self->func, args, kwds);
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300866 if (!result)
867 return NULL;
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300868 return result;
869}
870
871static PyObject *
872infinite_lru_cache_wrapper(lru_cache_object *self, PyObject *args, PyObject *kwds)
873{
874 PyObject *result;
Serhiy Storchakab9d98d52015-10-02 12:47:11 +0300875 Py_hash_t hash;
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300876 PyObject *key = lru_cache_make_key(args, kwds, self->typed);
877 if (!key)
878 return NULL;
Serhiy Storchakab9d98d52015-10-02 12:47:11 +0300879 hash = PyObject_Hash(key);
Yury Selivanov46a02db2016-11-09 18:55:45 -0500880 if (hash == -1) {
881 Py_DECREF(key);
Serhiy Storchakab9d98d52015-10-02 12:47:11 +0300882 return NULL;
Yury Selivanov46a02db2016-11-09 18:55:45 -0500883 }
Serhiy Storchakab9d98d52015-10-02 12:47:11 +0300884 result = _PyDict_GetItem_KnownHash(self->cache, key, hash);
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300885 if (result) {
886 Py_INCREF(result);
887 self->hits++;
888 Py_DECREF(key);
889 return result;
890 }
891 if (PyErr_Occurred()) {
892 Py_DECREF(key);
893 return NULL;
894 }
Raymond Hettingerffdf1c32019-01-31 15:03:38 -0800895 self->misses++;
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300896 result = PyObject_Call(self->func, args, kwds);
897 if (!result) {
898 Py_DECREF(key);
899 return NULL;
900 }
Serhiy Storchakab9d98d52015-10-02 12:47:11 +0300901 if (_PyDict_SetItem_KnownHash(self->cache, key, result, hash) < 0) {
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300902 Py_DECREF(result);
903 Py_DECREF(key);
904 return NULL;
905 }
906 Py_DECREF(key);
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300907 return result;
908}
909
910static void
Raymond Hettingerd8080c02019-01-26 03:02:00 -0500911lru_cache_extract_link(lru_list_elem *link)
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300912{
Raymond Hettingerd8080c02019-01-26 03:02:00 -0500913 lru_list_elem *link_prev = link->prev;
914 lru_list_elem *link_next = link->next;
915 link_prev->next = link->next;
916 link_next->prev = link->prev;
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300917}
918
919static void
920lru_cache_append_link(lru_cache_object *self, lru_list_elem *link)
921{
922 lru_list_elem *root = &self->root;
923 lru_list_elem *last = root->prev;
924 last->next = root->prev = link;
925 link->prev = last;
926 link->next = root;
927}
928
Raymond Hettingerd8080c02019-01-26 03:02:00 -0500929static void
930lru_cache_prepend_link(lru_cache_object *self, lru_list_elem *link)
931{
932 lru_list_elem *root = &self->root;
933 lru_list_elem *first = root->next;
934 first->prev = root->next = link;
935 link->prev = root;
936 link->next = first;
937}
938
939/* General note on reentrancy:
940
941 There are four dictionary calls in the bounded_lru_cache_wrapper():
942 1) The initial check for a cache match. 2) The post user-function
943 check for a cache match. 3) The deletion of the oldest entry.
944 4) The addition of the newest entry.
945
946 In all four calls, we have a known hash which lets use avoid a call
947 to __hash__(). That leaves only __eq__ as a possible source of a
948 reentrant call.
949
950 The __eq__ method call is always made for a cache hit (dict access #1).
951 Accordingly, we have make sure not modify the cache state prior to
952 this call.
953
954 The __eq__ method call is never made for the deletion (dict access #3)
955 because it is an identity match.
956
957 For the other two accesses (#2 and #4), calls to __eq__ only occur
958 when some other entry happens to have an exactly matching hash (all
959 64-bits). Though rare, this can happen, so we have to make sure to
960 either call it at the top of its code path before any cache
961 state modifications (dict access #2) or be prepared to restore
962 invariants at the end of the code path (dict access #4).
963
964 Another possible source of reentrancy is a decref which can trigger
965 arbitrary code execution. To make the code easier to reason about,
966 the decrefs are deferred to the end of the each possible code path
967 so that we know the cache is a consistent state.
968 */
969
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300970static PyObject *
971bounded_lru_cache_wrapper(lru_cache_object *self, PyObject *args, PyObject *kwds)
972{
973 lru_list_elem *link;
Raymond Hettingerd8080c02019-01-26 03:02:00 -0500974 PyObject *key, *result, *testresult;
Serhiy Storchakab9d98d52015-10-02 12:47:11 +0300975 Py_hash_t hash;
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300976
977 key = lru_cache_make_key(args, kwds, self->typed);
978 if (!key)
979 return NULL;
Serhiy Storchakab9d98d52015-10-02 12:47:11 +0300980 hash = PyObject_Hash(key);
Yury Selivanov46a02db2016-11-09 18:55:45 -0500981 if (hash == -1) {
982 Py_DECREF(key);
Serhiy Storchakab9d98d52015-10-02 12:47:11 +0300983 return NULL;
Yury Selivanov46a02db2016-11-09 18:55:45 -0500984 }
Serhiy Storchakab9d98d52015-10-02 12:47:11 +0300985 link = (lru_list_elem *)_PyDict_GetItem_KnownHash(self->cache, key, hash);
Raymond Hettingerd8080c02019-01-26 03:02:00 -0500986 if (link != NULL) {
987 lru_cache_extract_link(link);
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300988 lru_cache_append_link(self, link);
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300989 result = link->result;
Raymond Hettingerd8080c02019-01-26 03:02:00 -0500990 self->hits++;
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300991 Py_INCREF(result);
992 Py_DECREF(key);
993 return result;
994 }
995 if (PyErr_Occurred()) {
996 Py_DECREF(key);
997 return NULL;
998 }
Raymond Hettingerd8080c02019-01-26 03:02:00 -0500999 self->misses++;
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001000 result = PyObject_Call(self->func, args, kwds);
1001 if (!result) {
1002 Py_DECREF(key);
1003 return NULL;
1004 }
Raymond Hettingerd8080c02019-01-26 03:02:00 -05001005 testresult = _PyDict_GetItem_KnownHash(self->cache, key, hash);
1006 if (testresult != NULL) {
1007 /* Getting here means that this same key was added to the cache
1008 during the PyObject_Call(). Since the link update is already
1009 done, we need only return the computed result. */
1010 Py_DECREF(key);
1011 return result;
1012 }
1013 if (PyErr_Occurred()) {
1014 /* This is an unusual case since this same lookup
1015 did not previously trigger an error during lookup.
1016 Treat it the same as an error in user function
1017 and return with the error set. */
1018 Py_DECREF(key);
1019 Py_DECREF(result);
1020 return NULL;
1021 }
1022 /* This is the normal case. The new key wasn't found before
1023 user function call and it is still not there. So we
1024 proceed normally and update the cache with the new result. */
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001025
Raymond Hettingerd8080c02019-01-26 03:02:00 -05001026 assert(self->maxsize > 0);
1027 if (PyDict_GET_SIZE(self->cache) < self->maxsize ||
1028 self->root.next == &self->root)
1029 {
1030 /* Cache is not full, so put the result in a new link */
INADA Naoki3070b712017-12-26 02:03:24 +09001031 link = (lru_list_elem *)PyObject_New(lru_list_elem,
1032 &lru_list_elem_type);
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001033 if (link == NULL) {
1034 Py_DECREF(key);
1035 Py_DECREF(result);
1036 return NULL;
1037 }
1038
Serhiy Storchakab9d98d52015-10-02 12:47:11 +03001039 link->hash = hash;
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001040 link->key = key;
1041 link->result = result;
Raymond Hettingerd8080c02019-01-26 03:02:00 -05001042 /* What is really needed here is a SetItem variant with a "no clobber"
1043 option. If the __eq__ call triggers a reentrant call that adds
1044 this same key, then this setitem call will update the cache dict
1045 with this new link, leaving the old link as an orphan (i.e. not
1046 having a cache dict entry that refers to it). */
Serhiy Storchakab9d98d52015-10-02 12:47:11 +03001047 if (_PyDict_SetItem_KnownHash(self->cache, key, (PyObject *)link,
1048 hash) < 0) {
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001049 Py_DECREF(link);
1050 return NULL;
1051 }
1052 lru_cache_append_link(self, link);
1053 Py_INCREF(result); /* for return */
Raymond Hettingerd8080c02019-01-26 03:02:00 -05001054 return result;
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001055 }
Raymond Hettingerd8080c02019-01-26 03:02:00 -05001056 /* Since the cache is full, we need to evict an old key and add
1057 a new key. Rather than free the old link and allocate a new
1058 one, we reuse the link for the new key and result and move it
1059 to front of the cache to mark it as recently used.
1060
1061 We try to assure all code paths (including errors) leave all
1062 of the links in place. Either the link is successfully
1063 updated and moved or it is restored to its old position.
1064 However if an unrecoverable error is found, it doesn't
1065 make sense to reinsert the link, so we leave it out
1066 and the cache will no longer register as full.
1067 */
1068 PyObject *oldkey, *oldresult, *popresult;
1069
1070 /* Extract the oldest item. */
1071 assert(self->root.next != &self->root);
1072 link = self->root.next;
1073 lru_cache_extract_link(link);
1074 /* Remove it from the cache.
Raymond Hettinger2dda72a2019-02-08 18:55:02 -08001075 The cache dict holds one reference to the link.
1076 We created one other reference when the link was created.
1077 The linked list only has borrowed references. */
Raymond Hettingerd8080c02019-01-26 03:02:00 -05001078 popresult = _PyDict_Pop_KnownHash(self->cache, link->key,
1079 link->hash, Py_None);
1080 if (popresult == Py_None) {
1081 /* Getting here means that the user function call or another
1082 thread has already removed the old key from the dictionary.
Raymond Hettinger2dda72a2019-02-08 18:55:02 -08001083 This link is now an orphan. Since we don't want to leave the
Raymond Hettingerd8080c02019-01-26 03:02:00 -05001084 cache in an inconsistent state, we don't restore the link. */
1085 Py_DECREF(popresult);
1086 Py_DECREF(link);
1087 Py_DECREF(key);
1088 return result;
1089 }
1090 if (popresult == NULL) {
1091 /* An error arose while trying to remove the oldest key (the one
1092 being evicted) from the cache. We restore the link to its
1093 original position as the oldest link. Then we allow the
1094 error propagate upward; treating it the same as an error
1095 arising in the user function. */
1096 lru_cache_prepend_link(self, link);
1097 Py_DECREF(key);
1098 Py_DECREF(result);
1099 return NULL;
1100 }
1101 /* Keep a reference to the old key and old result to prevent their
1102 ref counts from going to zero during the update. That will
1103 prevent potentially arbitrary object clean-up code (i.e. __del__)
1104 from running while we're still adjusting the links. */
1105 oldkey = link->key;
1106 oldresult = link->result;
1107
1108 link->hash = hash;
1109 link->key = key;
1110 link->result = result;
1111 /* Note: The link is being added to the cache dict without the
1112 prev and next fields set to valid values. We have to wait
1113 for successful insertion in the cache dict before adding the
1114 link to the linked list. Otherwise, the potentially reentrant
Raymond Hettinger2dda72a2019-02-08 18:55:02 -08001115 __eq__ call could cause the then orphan link to be visited. */
Raymond Hettingerd8080c02019-01-26 03:02:00 -05001116 if (_PyDict_SetItem_KnownHash(self->cache, key, (PyObject *)link,
1117 hash) < 0) {
1118 /* Somehow the cache dict update failed. We no longer can
1119 restore the old link. Let the error propagate upward and
1120 leave the cache short one link. */
1121 Py_DECREF(popresult);
1122 Py_DECREF(link);
1123 Py_DECREF(oldkey);
1124 Py_DECREF(oldresult);
1125 return NULL;
1126 }
1127 lru_cache_append_link(self, link);
1128 Py_INCREF(result); /* for return */
1129 Py_DECREF(popresult);
1130 Py_DECREF(oldkey);
1131 Py_DECREF(oldresult);
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001132 return result;
1133}
1134
1135static PyObject *
1136lru_cache_new(PyTypeObject *type, PyObject *args, PyObject *kw)
1137{
Serhiy Storchaka374164c2015-07-25 12:10:21 +03001138 PyObject *func, *maxsize_O, *cache_info_type, *cachedict;
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001139 int typed;
1140 lru_cache_object *obj;
1141 Py_ssize_t maxsize;
1142 PyObject *(*wrapper)(lru_cache_object *, PyObject *, PyObject *);
1143 static char *keywords[] = {"user_function", "maxsize", "typed",
1144 "cache_info_type", NULL};
1145
1146 if (!PyArg_ParseTupleAndKeywords(args, kw, "OOpO:lru_cache", keywords,
1147 &func, &maxsize_O, &typed,
1148 &cache_info_type)) {
1149 return NULL;
1150 }
1151
1152 if (!PyCallable_Check(func)) {
1153 PyErr_SetString(PyExc_TypeError,
1154 "the first argument must be callable");
1155 return NULL;
1156 }
1157
1158 /* select the caching function, and make/inc maxsize_O */
1159 if (maxsize_O == Py_None) {
1160 wrapper = infinite_lru_cache_wrapper;
1161 /* use this only to initialize lru_cache_object attribute maxsize */
1162 maxsize = -1;
1163 } else if (PyIndex_Check(maxsize_O)) {
1164 maxsize = PyNumber_AsSsize_t(maxsize_O, PyExc_OverflowError);
1165 if (maxsize == -1 && PyErr_Occurred())
1166 return NULL;
Raymond Hettingerd8080c02019-01-26 03:02:00 -05001167 if (maxsize < 0) {
1168 maxsize = 0;
1169 }
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001170 if (maxsize == 0)
1171 wrapper = uncached_lru_cache_wrapper;
1172 else
1173 wrapper = bounded_lru_cache_wrapper;
1174 } else {
1175 PyErr_SetString(PyExc_TypeError, "maxsize should be integer or None");
1176 return NULL;
1177 }
1178
Serhiy Storchaka374164c2015-07-25 12:10:21 +03001179 if (!(cachedict = PyDict_New()))
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001180 return NULL;
1181
Serhiy Storchaka374164c2015-07-25 12:10:21 +03001182 obj = (lru_cache_object *)type->tp_alloc(type, 0);
1183 if (obj == NULL) {
1184 Py_DECREF(cachedict);
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001185 return NULL;
1186 }
1187
1188 obj->root.prev = &obj->root;
1189 obj->root.next = &obj->root;
Raymond Hettingerd8080c02019-01-26 03:02:00 -05001190 obj->wrapper = wrapper;
1191 obj->typed = typed;
1192 obj->cache = cachedict;
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001193 Py_INCREF(func);
1194 obj->func = func;
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001195 obj->misses = obj->hits = 0;
Raymond Hettingerd8080c02019-01-26 03:02:00 -05001196 obj->maxsize = maxsize;
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001197 Py_INCREF(cache_info_type);
1198 obj->cache_info_type = cache_info_type;
Raymond Hettingerbba760e2020-04-20 13:47:12 -07001199 obj->dict = NULL;
Dennis Sweeney1253c3e2020-05-05 17:14:32 -04001200 obj->weakreflist = NULL;
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001201 return (PyObject *)obj;
1202}
1203
1204static lru_list_elem *
1205lru_cache_unlink_list(lru_cache_object *self)
1206{
1207 lru_list_elem *root = &self->root;
1208 lru_list_elem *link = root->next;
1209 if (link == root)
1210 return NULL;
1211 root->prev->next = NULL;
1212 root->next = root->prev = root;
1213 return link;
1214}
1215
1216static void
1217lru_cache_clear_list(lru_list_elem *link)
1218{
1219 while (link != NULL) {
1220 lru_list_elem *next = link->next;
1221 Py_DECREF(link);
1222 link = next;
1223 }
1224}
1225
1226static void
1227lru_cache_dealloc(lru_cache_object *obj)
1228{
INADA Naokia6296d32017-08-24 14:55:17 +09001229 lru_list_elem *list;
1230 /* bpo-31095: UnTrack is needed before calling any callbacks */
1231 PyObject_GC_UnTrack(obj);
Dennis Sweeney1253c3e2020-05-05 17:14:32 -04001232 if (obj->weakreflist != NULL)
1233 PyObject_ClearWeakRefs((PyObject*)obj);
INADA Naokia6296d32017-08-24 14:55:17 +09001234
1235 list = lru_cache_unlink_list(obj);
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001236 Py_XDECREF(obj->cache);
Raymond Hettingerd8080c02019-01-26 03:02:00 -05001237 Py_XDECREF(obj->func);
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001238 Py_XDECREF(obj->cache_info_type);
Raymond Hettingerd8080c02019-01-26 03:02:00 -05001239 Py_XDECREF(obj->dict);
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001240 lru_cache_clear_list(list);
1241 Py_TYPE(obj)->tp_free(obj);
1242}
1243
1244static PyObject *
1245lru_cache_call(lru_cache_object *self, PyObject *args, PyObject *kwds)
1246{
1247 return self->wrapper(self, args, kwds);
1248}
1249
1250static PyObject *
Serhiy Storchakae7070f02015-06-08 11:19:24 +03001251lru_cache_descr_get(PyObject *self, PyObject *obj, PyObject *type)
1252{
1253 if (obj == Py_None || obj == NULL) {
1254 Py_INCREF(self);
1255 return self;
1256 }
1257 return PyMethod_New(self, obj);
1258}
1259
1260static PyObject *
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001261lru_cache_cache_info(lru_cache_object *self, PyObject *unused)
1262{
Raymond Hettingerd8080c02019-01-26 03:02:00 -05001263 if (self->maxsize == -1) {
1264 return PyObject_CallFunction(self->cache_info_type, "nnOn",
1265 self->hits, self->misses, Py_None,
1266 PyDict_GET_SIZE(self->cache));
1267 }
1268 return PyObject_CallFunction(self->cache_info_type, "nnnn",
1269 self->hits, self->misses, self->maxsize,
Serhiy Storchaka5ab81d72016-12-16 16:18:57 +02001270 PyDict_GET_SIZE(self->cache));
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001271}
1272
1273static PyObject *
1274lru_cache_cache_clear(lru_cache_object *self, PyObject *unused)
1275{
1276 lru_list_elem *list = lru_cache_unlink_list(self);
1277 self->hits = self->misses = 0;
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001278 PyDict_Clear(self->cache);
1279 lru_cache_clear_list(list);
1280 Py_RETURN_NONE;
1281}
1282
Serhiy Storchaka45120f22015-10-24 09:49:56 +03001283static PyObject *
1284lru_cache_reduce(PyObject *self, PyObject *unused)
1285{
1286 return PyObject_GetAttrString(self, "__qualname__");
1287}
1288
Serhiy Storchakae4d65e32015-12-28 23:58:07 +02001289static PyObject *
1290lru_cache_copy(PyObject *self, PyObject *unused)
1291{
1292 Py_INCREF(self);
1293 return self;
1294}
1295
1296static PyObject *
1297lru_cache_deepcopy(PyObject *self, PyObject *unused)
1298{
1299 Py_INCREF(self);
1300 return self;
1301}
1302
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001303static int
1304lru_cache_tp_traverse(lru_cache_object *self, visitproc visit, void *arg)
1305{
1306 lru_list_elem *link = self->root.next;
1307 while (link != &self->root) {
1308 lru_list_elem *next = link->next;
INADA Naoki3070b712017-12-26 02:03:24 +09001309 Py_VISIT(link->key);
1310 Py_VISIT(link->result);
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001311 link = next;
1312 }
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001313 Py_VISIT(self->func);
1314 Py_VISIT(self->cache);
1315 Py_VISIT(self->cache_info_type);
1316 Py_VISIT(self->dict);
1317 return 0;
1318}
1319
1320static int
1321lru_cache_tp_clear(lru_cache_object *self)
1322{
1323 lru_list_elem *list = lru_cache_unlink_list(self);
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001324 Py_CLEAR(self->func);
1325 Py_CLEAR(self->cache);
1326 Py_CLEAR(self->cache_info_type);
1327 Py_CLEAR(self->dict);
1328 lru_cache_clear_list(list);
1329 return 0;
1330}
1331
1332
1333PyDoc_STRVAR(lru_cache_doc,
1334"Create a cached callable that wraps another function.\n\
1335\n\
1336user_function: the function being cached\n\
1337\n\
1338maxsize: 0 for no caching\n\
1339 None for unlimited cache size\n\
1340 n for a bounded cache\n\
1341\n\
1342typed: False cache f(3) and f(3.0) as identical calls\n\
1343 True cache f(3) and f(3.0) as distinct calls\n\
1344\n\
1345cache_info_type: namedtuple class with the fields:\n\
1346 hits misses currsize maxsize\n"
1347);
1348
1349static PyMethodDef lru_cache_methods[] = {
1350 {"cache_info", (PyCFunction)lru_cache_cache_info, METH_NOARGS},
1351 {"cache_clear", (PyCFunction)lru_cache_cache_clear, METH_NOARGS},
Serhiy Storchaka45120f22015-10-24 09:49:56 +03001352 {"__reduce__", (PyCFunction)lru_cache_reduce, METH_NOARGS},
Serhiy Storchakae4d65e32015-12-28 23:58:07 +02001353 {"__copy__", (PyCFunction)lru_cache_copy, METH_VARARGS},
1354 {"__deepcopy__", (PyCFunction)lru_cache_deepcopy, METH_VARARGS},
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001355 {NULL}
1356};
1357
1358static PyGetSetDef lru_cache_getsetlist[] = {
1359 {"__dict__", PyObject_GenericGetDict, PyObject_GenericSetDict},
1360 {NULL}
1361};
1362
1363static PyTypeObject lru_cache_type = {
1364 PyVarObject_HEAD_INIT(NULL, 0)
1365 "functools._lru_cache_wrapper", /* tp_name */
1366 sizeof(lru_cache_object), /* tp_basicsize */
1367 0, /* tp_itemsize */
1368 /* methods */
1369 (destructor)lru_cache_dealloc, /* tp_dealloc */
Jeroen Demeyer530f5062019-05-31 04:13:39 +02001370 0, /* tp_vectorcall_offset */
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001371 0, /* tp_getattr */
1372 0, /* tp_setattr */
Jeroen Demeyer530f5062019-05-31 04:13:39 +02001373 0, /* tp_as_async */
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001374 0, /* tp_repr */
1375 0, /* tp_as_number */
1376 0, /* tp_as_sequence */
1377 0, /* tp_as_mapping */
1378 0, /* tp_hash */
1379 (ternaryfunc)lru_cache_call, /* tp_call */
1380 0, /* tp_str */
1381 0, /* tp_getattro */
1382 0, /* tp_setattro */
1383 0, /* tp_as_buffer */
Jeroen Demeyereb65e242019-05-28 14:42:53 +02001384 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE |
1385 Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_METHOD_DESCRIPTOR,
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001386 /* tp_flags */
1387 lru_cache_doc, /* tp_doc */
1388 (traverseproc)lru_cache_tp_traverse,/* tp_traverse */
1389 (inquiry)lru_cache_tp_clear, /* tp_clear */
1390 0, /* tp_richcompare */
Dennis Sweeney1253c3e2020-05-05 17:14:32 -04001391 offsetof(lru_cache_object, weakreflist),
1392 /* tp_weaklistoffset */
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001393 0, /* tp_iter */
1394 0, /* tp_iternext */
1395 lru_cache_methods, /* tp_methods */
1396 0, /* tp_members */
1397 lru_cache_getsetlist, /* tp_getset */
1398 0, /* tp_base */
1399 0, /* tp_dict */
Serhiy Storchakae7070f02015-06-08 11:19:24 +03001400 lru_cache_descr_get, /* tp_descr_get */
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001401 0, /* tp_descr_set */
1402 offsetof(lru_cache_object, dict), /* tp_dictoffset */
1403 0, /* tp_init */
1404 0, /* tp_alloc */
1405 lru_cache_new, /* tp_new */
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
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001420static void
Paulo Henrique Silva7dd549e2020-03-24 23:19:58 -03001421_functools_free(void *m)
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001422{
Paulo Henrique Silvaeacc0742020-04-01 12:06:21 -03001423 // FIXME: Do not clear kwd_mark to avoid NULL pointer dereferencing if we have
1424 // other modules instances that could use it. Will fix when PEP-573 land
1425 // and we could move kwd_mark to a per-module state.
1426 // Py_CLEAR(kwd_mark);
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001427}
Martin v. Löwis1a214512008-06-11 05:26:20 +00001428
Paulo Henrique Silva7dd549e2020-03-24 23:19:58 -03001429static int
1430_functools_exec(PyObject *module)
Raymond Hettinger9c323f82005-02-28 19:39:44 +00001431{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001432 PyTypeObject *typelist[] = {
1433 &partial_type,
Dong-hee Na05e4a292020-03-23 01:17:34 +09001434 &lru_cache_type
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001435 };
Raymond Hettinger9c323f82005-02-28 19:39:44 +00001436
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001437 if (!kwd_mark) {
Paulo Henrique Silvab09ae3f2020-03-26 09:47:45 -03001438 kwd_mark = _PyObject_CallNoArg((PyObject *)&PyBaseObject_Type);
1439 if (!kwd_mark) {
1440 return -1;
1441 }
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001442 }
1443
Dong-hee Na05e4a292020-03-23 01:17:34 +09001444 for (size_t i = 0; i < Py_ARRAY_LENGTH(typelist); i++) {
Paulo Henrique Silva7dd549e2020-03-24 23:19:58 -03001445 if (PyModule_AddType(module, typelist[i]) < 0) {
1446 return -1;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001447 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001448 }
Paulo Henrique Silva7dd549e2020-03-24 23:19:58 -03001449 return 0;
1450}
1451
1452static struct PyModuleDef_Slot _functools_slots[] = {
1453 {Py_mod_exec, _functools_exec},
1454 {0, NULL}
1455};
1456
1457static struct PyModuleDef _functools_module = {
1458 PyModuleDef_HEAD_INIT,
1459 "_functools",
1460 _functools_doc,
1461 0,
1462 _functools_methods,
1463 _functools_slots,
1464 NULL,
1465 NULL,
1466 _functools_free,
1467};
1468
1469PyMODINIT_FUNC
1470PyInit__functools(void)
1471{
1472 return PyModuleDef_Init(&_functools_module);
Raymond Hettinger9c323f82005-02-28 19:39:44 +00001473}