blob: 17d49ac5b342da79bc8062b32bea3f2b7a14ec65 [file] [log] [blame]
Raymond Hettinger9c323f82005-02-28 19:39:44 +00001#include "Python.h"
Victor Stinner621cebe2018-11-12 16:53:38 +01002#include "pycore_pymem.h"
3#include "pycore_pystate.h"
Victor Stinnerec13b932018-11-25 23:56:17 +01004#include "pycore_tupleobject.h"
Raymond Hettinger9c323f82005-02-28 19:39:44 +00005#include "structmember.h"
6
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);
Alexander Belopolskye49af342015-03-01 15:08:17 -050044 if (Py_TYPE(func) == &partial_type && type == &partial_type) {
45 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 *
135partial_vectorcall_fallback(partialobject *pto, PyObject *const *args,
136 size_t nargsf, PyObject *kwnames)
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000137{
Jeroen Demeyered184c02019-07-13 16:39:18 +0200138 pto->vectorcall = NULL;
139 Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
140 return _PyObject_MakeTpCall((PyObject *)pto, args, nargs, kwnames);
141}
142
143static PyObject *
144partial_vectorcall(partialobject *pto, PyObject *const *args,
145 size_t nargsf, PyObject *kwnames)
146{
147 /* pto->kw is mutable, so need to check every time */
148 if (PyDict_GET_SIZE(pto->kw)) {
149 return partial_vectorcall_fallback(pto, args, nargsf, kwnames);
150 }
151
152 Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
153 Py_ssize_t nargs_total = nargs;
154 if (kwnames != NULL) {
155 nargs_total += PyTuple_GET_SIZE(kwnames);
156 }
157
158 PyObject **pto_args = _PyTuple_ITEMS(pto->args);
159 Py_ssize_t pto_nargs = PyTuple_GET_SIZE(pto->args);
160
161 /* Fast path if we're called without arguments */
162 if (nargs_total == 0) {
163 return _PyObject_Vectorcall(pto->fn, pto_args, pto_nargs, NULL);
164 }
165
166 /* Fast path using PY_VECTORCALL_ARGUMENTS_OFFSET to prepend a single
167 * positional argument */
168 if (pto_nargs == 1 && (nargsf & PY_VECTORCALL_ARGUMENTS_OFFSET)) {
169 PyObject **newargs = (PyObject **)args - 1;
170 PyObject *tmp = newargs[0];
171 newargs[0] = pto_args[0];
172 PyObject *ret = _PyObject_Vectorcall(pto->fn, newargs, nargs + 1, kwnames);
173 newargs[0] = tmp;
174 return ret;
175 }
176
177 Py_ssize_t newnargs_total = pto_nargs + nargs_total;
178
Victor Stinner0f7b0b32017-03-14 21:37:20 +0100179 PyObject *small_stack[_PY_FASTCALL_SMALL_STACK];
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000180 PyObject *ret;
Jeroen Demeyered184c02019-07-13 16:39:18 +0200181 PyObject **stack;
Victor Stinner0f7b0b32017-03-14 21:37:20 +0100182
Jeroen Demeyered184c02019-07-13 16:39:18 +0200183 if (newnargs_total <= (Py_ssize_t)Py_ARRAY_LENGTH(small_stack)) {
184 stack = small_stack;
Victor Stinner0f7b0b32017-03-14 21:37:20 +0100185 }
186 else {
Jeroen Demeyered184c02019-07-13 16:39:18 +0200187 stack = PyMem_Malloc(newnargs_total * sizeof(PyObject *));
188 if (stack == NULL) {
189 PyErr_NoMemory();
190 return NULL;
Victor Stinner0f7b0b32017-03-14 21:37:20 +0100191 }
Victor Stinner0f7b0b32017-03-14 21:37:20 +0100192 }
193
Jeroen Demeyered184c02019-07-13 16:39:18 +0200194 /* Copy to new stack, using borrowed references */
195 memcpy(stack, pto_args, pto_nargs * sizeof(PyObject*));
196 memcpy(stack + pto_nargs, args, nargs_total * sizeof(PyObject*));
197
198 ret = _PyObject_Vectorcall(pto->fn, stack, pto_nargs + nargs, kwnames);
199 if (stack != small_stack) {
200 PyMem_Free(stack);
201 }
Victor Stinner0f7b0b32017-03-14 21:37:20 +0100202 return ret;
203}
204
Jeroen Demeyered184c02019-07-13 16:39:18 +0200205/* Set pto->vectorcall depending on the parameters of the partial object */
206static void
207partial_setvectorcall(partialobject *pto)
Victor Stinner0f7b0b32017-03-14 21:37:20 +0100208{
Jeroen Demeyered184c02019-07-13 16:39:18 +0200209 if (_PyVectorcall_Function(pto->fn) == NULL) {
210 /* Don't use vectorcall if the underlying function doesn't support it */
211 pto->vectorcall = NULL;
Victor Stinner0f7b0b32017-03-14 21:37:20 +0100212 }
Jeroen Demeyered184c02019-07-13 16:39:18 +0200213 /* We could have a special case if there are no arguments,
214 * but that is unlikely (why use partial without arguments?),
215 * so we don't optimize that */
216 else {
217 pto->vectorcall = (vectorcallfunc)partial_vectorcall;
218 }
Victor Stinner0f7b0b32017-03-14 21:37:20 +0100219}
220
Jeroen Demeyered184c02019-07-13 16:39:18 +0200221
Victor Stinner0f7b0b32017-03-14 21:37:20 +0100222static PyObject *
223partial_call(partialobject *pto, PyObject *args, PyObject *kwargs)
224{
Jeroen Demeyered184c02019-07-13 16:39:18 +0200225 assert(PyCallable_Check(pto->fn));
226 assert(PyTuple_Check(pto->args));
227 assert(PyDict_Check(pto->kw));
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000228
Jeroen Demeyered184c02019-07-13 16:39:18 +0200229 /* Merge keywords */
230 PyObject *kwargs2;
Serhiy Storchaka5ab81d72016-12-16 16:18:57 +0200231 if (PyDict_GET_SIZE(pto->kw) == 0) {
Victor Stinner0f7b0b32017-03-14 21:37:20 +0100232 /* kwargs can be NULL */
233 kwargs2 = kwargs;
234 Py_XINCREF(kwargs2);
Victor Stinnerf4d28d42016-08-23 16:22:35 +0200235 }
236 else {
Victor Stinner561ca802017-02-23 18:26:43 +0100237 /* bpo-27840, bpo-29318: dictionary of keyword parameters must be
238 copied, because a function using "**kwargs" can modify the
239 dictionary. */
Victor Stinner0f7b0b32017-03-14 21:37:20 +0100240 kwargs2 = PyDict_Copy(pto->kw);
241 if (kwargs2 == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000242 return NULL;
243 }
Victor Stinnerf4d28d42016-08-23 16:22:35 +0200244
Victor Stinner0f7b0b32017-03-14 21:37:20 +0100245 if (kwargs != NULL) {
246 if (PyDict_Merge(kwargs2, kwargs, 1) != 0) {
247 Py_DECREF(kwargs2);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000248 return NULL;
249 }
250 }
251 }
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000252
Jeroen Demeyered184c02019-07-13 16:39:18 +0200253 /* Merge positional arguments */
254 /* Note: tupleconcat() is optimized for empty tuples */
255 PyObject *args2 = PySequence_Concat(pto->args, args);
256 if (args2 == NULL) {
257 Py_XDECREF(kwargs2);
258 return NULL;
259 }
Victor Stinner0f7b0b32017-03-14 21:37:20 +0100260
Jeroen Demeyered184c02019-07-13 16:39:18 +0200261 PyObject *res = PyObject_Call(pto->fn, args2, kwargs2);
262 Py_DECREF(args2);
Victor Stinner0f7b0b32017-03-14 21:37:20 +0100263 Py_XDECREF(kwargs2);
264 return res;
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000265}
266
267static int
268partial_traverse(partialobject *pto, visitproc visit, void *arg)
269{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000270 Py_VISIT(pto->fn);
271 Py_VISIT(pto->args);
272 Py_VISIT(pto->kw);
273 Py_VISIT(pto->dict);
274 return 0;
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000275}
276
277PyDoc_STRVAR(partial_doc,
278"partial(func, *args, **keywords) - new function with partial application\n\
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000279 of the given arguments and keywords.\n");
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000280
281#define OFF(x) offsetof(partialobject, x)
282static PyMemberDef partial_memberlist[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000283 {"func", T_OBJECT, OFF(fn), READONLY,
284 "function object to use in future partial calls"},
285 {"args", T_OBJECT, OFF(args), READONLY,
286 "tuple of arguments to future partial calls"},
287 {"keywords", T_OBJECT, OFF(kw), READONLY,
288 "dictionary of keyword arguments to future partial calls"},
289 {NULL} /* Sentinel */
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000290};
291
Georg Brandlc2fb6c72006-02-21 17:49:57 +0000292static PyGetSetDef partial_getsetlist[] = {
Benjamin Peterson23d7f122012-02-19 20:02:57 -0500293 {"__dict__", PyObject_GenericGetDict, PyObject_GenericSetDict},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000294 {NULL} /* Sentinel */
Raymond Hettingerc8b6d1b2005-03-08 06:14:50 +0000295};
296
Alexander Belopolsky41e422a2010-12-01 20:05:49 +0000297static PyObject *
298partial_repr(partialobject *pto)
299{
Serhiy Storchaka179f9602016-06-12 11:44:06 +0300300 PyObject *result = NULL;
Alexander Belopolsky41e422a2010-12-01 20:05:49 +0000301 PyObject *arglist;
Alexander Belopolsky41e422a2010-12-01 20:05:49 +0000302 Py_ssize_t i, n;
Serhiy Storchaka38741282016-02-02 18:45:17 +0200303 PyObject *key, *value;
Serhiy Storchaka179f9602016-06-12 11:44:06 +0300304 int status;
305
306 status = Py_ReprEnter((PyObject *)pto);
307 if (status != 0) {
308 if (status < 0)
309 return NULL;
Nick Coghlan457fc9a2016-09-10 20:00:02 +1000310 return PyUnicode_FromString("...");
Serhiy Storchaka179f9602016-06-12 11:44:06 +0300311 }
Alexander Belopolsky41e422a2010-12-01 20:05:49 +0000312
313 arglist = PyUnicode_FromString("");
Serhiy Storchaka179f9602016-06-12 11:44:06 +0300314 if (arglist == NULL)
315 goto done;
Alexander Belopolsky41e422a2010-12-01 20:05:49 +0000316 /* Pack positional arguments */
317 assert (PyTuple_Check(pto->args));
318 n = PyTuple_GET_SIZE(pto->args);
319 for (i = 0; i < n; i++) {
Serhiy Storchaka179f9602016-06-12 11:44:06 +0300320 Py_SETREF(arglist, PyUnicode_FromFormat("%U, %R", arglist,
321 PyTuple_GET_ITEM(pto->args, i)));
322 if (arglist == NULL)
323 goto done;
Alexander Belopolsky41e422a2010-12-01 20:05:49 +0000324 }
325 /* Pack keyword arguments */
Serhiy Storchaka38741282016-02-02 18:45:17 +0200326 assert (PyDict_Check(pto->kw));
327 for (i = 0; PyDict_Next(pto->kw, &i, &key, &value);) {
Michael Seifert6c3d5272017-03-15 06:26:33 +0100328 /* Prevent key.__str__ from deleting the value. */
329 Py_INCREF(value);
330 Py_SETREF(arglist, PyUnicode_FromFormat("%U, %S=%R", arglist,
Serhiy Storchaka179f9602016-06-12 11:44:06 +0300331 key, value));
Michael Seifert6c3d5272017-03-15 06:26:33 +0100332 Py_DECREF(value);
Serhiy Storchaka179f9602016-06-12 11:44:06 +0300333 if (arglist == NULL)
334 goto done;
Alexander Belopolsky41e422a2010-12-01 20:05:49 +0000335 }
336 result = PyUnicode_FromFormat("%s(%R%U)", Py_TYPE(pto)->tp_name,
337 pto->fn, arglist);
338 Py_DECREF(arglist);
Serhiy Storchaka179f9602016-06-12 11:44:06 +0300339
340 done:
341 Py_ReprLeave((PyObject *)pto);
Alexander Belopolsky41e422a2010-12-01 20:05:49 +0000342 return result;
343}
344
Jack Diederiche0cbd692009-04-01 04:27:09 +0000345/* Pickle strategy:
346 __reduce__ by itself doesn't support getting kwargs in the unpickle
347 operation so we define a __setstate__ that replaces all the information
348 about the partial. If we only replaced part of it someone would use
Ezio Melotti13925002011-03-16 11:05:33 +0200349 it as a hook to do strange things.
Jack Diederiche0cbd692009-04-01 04:27:09 +0000350 */
351
Antoine Pitrou69f71142009-05-24 21:25:49 +0000352static PyObject *
Jack Diederiche0cbd692009-04-01 04:27:09 +0000353partial_reduce(partialobject *pto, PyObject *unused)
354{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000355 return Py_BuildValue("O(O)(OOOO)", Py_TYPE(pto), pto->fn, pto->fn,
356 pto->args, pto->kw,
357 pto->dict ? pto->dict : Py_None);
Jack Diederiche0cbd692009-04-01 04:27:09 +0000358}
359
Antoine Pitrou69f71142009-05-24 21:25:49 +0000360static PyObject *
Serhiy Storchaka19c4e0d2013-02-04 12:47:24 +0200361partial_setstate(partialobject *pto, PyObject *state)
Jack Diederiche0cbd692009-04-01 04:27:09 +0000362{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000363 PyObject *fn, *fnargs, *kw, *dict;
Serhiy Storchaka38741282016-02-02 18:45:17 +0200364
365 if (!PyTuple_Check(state) ||
366 !PyArg_ParseTuple(state, "OOOO", &fn, &fnargs, &kw, &dict) ||
367 !PyCallable_Check(fn) ||
368 !PyTuple_Check(fnargs) ||
369 (kw != Py_None && !PyDict_Check(kw)))
370 {
371 PyErr_SetString(PyExc_TypeError, "invalid partial state");
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000372 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000373 }
Serhiy Storchaka38741282016-02-02 18:45:17 +0200374
375 if(!PyTuple_CheckExact(fnargs))
376 fnargs = PySequence_Tuple(fnargs);
377 else
378 Py_INCREF(fnargs);
379 if (fnargs == NULL)
380 return NULL;
381
382 if (kw == Py_None)
383 kw = PyDict_New();
384 else if(!PyDict_CheckExact(kw))
385 kw = PyDict_Copy(kw);
386 else
387 Py_INCREF(kw);
388 if (kw == NULL) {
389 Py_DECREF(fnargs);
390 return NULL;
391 }
392
Serhiy Storchaka38741282016-02-02 18:45:17 +0200393 if (dict == Py_None)
394 dict = NULL;
395 else
396 Py_INCREF(dict);
397
Victor Stinner0f7b0b32017-03-14 21:37:20 +0100398 Py_INCREF(fn);
Serhiy Storchaka864b63c2016-04-11 09:53:37 +0300399 Py_SETREF(pto->fn, fn);
400 Py_SETREF(pto->args, fnargs);
401 Py_SETREF(pto->kw, kw);
Serhiy Storchaka48842712016-04-06 09:45:48 +0300402 Py_XSETREF(pto->dict, dict);
Jeroen Demeyered184c02019-07-13 16:39:18 +0200403 partial_setvectorcall(pto);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000404 Py_RETURN_NONE;
Jack Diederiche0cbd692009-04-01 04:27:09 +0000405}
406
407static PyMethodDef partial_methods[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000408 {"__reduce__", (PyCFunction)partial_reduce, METH_NOARGS},
Serhiy Storchaka19c4e0d2013-02-04 12:47:24 +0200409 {"__setstate__", (PyCFunction)partial_setstate, METH_O},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000410 {NULL, NULL} /* sentinel */
Jack Diederiche0cbd692009-04-01 04:27:09 +0000411};
412
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000413static PyTypeObject partial_type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000414 PyVarObject_HEAD_INIT(NULL, 0)
415 "functools.partial", /* tp_name */
416 sizeof(partialobject), /* tp_basicsize */
417 0, /* tp_itemsize */
418 /* methods */
419 (destructor)partial_dealloc, /* tp_dealloc */
Jeroen Demeyered184c02019-07-13 16:39:18 +0200420 offsetof(partialobject, vectorcall),/* tp_vectorcall_offset */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000421 0, /* tp_getattr */
422 0, /* tp_setattr */
Jeroen Demeyer530f5062019-05-31 04:13:39 +0200423 0, /* tp_as_async */
Alexander Belopolsky41e422a2010-12-01 20:05:49 +0000424 (reprfunc)partial_repr, /* tp_repr */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000425 0, /* tp_as_number */
426 0, /* tp_as_sequence */
427 0, /* tp_as_mapping */
428 0, /* tp_hash */
429 (ternaryfunc)partial_call, /* tp_call */
430 0, /* tp_str */
431 PyObject_GenericGetAttr, /* tp_getattro */
432 PyObject_GenericSetAttr, /* tp_setattro */
433 0, /* tp_as_buffer */
434 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
Jeroen Demeyered184c02019-07-13 16:39:18 +0200435 Py_TPFLAGS_BASETYPE |
436 _Py_TPFLAGS_HAVE_VECTORCALL, /* tp_flags */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000437 partial_doc, /* tp_doc */
438 (traverseproc)partial_traverse, /* tp_traverse */
439 0, /* tp_clear */
440 0, /* tp_richcompare */
441 offsetof(partialobject, weakreflist), /* tp_weaklistoffset */
442 0, /* tp_iter */
443 0, /* tp_iternext */
444 partial_methods, /* tp_methods */
445 partial_memberlist, /* tp_members */
446 partial_getsetlist, /* tp_getset */
447 0, /* tp_base */
448 0, /* tp_dict */
449 0, /* tp_descr_get */
450 0, /* tp_descr_set */
451 offsetof(partialobject, dict), /* tp_dictoffset */
452 0, /* tp_init */
453 0, /* tp_alloc */
454 partial_new, /* tp_new */
455 PyObject_GC_Del, /* tp_free */
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000456};
457
458
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700459/* cmp_to_key ***************************************************************/
460
461typedef struct {
Victor Stinner446c8d52011-04-05 12:21:35 +0200462 PyObject_HEAD
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700463 PyObject *cmp;
464 PyObject *object;
465} keyobject;
466
467static void
468keyobject_dealloc(keyobject *ko)
469{
470 Py_DECREF(ko->cmp);
471 Py_XDECREF(ko->object);
472 PyObject_FREE(ko);
473}
474
475static int
476keyobject_traverse(keyobject *ko, visitproc visit, void *arg)
477{
478 Py_VISIT(ko->cmp);
479 if (ko->object)
480 Py_VISIT(ko->object);
481 return 0;
482}
483
Benjamin Peterson3bd97292011-04-05 17:25:14 -0500484static int
485keyobject_clear(keyobject *ko)
486{
487 Py_CLEAR(ko->cmp);
488 if (ko->object)
489 Py_CLEAR(ko->object);
490 return 0;
491}
492
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700493static PyMemberDef keyobject_members[] = {
494 {"obj", T_OBJECT,
495 offsetof(keyobject, object), 0,
496 PyDoc_STR("Value wrapped by a key function.")},
497 {NULL}
498};
499
500static PyObject *
Raymond Hettingera5632862011-04-09 12:57:00 -0700501keyobject_call(keyobject *ko, PyObject *args, PyObject *kwds);
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700502
503static PyObject *
504keyobject_richcompare(PyObject *ko, PyObject *other, int op);
505
506static PyTypeObject keyobject_type = {
507 PyVarObject_HEAD_INIT(&PyType_Type, 0)
508 "functools.KeyWrapper", /* tp_name */
509 sizeof(keyobject), /* tp_basicsize */
510 0, /* tp_itemsize */
511 /* methods */
512 (destructor)keyobject_dealloc, /* tp_dealloc */
Jeroen Demeyer530f5062019-05-31 04:13:39 +0200513 0, /* tp_vectorcall_offset */
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700514 0, /* tp_getattr */
515 0, /* tp_setattr */
Jeroen Demeyer530f5062019-05-31 04:13:39 +0200516 0, /* tp_as_async */
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700517 0, /* tp_repr */
518 0, /* tp_as_number */
519 0, /* tp_as_sequence */
520 0, /* tp_as_mapping */
521 0, /* tp_hash */
522 (ternaryfunc)keyobject_call, /* tp_call */
523 0, /* tp_str */
524 PyObject_GenericGetAttr, /* tp_getattro */
525 0, /* tp_setattro */
526 0, /* tp_as_buffer */
527 Py_TPFLAGS_DEFAULT, /* tp_flags */
528 0, /* tp_doc */
529 (traverseproc)keyobject_traverse, /* tp_traverse */
Benjamin Peterson3bd97292011-04-05 17:25:14 -0500530 (inquiry)keyobject_clear, /* tp_clear */
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700531 keyobject_richcompare, /* tp_richcompare */
532 0, /* tp_weaklistoffset */
533 0, /* tp_iter */
534 0, /* tp_iternext */
535 0, /* tp_methods */
536 keyobject_members, /* tp_members */
537 0, /* tp_getset */
538};
539
540static PyObject *
541keyobject_call(keyobject *ko, PyObject *args, PyObject *kwds)
542{
543 PyObject *object;
544 keyobject *result;
545 static char *kwargs[] = {"obj", NULL};
546
547 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:K", kwargs, &object))
548 return NULL;
549 result = PyObject_New(keyobject, &keyobject_type);
550 if (!result)
551 return NULL;
552 Py_INCREF(ko->cmp);
553 result->cmp = ko->cmp;
554 Py_INCREF(object);
555 result->object = object;
556 return (PyObject *)result;
557}
558
559static PyObject *
560keyobject_richcompare(PyObject *ko, PyObject *other, int op)
561{
562 PyObject *res;
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700563 PyObject *x;
564 PyObject *y;
565 PyObject *compare;
566 PyObject *answer;
Victor Stinnerf7a4c482016-08-19 18:52:35 +0200567 PyObject* stack[2];
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700568
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700569 if (Py_TYPE(other) != &keyobject_type){
570 PyErr_Format(PyExc_TypeError, "other argument must be K instance");
571 return NULL;
572 }
573 compare = ((keyobject *) ko)->cmp;
574 assert(compare != NULL);
575 x = ((keyobject *) ko)->object;
576 y = ((keyobject *) other)->object;
577 if (!x || !y){
578 PyErr_Format(PyExc_AttributeError, "object");
579 return NULL;
580 }
581
582 /* Call the user's comparison function and translate the 3-way
583 * result into true or false (or error).
584 */
Victor Stinnerf7a4c482016-08-19 18:52:35 +0200585 stack[0] = x;
586 stack[1] = y;
Victor Stinner559bb6a2016-08-22 22:48:54 +0200587 res = _PyObject_FastCall(compare, stack, 2);
Victor Stinnerf7a4c482016-08-19 18:52:35 +0200588 if (res == NULL) {
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700589 return NULL;
Victor Stinnerf7a4c482016-08-19 18:52:35 +0200590 }
591
Serhiy Storchakaba85d692017-03-30 09:09:41 +0300592 answer = PyObject_RichCompare(res, _PyLong_Zero, op);
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700593 Py_DECREF(res);
594 return answer;
595}
596
597static PyObject *
Victor Stinner446c8d52011-04-05 12:21:35 +0200598functools_cmp_to_key(PyObject *self, PyObject *args, PyObject *kwds)
599{
600 PyObject *cmp;
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700601 static char *kwargs[] = {"mycmp", NULL};
Victor Stinner446c8d52011-04-05 12:21:35 +0200602 keyobject *object;
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700603
604 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:cmp_to_key", kwargs, &cmp))
605 return NULL;
Victor Stinner446c8d52011-04-05 12:21:35 +0200606 object = PyObject_New(keyobject, &keyobject_type);
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700607 if (!object)
608 return NULL;
609 Py_INCREF(cmp);
610 object->cmp = cmp;
611 object->object = NULL;
612 return (PyObject *)object;
613}
614
615PyDoc_STRVAR(functools_cmp_to_key_doc,
616"Convert a cmp= function into a key= function.");
617
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000618/* reduce (used to be a builtin) ********************************************/
619
620static PyObject *
621functools_reduce(PyObject *self, PyObject *args)
622{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000623 PyObject *seq, *func, *result = NULL, *it;
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000624
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000625 if (!PyArg_UnpackTuple(args, "reduce", 2, 3, &func, &seq, &result))
626 return NULL;
627 if (result != NULL)
628 Py_INCREF(result);
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000629
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000630 it = PyObject_GetIter(seq);
631 if (it == NULL) {
Alexander Belopolskye29e6bf2010-08-16 18:55:46 +0000632 if (PyErr_ExceptionMatches(PyExc_TypeError))
633 PyErr_SetString(PyExc_TypeError,
634 "reduce() arg 2 must support iteration");
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000635 Py_XDECREF(result);
636 return NULL;
637 }
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000638
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000639 if ((args = PyTuple_New(2)) == NULL)
640 goto Fail;
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000641
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000642 for (;;) {
643 PyObject *op2;
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000644
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000645 if (args->ob_refcnt > 1) {
646 Py_DECREF(args);
647 if ((args = PyTuple_New(2)) == NULL)
648 goto Fail;
649 }
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000650
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000651 op2 = PyIter_Next(it);
652 if (op2 == NULL) {
653 if (PyErr_Occurred())
654 goto Fail;
655 break;
656 }
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000657
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000658 if (result == NULL)
659 result = op2;
660 else {
Sergey Fedoseeve5f62072019-06-02 01:32:18 +0500661 /* Update the args tuple in-place */
662 assert(args->ob_refcnt == 1);
663 Py_XSETREF(_PyTuple_ITEMS(args)[0], result);
664 Py_XSETREF(_PyTuple_ITEMS(args)[1], op2);
665 if ((result = PyObject_Call(func, args, NULL)) == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000666 goto Fail;
Sergey Fedoseeve5f62072019-06-02 01:32:18 +0500667 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000668 }
669 }
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000670
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000671 Py_DECREF(args);
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000672
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000673 if (result == NULL)
674 PyErr_SetString(PyExc_TypeError,
675 "reduce() of empty sequence with no initial value");
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000676
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000677 Py_DECREF(it);
678 return result;
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000679
680Fail:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000681 Py_XDECREF(args);
682 Py_XDECREF(result);
683 Py_DECREF(it);
684 return NULL;
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000685}
686
687PyDoc_STRVAR(functools_reduce_doc,
688"reduce(function, sequence[, initial]) -> value\n\
689\n\
690Apply a function of two arguments cumulatively to the items of a sequence,\n\
691from left to right, so as to reduce the sequence to a single value.\n\
692For example, reduce(lambda x, y: x+y, [1, 2, 3, 4, 5]) calculates\n\
693((((1+2)+3)+4)+5). If initial is present, it is placed before the items\n\
694of the sequence in the calculation, and serves as a default when the\n\
695sequence is empty.");
696
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300697/* lru_cache object **********************************************************/
698
Raymond Hettinger2dda72a2019-02-08 18:55:02 -0800699/* There are four principal algorithmic differences from the pure python version:
700
701 1). The C version relies on the GIL instead of having its own reentrant lock.
702
703 2). The prev/next link fields use borrowed references.
704
705 3). For a full cache, the pure python version rotates the location of the
706 root entry so that it never has to move individual links and it can
707 limit updates to just the key and result fields. However, in the C
708 version, links are temporarily removed while the cache dict updates are
709 occurring. Afterwards, they are appended or prepended back into the
710 doubly-linked lists.
711
712 4) In the Python version, the _HashSeq class is used to prevent __hash__
713 from being called more than once. In the C version, the "known hash"
714 variants of dictionary calls as used to the same effect.
715
716*/
717
718
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300719/* this object is used delimit args and keywords in the cache keys */
720static PyObject *kwd_mark = NULL;
721
722struct lru_list_elem;
723struct lru_cache_object;
724
725typedef struct lru_list_elem {
726 PyObject_HEAD
727 struct lru_list_elem *prev, *next; /* borrowed links */
Serhiy Storchakab9d98d52015-10-02 12:47:11 +0300728 Py_hash_t hash;
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300729 PyObject *key, *result;
730} lru_list_elem;
731
732static void
733lru_list_elem_dealloc(lru_list_elem *link)
734{
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300735 Py_XDECREF(link->key);
736 Py_XDECREF(link->result);
INADA Naoki3070b712017-12-26 02:03:24 +0900737 PyObject_Del(link);
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300738}
739
740static PyTypeObject lru_list_elem_type = {
741 PyVarObject_HEAD_INIT(&PyType_Type, 0)
742 "functools._lru_list_elem", /* tp_name */
743 sizeof(lru_list_elem), /* tp_basicsize */
744 0, /* tp_itemsize */
745 /* methods */
746 (destructor)lru_list_elem_dealloc, /* tp_dealloc */
Jeroen Demeyer530f5062019-05-31 04:13:39 +0200747 0, /* tp_vectorcall_offset */
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300748 0, /* tp_getattr */
749 0, /* tp_setattr */
Jeroen Demeyer530f5062019-05-31 04:13:39 +0200750 0, /* tp_as_async */
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300751 0, /* tp_repr */
752 0, /* tp_as_number */
753 0, /* tp_as_sequence */
754 0, /* tp_as_mapping */
755 0, /* tp_hash */
756 0, /* tp_call */
757 0, /* tp_str */
758 0, /* tp_getattro */
759 0, /* tp_setattro */
760 0, /* tp_as_buffer */
INADA Naoki3070b712017-12-26 02:03:24 +0900761 Py_TPFLAGS_DEFAULT, /* tp_flags */
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300762};
763
764
765typedef PyObject *(*lru_cache_ternaryfunc)(struct lru_cache_object *, PyObject *, PyObject *);
766
767typedef struct lru_cache_object {
768 lru_list_elem root; /* includes PyObject_HEAD */
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300769 lru_cache_ternaryfunc wrapper;
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300770 int typed;
Raymond Hettingerd8080c02019-01-26 03:02:00 -0500771 PyObject *cache;
772 Py_ssize_t hits;
773 PyObject *func;
774 Py_ssize_t maxsize;
775 Py_ssize_t misses;
776 PyObject *cache_info_type;
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300777 PyObject *dict;
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300778} lru_cache_object;
779
780static PyTypeObject lru_cache_type;
781
782static PyObject *
783lru_cache_make_key(PyObject *args, PyObject *kwds, int typed)
784{
Raymond Hettingerdda44682017-01-08 18:04:30 -0800785 PyObject *key, *keyword, *value;
786 Py_ssize_t key_size, pos, key_pos, kwds_size;
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300787
Raymond Hettinger14adbd42019-04-20 07:20:44 -1000788 kwds_size = kwds ? PyDict_GET_SIZE(kwds) : 0;
789
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300790 /* short path, key will match args anyway, which is a tuple */
Raymond Hettinger14adbd42019-04-20 07:20:44 -1000791 if (!typed && !kwds_size) {
Raymond Hettingerd8080c02019-01-26 03:02:00 -0500792 if (PyTuple_GET_SIZE(args) == 1) {
793 key = PyTuple_GET_ITEM(args, 0);
794 if (PyUnicode_CheckExact(key) || PyLong_CheckExact(key)) {
795 /* For common scalar keys, save space by
796 dropping the enclosing args tuple */
797 Py_INCREF(key);
798 return key;
799 }
800 }
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300801 Py_INCREF(args);
802 return args;
803 }
804
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300805 key_size = PyTuple_GET_SIZE(args);
Raymond Hettingerdda44682017-01-08 18:04:30 -0800806 if (kwds_size)
807 key_size += kwds_size * 2 + 1;
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300808 if (typed)
Raymond Hettingerdda44682017-01-08 18:04:30 -0800809 key_size += PyTuple_GET_SIZE(args) + kwds_size;
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300810
811 key = PyTuple_New(key_size);
812 if (key == NULL)
Raymond Hettingerdda44682017-01-08 18:04:30 -0800813 return NULL;
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300814
815 key_pos = 0;
816 for (pos = 0; pos < PyTuple_GET_SIZE(args); ++pos) {
817 PyObject *item = PyTuple_GET_ITEM(args, pos);
818 Py_INCREF(item);
819 PyTuple_SET_ITEM(key, key_pos++, item);
820 }
Raymond Hettingerdda44682017-01-08 18:04:30 -0800821 if (kwds_size) {
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300822 Py_INCREF(kwd_mark);
823 PyTuple_SET_ITEM(key, key_pos++, kwd_mark);
Raymond Hettingerdda44682017-01-08 18:04:30 -0800824 for (pos = 0; PyDict_Next(kwds, &pos, &keyword, &value);) {
825 Py_INCREF(keyword);
826 PyTuple_SET_ITEM(key, key_pos++, keyword);
827 Py_INCREF(value);
828 PyTuple_SET_ITEM(key, key_pos++, value);
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300829 }
Raymond Hettingerdda44682017-01-08 18:04:30 -0800830 assert(key_pos == PyTuple_GET_SIZE(args) + kwds_size * 2 + 1);
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300831 }
832 if (typed) {
833 for (pos = 0; pos < PyTuple_GET_SIZE(args); ++pos) {
834 PyObject *item = (PyObject *)Py_TYPE(PyTuple_GET_ITEM(args, pos));
835 Py_INCREF(item);
836 PyTuple_SET_ITEM(key, key_pos++, item);
837 }
Raymond Hettingerdda44682017-01-08 18:04:30 -0800838 if (kwds_size) {
839 for (pos = 0; PyDict_Next(kwds, &pos, &keyword, &value);) {
840 PyObject *item = (PyObject *)Py_TYPE(value);
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300841 Py_INCREF(item);
842 PyTuple_SET_ITEM(key, key_pos++, item);
843 }
844 }
845 }
846 assert(key_pos == key_size);
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300847 return key;
848}
849
850static PyObject *
851uncached_lru_cache_wrapper(lru_cache_object *self, PyObject *args, PyObject *kwds)
852{
Raymond Hettingerffdf1c32019-01-31 15:03:38 -0800853 PyObject *result;
854
855 self->misses++;
856 result = PyObject_Call(self->func, args, kwds);
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300857 if (!result)
858 return NULL;
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300859 return result;
860}
861
862static PyObject *
863infinite_lru_cache_wrapper(lru_cache_object *self, PyObject *args, PyObject *kwds)
864{
865 PyObject *result;
Serhiy Storchakab9d98d52015-10-02 12:47:11 +0300866 Py_hash_t hash;
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300867 PyObject *key = lru_cache_make_key(args, kwds, self->typed);
868 if (!key)
869 return NULL;
Serhiy Storchakab9d98d52015-10-02 12:47:11 +0300870 hash = PyObject_Hash(key);
Yury Selivanov46a02db2016-11-09 18:55:45 -0500871 if (hash == -1) {
872 Py_DECREF(key);
Serhiy Storchakab9d98d52015-10-02 12:47:11 +0300873 return NULL;
Yury Selivanov46a02db2016-11-09 18:55:45 -0500874 }
Serhiy Storchakab9d98d52015-10-02 12:47:11 +0300875 result = _PyDict_GetItem_KnownHash(self->cache, key, hash);
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300876 if (result) {
877 Py_INCREF(result);
878 self->hits++;
879 Py_DECREF(key);
880 return result;
881 }
882 if (PyErr_Occurred()) {
883 Py_DECREF(key);
884 return NULL;
885 }
Raymond Hettingerffdf1c32019-01-31 15:03:38 -0800886 self->misses++;
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300887 result = PyObject_Call(self->func, args, kwds);
888 if (!result) {
889 Py_DECREF(key);
890 return NULL;
891 }
Serhiy Storchakab9d98d52015-10-02 12:47:11 +0300892 if (_PyDict_SetItem_KnownHash(self->cache, key, result, hash) < 0) {
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300893 Py_DECREF(result);
894 Py_DECREF(key);
895 return NULL;
896 }
897 Py_DECREF(key);
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300898 return result;
899}
900
901static void
Raymond Hettingerd8080c02019-01-26 03:02:00 -0500902lru_cache_extract_link(lru_list_elem *link)
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300903{
Raymond Hettingerd8080c02019-01-26 03:02:00 -0500904 lru_list_elem *link_prev = link->prev;
905 lru_list_elem *link_next = link->next;
906 link_prev->next = link->next;
907 link_next->prev = link->prev;
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300908}
909
910static void
911lru_cache_append_link(lru_cache_object *self, lru_list_elem *link)
912{
913 lru_list_elem *root = &self->root;
914 lru_list_elem *last = root->prev;
915 last->next = root->prev = link;
916 link->prev = last;
917 link->next = root;
918}
919
Raymond Hettingerd8080c02019-01-26 03:02:00 -0500920static void
921lru_cache_prepend_link(lru_cache_object *self, lru_list_elem *link)
922{
923 lru_list_elem *root = &self->root;
924 lru_list_elem *first = root->next;
925 first->prev = root->next = link;
926 link->prev = root;
927 link->next = first;
928}
929
930/* General note on reentrancy:
931
932 There are four dictionary calls in the bounded_lru_cache_wrapper():
933 1) The initial check for a cache match. 2) The post user-function
934 check for a cache match. 3) The deletion of the oldest entry.
935 4) The addition of the newest entry.
936
937 In all four calls, we have a known hash which lets use avoid a call
938 to __hash__(). That leaves only __eq__ as a possible source of a
939 reentrant call.
940
941 The __eq__ method call is always made for a cache hit (dict access #1).
942 Accordingly, we have make sure not modify the cache state prior to
943 this call.
944
945 The __eq__ method call is never made for the deletion (dict access #3)
946 because it is an identity match.
947
948 For the other two accesses (#2 and #4), calls to __eq__ only occur
949 when some other entry happens to have an exactly matching hash (all
950 64-bits). Though rare, this can happen, so we have to make sure to
951 either call it at the top of its code path before any cache
952 state modifications (dict access #2) or be prepared to restore
953 invariants at the end of the code path (dict access #4).
954
955 Another possible source of reentrancy is a decref which can trigger
956 arbitrary code execution. To make the code easier to reason about,
957 the decrefs are deferred to the end of the each possible code path
958 so that we know the cache is a consistent state.
959 */
960
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300961static PyObject *
962bounded_lru_cache_wrapper(lru_cache_object *self, PyObject *args, PyObject *kwds)
963{
964 lru_list_elem *link;
Raymond Hettingerd8080c02019-01-26 03:02:00 -0500965 PyObject *key, *result, *testresult;
Serhiy Storchakab9d98d52015-10-02 12:47:11 +0300966 Py_hash_t hash;
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300967
968 key = lru_cache_make_key(args, kwds, self->typed);
969 if (!key)
970 return NULL;
Serhiy Storchakab9d98d52015-10-02 12:47:11 +0300971 hash = PyObject_Hash(key);
Yury Selivanov46a02db2016-11-09 18:55:45 -0500972 if (hash == -1) {
973 Py_DECREF(key);
Serhiy Storchakab9d98d52015-10-02 12:47:11 +0300974 return NULL;
Yury Selivanov46a02db2016-11-09 18:55:45 -0500975 }
Serhiy Storchakab9d98d52015-10-02 12:47:11 +0300976 link = (lru_list_elem *)_PyDict_GetItem_KnownHash(self->cache, key, hash);
Raymond Hettingerd8080c02019-01-26 03:02:00 -0500977 if (link != NULL) {
978 lru_cache_extract_link(link);
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300979 lru_cache_append_link(self, link);
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300980 result = link->result;
Raymond Hettingerd8080c02019-01-26 03:02:00 -0500981 self->hits++;
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300982 Py_INCREF(result);
983 Py_DECREF(key);
984 return result;
985 }
986 if (PyErr_Occurred()) {
987 Py_DECREF(key);
988 return NULL;
989 }
Raymond Hettingerd8080c02019-01-26 03:02:00 -0500990 self->misses++;
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300991 result = PyObject_Call(self->func, args, kwds);
992 if (!result) {
993 Py_DECREF(key);
994 return NULL;
995 }
Raymond Hettingerd8080c02019-01-26 03:02:00 -0500996 testresult = _PyDict_GetItem_KnownHash(self->cache, key, hash);
997 if (testresult != NULL) {
998 /* Getting here means that this same key was added to the cache
999 during the PyObject_Call(). Since the link update is already
1000 done, we need only return the computed result. */
1001 Py_DECREF(key);
1002 return result;
1003 }
1004 if (PyErr_Occurred()) {
1005 /* This is an unusual case since this same lookup
1006 did not previously trigger an error during lookup.
1007 Treat it the same as an error in user function
1008 and return with the error set. */
1009 Py_DECREF(key);
1010 Py_DECREF(result);
1011 return NULL;
1012 }
1013 /* This is the normal case. The new key wasn't found before
1014 user function call and it is still not there. So we
1015 proceed normally and update the cache with the new result. */
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001016
Raymond Hettingerd8080c02019-01-26 03:02:00 -05001017 assert(self->maxsize > 0);
1018 if (PyDict_GET_SIZE(self->cache) < self->maxsize ||
1019 self->root.next == &self->root)
1020 {
1021 /* Cache is not full, so put the result in a new link */
INADA Naoki3070b712017-12-26 02:03:24 +09001022 link = (lru_list_elem *)PyObject_New(lru_list_elem,
1023 &lru_list_elem_type);
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001024 if (link == NULL) {
1025 Py_DECREF(key);
1026 Py_DECREF(result);
1027 return NULL;
1028 }
1029
Serhiy Storchakab9d98d52015-10-02 12:47:11 +03001030 link->hash = hash;
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001031 link->key = key;
1032 link->result = result;
Raymond Hettingerd8080c02019-01-26 03:02:00 -05001033 /* What is really needed here is a SetItem variant with a "no clobber"
1034 option. If the __eq__ call triggers a reentrant call that adds
1035 this same key, then this setitem call will update the cache dict
1036 with this new link, leaving the old link as an orphan (i.e. not
1037 having a cache dict entry that refers to it). */
Serhiy Storchakab9d98d52015-10-02 12:47:11 +03001038 if (_PyDict_SetItem_KnownHash(self->cache, key, (PyObject *)link,
1039 hash) < 0) {
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001040 Py_DECREF(link);
1041 return NULL;
1042 }
1043 lru_cache_append_link(self, link);
1044 Py_INCREF(result); /* for return */
Raymond Hettingerd8080c02019-01-26 03:02:00 -05001045 return result;
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001046 }
Raymond Hettingerd8080c02019-01-26 03:02:00 -05001047 /* Since the cache is full, we need to evict an old key and add
1048 a new key. Rather than free the old link and allocate a new
1049 one, we reuse the link for the new key and result and move it
1050 to front of the cache to mark it as recently used.
1051
1052 We try to assure all code paths (including errors) leave all
1053 of the links in place. Either the link is successfully
1054 updated and moved or it is restored to its old position.
1055 However if an unrecoverable error is found, it doesn't
1056 make sense to reinsert the link, so we leave it out
1057 and the cache will no longer register as full.
1058 */
1059 PyObject *oldkey, *oldresult, *popresult;
1060
1061 /* Extract the oldest item. */
1062 assert(self->root.next != &self->root);
1063 link = self->root.next;
1064 lru_cache_extract_link(link);
1065 /* Remove it from the cache.
Raymond Hettinger2dda72a2019-02-08 18:55:02 -08001066 The cache dict holds one reference to the link.
1067 We created one other reference when the link was created.
1068 The linked list only has borrowed references. */
Raymond Hettingerd8080c02019-01-26 03:02:00 -05001069 popresult = _PyDict_Pop_KnownHash(self->cache, link->key,
1070 link->hash, Py_None);
1071 if (popresult == Py_None) {
1072 /* Getting here means that the user function call or another
1073 thread has already removed the old key from the dictionary.
Raymond Hettinger2dda72a2019-02-08 18:55:02 -08001074 This link is now an orphan. Since we don't want to leave the
Raymond Hettingerd8080c02019-01-26 03:02:00 -05001075 cache in an inconsistent state, we don't restore the link. */
1076 Py_DECREF(popresult);
1077 Py_DECREF(link);
1078 Py_DECREF(key);
1079 return result;
1080 }
1081 if (popresult == NULL) {
1082 /* An error arose while trying to remove the oldest key (the one
1083 being evicted) from the cache. We restore the link to its
1084 original position as the oldest link. Then we allow the
1085 error propagate upward; treating it the same as an error
1086 arising in the user function. */
1087 lru_cache_prepend_link(self, link);
1088 Py_DECREF(key);
1089 Py_DECREF(result);
1090 return NULL;
1091 }
1092 /* Keep a reference to the old key and old result to prevent their
1093 ref counts from going to zero during the update. That will
1094 prevent potentially arbitrary object clean-up code (i.e. __del__)
1095 from running while we're still adjusting the links. */
1096 oldkey = link->key;
1097 oldresult = link->result;
1098
1099 link->hash = hash;
1100 link->key = key;
1101 link->result = result;
1102 /* Note: The link is being added to the cache dict without the
1103 prev and next fields set to valid values. We have to wait
1104 for successful insertion in the cache dict before adding the
1105 link to the linked list. Otherwise, the potentially reentrant
Raymond Hettinger2dda72a2019-02-08 18:55:02 -08001106 __eq__ call could cause the then orphan link to be visited. */
Raymond Hettingerd8080c02019-01-26 03:02:00 -05001107 if (_PyDict_SetItem_KnownHash(self->cache, key, (PyObject *)link,
1108 hash) < 0) {
1109 /* Somehow the cache dict update failed. We no longer can
1110 restore the old link. Let the error propagate upward and
1111 leave the cache short one link. */
1112 Py_DECREF(popresult);
1113 Py_DECREF(link);
1114 Py_DECREF(oldkey);
1115 Py_DECREF(oldresult);
1116 return NULL;
1117 }
1118 lru_cache_append_link(self, link);
1119 Py_INCREF(result); /* for return */
1120 Py_DECREF(popresult);
1121 Py_DECREF(oldkey);
1122 Py_DECREF(oldresult);
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001123 return result;
1124}
1125
1126static PyObject *
1127lru_cache_new(PyTypeObject *type, PyObject *args, PyObject *kw)
1128{
Serhiy Storchaka374164c2015-07-25 12:10:21 +03001129 PyObject *func, *maxsize_O, *cache_info_type, *cachedict;
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001130 int typed;
1131 lru_cache_object *obj;
1132 Py_ssize_t maxsize;
1133 PyObject *(*wrapper)(lru_cache_object *, PyObject *, PyObject *);
1134 static char *keywords[] = {"user_function", "maxsize", "typed",
1135 "cache_info_type", NULL};
1136
1137 if (!PyArg_ParseTupleAndKeywords(args, kw, "OOpO:lru_cache", keywords,
1138 &func, &maxsize_O, &typed,
1139 &cache_info_type)) {
1140 return NULL;
1141 }
1142
1143 if (!PyCallable_Check(func)) {
1144 PyErr_SetString(PyExc_TypeError,
1145 "the first argument must be callable");
1146 return NULL;
1147 }
1148
1149 /* select the caching function, and make/inc maxsize_O */
1150 if (maxsize_O == Py_None) {
1151 wrapper = infinite_lru_cache_wrapper;
1152 /* use this only to initialize lru_cache_object attribute maxsize */
1153 maxsize = -1;
1154 } else if (PyIndex_Check(maxsize_O)) {
1155 maxsize = PyNumber_AsSsize_t(maxsize_O, PyExc_OverflowError);
1156 if (maxsize == -1 && PyErr_Occurred())
1157 return NULL;
Raymond Hettingerd8080c02019-01-26 03:02:00 -05001158 if (maxsize < 0) {
1159 maxsize = 0;
1160 }
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001161 if (maxsize == 0)
1162 wrapper = uncached_lru_cache_wrapper;
1163 else
1164 wrapper = bounded_lru_cache_wrapper;
1165 } else {
1166 PyErr_SetString(PyExc_TypeError, "maxsize should be integer or None");
1167 return NULL;
1168 }
1169
Serhiy Storchaka374164c2015-07-25 12:10:21 +03001170 if (!(cachedict = PyDict_New()))
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001171 return NULL;
1172
Serhiy Storchaka374164c2015-07-25 12:10:21 +03001173 obj = (lru_cache_object *)type->tp_alloc(type, 0);
1174 if (obj == NULL) {
1175 Py_DECREF(cachedict);
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001176 return NULL;
1177 }
1178
1179 obj->root.prev = &obj->root;
1180 obj->root.next = &obj->root;
Raymond Hettingerd8080c02019-01-26 03:02:00 -05001181 obj->wrapper = wrapper;
1182 obj->typed = typed;
1183 obj->cache = cachedict;
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001184 Py_INCREF(func);
1185 obj->func = func;
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001186 obj->misses = obj->hits = 0;
Raymond Hettingerd8080c02019-01-26 03:02:00 -05001187 obj->maxsize = maxsize;
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001188 Py_INCREF(cache_info_type);
1189 obj->cache_info_type = cache_info_type;
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001190 return (PyObject *)obj;
1191}
1192
1193static lru_list_elem *
1194lru_cache_unlink_list(lru_cache_object *self)
1195{
1196 lru_list_elem *root = &self->root;
1197 lru_list_elem *link = root->next;
1198 if (link == root)
1199 return NULL;
1200 root->prev->next = NULL;
1201 root->next = root->prev = root;
1202 return link;
1203}
1204
1205static void
1206lru_cache_clear_list(lru_list_elem *link)
1207{
1208 while (link != NULL) {
1209 lru_list_elem *next = link->next;
1210 Py_DECREF(link);
1211 link = next;
1212 }
1213}
1214
1215static void
1216lru_cache_dealloc(lru_cache_object *obj)
1217{
INADA Naokia6296d32017-08-24 14:55:17 +09001218 lru_list_elem *list;
1219 /* bpo-31095: UnTrack is needed before calling any callbacks */
1220 PyObject_GC_UnTrack(obj);
1221
1222 list = lru_cache_unlink_list(obj);
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001223 Py_XDECREF(obj->cache);
Raymond Hettingerd8080c02019-01-26 03:02:00 -05001224 Py_XDECREF(obj->func);
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001225 Py_XDECREF(obj->cache_info_type);
Raymond Hettingerd8080c02019-01-26 03:02:00 -05001226 Py_XDECREF(obj->dict);
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001227 lru_cache_clear_list(list);
1228 Py_TYPE(obj)->tp_free(obj);
1229}
1230
1231static PyObject *
1232lru_cache_call(lru_cache_object *self, PyObject *args, PyObject *kwds)
1233{
1234 return self->wrapper(self, args, kwds);
1235}
1236
1237static PyObject *
Serhiy Storchakae7070f02015-06-08 11:19:24 +03001238lru_cache_descr_get(PyObject *self, PyObject *obj, PyObject *type)
1239{
1240 if (obj == Py_None || obj == NULL) {
1241 Py_INCREF(self);
1242 return self;
1243 }
1244 return PyMethod_New(self, obj);
1245}
1246
1247static PyObject *
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001248lru_cache_cache_info(lru_cache_object *self, PyObject *unused)
1249{
Raymond Hettingerd8080c02019-01-26 03:02:00 -05001250 if (self->maxsize == -1) {
1251 return PyObject_CallFunction(self->cache_info_type, "nnOn",
1252 self->hits, self->misses, Py_None,
1253 PyDict_GET_SIZE(self->cache));
1254 }
1255 return PyObject_CallFunction(self->cache_info_type, "nnnn",
1256 self->hits, self->misses, self->maxsize,
Serhiy Storchaka5ab81d72016-12-16 16:18:57 +02001257 PyDict_GET_SIZE(self->cache));
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001258}
1259
1260static PyObject *
1261lru_cache_cache_clear(lru_cache_object *self, PyObject *unused)
1262{
1263 lru_list_elem *list = lru_cache_unlink_list(self);
1264 self->hits = self->misses = 0;
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001265 PyDict_Clear(self->cache);
1266 lru_cache_clear_list(list);
1267 Py_RETURN_NONE;
1268}
1269
Serhiy Storchaka45120f22015-10-24 09:49:56 +03001270static PyObject *
1271lru_cache_reduce(PyObject *self, PyObject *unused)
1272{
1273 return PyObject_GetAttrString(self, "__qualname__");
1274}
1275
Serhiy Storchakae4d65e32015-12-28 23:58:07 +02001276static PyObject *
1277lru_cache_copy(PyObject *self, PyObject *unused)
1278{
1279 Py_INCREF(self);
1280 return self;
1281}
1282
1283static PyObject *
1284lru_cache_deepcopy(PyObject *self, PyObject *unused)
1285{
1286 Py_INCREF(self);
1287 return self;
1288}
1289
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001290static int
1291lru_cache_tp_traverse(lru_cache_object *self, visitproc visit, void *arg)
1292{
1293 lru_list_elem *link = self->root.next;
1294 while (link != &self->root) {
1295 lru_list_elem *next = link->next;
INADA Naoki3070b712017-12-26 02:03:24 +09001296 Py_VISIT(link->key);
1297 Py_VISIT(link->result);
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001298 link = next;
1299 }
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001300 Py_VISIT(self->func);
1301 Py_VISIT(self->cache);
1302 Py_VISIT(self->cache_info_type);
1303 Py_VISIT(self->dict);
1304 return 0;
1305}
1306
1307static int
1308lru_cache_tp_clear(lru_cache_object *self)
1309{
1310 lru_list_elem *list = lru_cache_unlink_list(self);
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001311 Py_CLEAR(self->func);
1312 Py_CLEAR(self->cache);
1313 Py_CLEAR(self->cache_info_type);
1314 Py_CLEAR(self->dict);
1315 lru_cache_clear_list(list);
1316 return 0;
1317}
1318
1319
1320PyDoc_STRVAR(lru_cache_doc,
1321"Create a cached callable that wraps another function.\n\
1322\n\
1323user_function: the function being cached\n\
1324\n\
1325maxsize: 0 for no caching\n\
1326 None for unlimited cache size\n\
1327 n for a bounded cache\n\
1328\n\
1329typed: False cache f(3) and f(3.0) as identical calls\n\
1330 True cache f(3) and f(3.0) as distinct calls\n\
1331\n\
1332cache_info_type: namedtuple class with the fields:\n\
1333 hits misses currsize maxsize\n"
1334);
1335
1336static PyMethodDef lru_cache_methods[] = {
1337 {"cache_info", (PyCFunction)lru_cache_cache_info, METH_NOARGS},
1338 {"cache_clear", (PyCFunction)lru_cache_cache_clear, METH_NOARGS},
Serhiy Storchaka45120f22015-10-24 09:49:56 +03001339 {"__reduce__", (PyCFunction)lru_cache_reduce, METH_NOARGS},
Serhiy Storchakae4d65e32015-12-28 23:58:07 +02001340 {"__copy__", (PyCFunction)lru_cache_copy, METH_VARARGS},
1341 {"__deepcopy__", (PyCFunction)lru_cache_deepcopy, METH_VARARGS},
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001342 {NULL}
1343};
1344
1345static PyGetSetDef lru_cache_getsetlist[] = {
1346 {"__dict__", PyObject_GenericGetDict, PyObject_GenericSetDict},
1347 {NULL}
1348};
1349
1350static PyTypeObject lru_cache_type = {
1351 PyVarObject_HEAD_INIT(NULL, 0)
1352 "functools._lru_cache_wrapper", /* tp_name */
1353 sizeof(lru_cache_object), /* tp_basicsize */
1354 0, /* tp_itemsize */
1355 /* methods */
1356 (destructor)lru_cache_dealloc, /* tp_dealloc */
Jeroen Demeyer530f5062019-05-31 04:13:39 +02001357 0, /* tp_vectorcall_offset */
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001358 0, /* tp_getattr */
1359 0, /* tp_setattr */
Jeroen Demeyer530f5062019-05-31 04:13:39 +02001360 0, /* tp_as_async */
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001361 0, /* tp_repr */
1362 0, /* tp_as_number */
1363 0, /* tp_as_sequence */
1364 0, /* tp_as_mapping */
1365 0, /* tp_hash */
1366 (ternaryfunc)lru_cache_call, /* tp_call */
1367 0, /* tp_str */
1368 0, /* tp_getattro */
1369 0, /* tp_setattro */
1370 0, /* tp_as_buffer */
Jeroen Demeyereb65e242019-05-28 14:42:53 +02001371 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE |
1372 Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_METHOD_DESCRIPTOR,
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001373 /* tp_flags */
1374 lru_cache_doc, /* tp_doc */
1375 (traverseproc)lru_cache_tp_traverse,/* tp_traverse */
1376 (inquiry)lru_cache_tp_clear, /* tp_clear */
1377 0, /* tp_richcompare */
1378 0, /* tp_weaklistoffset */
1379 0, /* tp_iter */
1380 0, /* tp_iternext */
1381 lru_cache_methods, /* tp_methods */
1382 0, /* tp_members */
1383 lru_cache_getsetlist, /* tp_getset */
1384 0, /* tp_base */
1385 0, /* tp_dict */
Serhiy Storchakae7070f02015-06-08 11:19:24 +03001386 lru_cache_descr_get, /* tp_descr_get */
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001387 0, /* tp_descr_set */
1388 offsetof(lru_cache_object, dict), /* tp_dictoffset */
1389 0, /* tp_init */
1390 0, /* tp_alloc */
1391 lru_cache_new, /* tp_new */
1392};
1393
Raymond Hettinger9c323f82005-02-28 19:39:44 +00001394/* module level code ********************************************************/
1395
1396PyDoc_STRVAR(module_doc,
Thomas Wouters4d70c3d2006-06-08 14:42:34 +00001397"Tools that operate on functions.");
Raymond Hettinger9c323f82005-02-28 19:39:44 +00001398
1399static PyMethodDef module_methods[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001400 {"reduce", functools_reduce, METH_VARARGS, functools_reduce_doc},
Serhiy Storchaka62be7422018-11-27 13:27:31 +02001401 {"cmp_to_key", (PyCFunction)(void(*)(void))functools_cmp_to_key,
Victor Stinner446c8d52011-04-05 12:21:35 +02001402 METH_VARARGS | METH_KEYWORDS, functools_cmp_to_key_doc},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001403 {NULL, NULL} /* sentinel */
Raymond Hettinger9c323f82005-02-28 19:39:44 +00001404};
1405
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001406static void
1407module_free(void *m)
1408{
1409 Py_CLEAR(kwd_mark);
1410}
Martin v. Löwis1a214512008-06-11 05:26:20 +00001411
1412static struct PyModuleDef _functoolsmodule = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001413 PyModuleDef_HEAD_INIT,
1414 "_functools",
1415 module_doc,
1416 -1,
1417 module_methods,
1418 NULL,
1419 NULL,
1420 NULL,
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001421 module_free,
Martin v. Löwis1a214512008-06-11 05:26:20 +00001422};
1423
Raymond Hettinger9c323f82005-02-28 19:39:44 +00001424PyMODINIT_FUNC
Martin v. Löwis1a214512008-06-11 05:26:20 +00001425PyInit__functools(void)
Raymond Hettinger9c323f82005-02-28 19:39:44 +00001426{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001427 int i;
1428 PyObject *m;
Serhiy Storchaka4ab46d72017-09-17 21:11:04 +03001429 const char *name;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001430 PyTypeObject *typelist[] = {
1431 &partial_type,
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001432 &lru_cache_type,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001433 NULL
1434 };
Raymond Hettinger9c323f82005-02-28 19:39:44 +00001435
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001436 m = PyModule_Create(&_functoolsmodule);
1437 if (m == NULL)
1438 return NULL;
Raymond Hettinger9c323f82005-02-28 19:39:44 +00001439
Victor Stinnera5ed5f02016-12-06 18:45:50 +01001440 kwd_mark = _PyObject_CallNoArg((PyObject *)&PyBaseObject_Type);
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001441 if (!kwd_mark) {
1442 Py_DECREF(m);
1443 return NULL;
1444 }
1445
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001446 for (i=0 ; typelist[i] != NULL ; i++) {
1447 if (PyType_Ready(typelist[i]) < 0) {
1448 Py_DECREF(m);
1449 return NULL;
1450 }
Serhiy Storchaka4ab46d72017-09-17 21:11:04 +03001451 name = _PyType_Name(typelist[i]);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001452 Py_INCREF(typelist[i]);
Serhiy Storchaka4ab46d72017-09-17 21:11:04 +03001453 PyModule_AddObject(m, name, (PyObject *)typelist[i]);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001454 }
1455 return m;
Raymond Hettinger9c323f82005-02-28 19:39:44 +00001456}