blob: a101363bf02a07dedfa3184a52fc42c46bbb660c [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;
21 PyObject *dict;
22 PyObject *weakreflist; /* List of weak references */
Victor Stinner0f7b0b32017-03-14 21:37:20 +010023 int use_fastcall;
Raymond Hettinger9c323f82005-02-28 19:39:44 +000024} partialobject;
25
26static PyTypeObject partial_type;
27
28static PyObject *
29partial_new(PyTypeObject *type, PyObject *args, PyObject *kw)
30{
Alexander Belopolskye49af342015-03-01 15:08:17 -050031 PyObject *func, *pargs, *nargs, *pkw;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000032 partialobject *pto;
Raymond Hettinger9c323f82005-02-28 19:39:44 +000033
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000034 if (PyTuple_GET_SIZE(args) < 1) {
35 PyErr_SetString(PyExc_TypeError,
36 "type 'partial' takes at least one argument");
37 return NULL;
38 }
Raymond Hettinger9c323f82005-02-28 19:39:44 +000039
Serhiy Storchaka38741282016-02-02 18:45:17 +020040 pargs = pkw = NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000041 func = PyTuple_GET_ITEM(args, 0);
Alexander Belopolskye49af342015-03-01 15:08:17 -050042 if (Py_TYPE(func) == &partial_type && type == &partial_type) {
43 partialobject *part = (partialobject *)func;
44 if (part->dict == NULL) {
45 pargs = part->args;
46 pkw = part->kw;
47 func = part->fn;
Serhiy Storchaka38741282016-02-02 18:45:17 +020048 assert(PyTuple_Check(pargs));
49 assert(PyDict_Check(pkw));
Alexander Belopolskye49af342015-03-01 15:08:17 -050050 }
51 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000052 if (!PyCallable_Check(func)) {
53 PyErr_SetString(PyExc_TypeError,
54 "the first argument must be callable");
55 return NULL;
56 }
Raymond Hettinger9c323f82005-02-28 19:39:44 +000057
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000058 /* create partialobject structure */
59 pto = (partialobject *)type->tp_alloc(type, 0);
60 if (pto == NULL)
61 return NULL;
Raymond Hettinger9c323f82005-02-28 19:39:44 +000062
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000063 pto->fn = func;
64 Py_INCREF(func);
Alexander Belopolskye49af342015-03-01 15:08:17 -050065
66 nargs = PyTuple_GetSlice(args, 1, PY_SSIZE_T_MAX);
67 if (nargs == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000068 Py_DECREF(pto);
69 return NULL;
70 }
Serhiy Storchaka3c749fc2017-03-25 12:10:16 +020071 if (pargs == NULL) {
Alexander Belopolskye49af342015-03-01 15:08:17 -050072 pto->args = nargs;
Alexander Belopolskye49af342015-03-01 15:08:17 -050073 }
74 else {
75 pto->args = PySequence_Concat(pargs, nargs);
Serhiy Storchaka3c749fc2017-03-25 12:10:16 +020076 Py_DECREF(nargs);
Alexander Belopolskye49af342015-03-01 15:08:17 -050077 if (pto->args == NULL) {
Alexander Belopolskye49af342015-03-01 15:08:17 -050078 Py_DECREF(pto);
79 return NULL;
80 }
Serhiy Storchaka38741282016-02-02 18:45:17 +020081 assert(PyTuple_Check(pto->args));
Alexander Belopolskye49af342015-03-01 15:08:17 -050082 }
Alexander Belopolskye49af342015-03-01 15:08:17 -050083
Serhiy Storchaka5ab81d72016-12-16 16:18:57 +020084 if (pkw == NULL || PyDict_GET_SIZE(pkw) == 0) {
Serhiy Storchaka38741282016-02-02 18:45:17 +020085 if (kw == NULL) {
86 pto->kw = PyDict_New();
Alexander Belopolskye49af342015-03-01 15:08:17 -050087 }
Serhiy Storchaka9639e4a2017-02-20 14:04:30 +020088 else if (Py_REFCNT(kw) == 1) {
Serhiy Storchaka38741282016-02-02 18:45:17 +020089 Py_INCREF(kw);
90 pto->kw = kw;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000091 }
Serhiy Storchaka9639e4a2017-02-20 14:04:30 +020092 else {
93 pto->kw = PyDict_Copy(kw);
94 }
Alexander Belopolskye49af342015-03-01 15:08:17 -050095 }
96 else {
Serhiy Storchaka38741282016-02-02 18:45:17 +020097 pto->kw = PyDict_Copy(pkw);
98 if (kw != NULL && pto->kw != NULL) {
99 if (PyDict_Merge(pto->kw, kw, 1) != 0) {
Benjamin Petersondae2ef12015-05-09 00:29:08 -0400100 Py_DECREF(pto);
101 return NULL;
102 }
103 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000104 }
Serhiy Storchaka38741282016-02-02 18:45:17 +0200105 if (pto->kw == NULL) {
106 Py_DECREF(pto);
107 return NULL;
108 }
Raymond Hettingerc8b6d1b2005-03-08 06:14:50 +0000109
Jeroen Demeyerc145f3b2019-05-30 12:43:59 +0200110 pto->use_fastcall = (_PyVectorcall_Function(func) != NULL);
Victor Stinner0f7b0b32017-03-14 21:37:20 +0100111
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000112 return (PyObject *)pto;
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000113}
114
115static void
116partial_dealloc(partialobject *pto)
117{
INADA Naokia6296d32017-08-24 14:55:17 +0900118 /* bpo-31095: UnTrack is needed before calling any callbacks */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000119 PyObject_GC_UnTrack(pto);
120 if (pto->weakreflist != NULL)
121 PyObject_ClearWeakRefs((PyObject *) pto);
122 Py_XDECREF(pto->fn);
123 Py_XDECREF(pto->args);
124 Py_XDECREF(pto->kw);
125 Py_XDECREF(pto->dict);
126 Py_TYPE(pto)->tp_free(pto);
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000127}
128
129static PyObject *
Victor Stinner0f7b0b32017-03-14 21:37:20 +0100130partial_fastcall(partialobject *pto, PyObject **args, Py_ssize_t nargs,
131 PyObject *kwargs)
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000132{
Victor Stinner0f7b0b32017-03-14 21:37:20 +0100133 PyObject *small_stack[_PY_FASTCALL_SMALL_STACK];
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000134 PyObject *ret;
Victor Stinner0f7b0b32017-03-14 21:37:20 +0100135 PyObject **stack, **stack_buf = NULL;
136 Py_ssize_t nargs2, pto_nargs;
137
138 pto_nargs = PyTuple_GET_SIZE(pto->args);
139 nargs2 = pto_nargs + nargs;
140
141 if (pto_nargs == 0) {
142 stack = args;
143 }
144 else if (nargs == 0) {
Victor Stinnerd17a6932018-11-09 16:56:48 +0100145 stack = _PyTuple_ITEMS(pto->args);
Victor Stinner0f7b0b32017-03-14 21:37:20 +0100146 }
147 else {
148 if (nargs2 <= (Py_ssize_t)Py_ARRAY_LENGTH(small_stack)) {
149 stack = small_stack;
150 }
151 else {
152 stack_buf = PyMem_Malloc(nargs2 * sizeof(PyObject *));
153 if (stack_buf == NULL) {
154 PyErr_NoMemory();
155 return NULL;
156 }
157 stack = stack_buf;
158 }
159
160 /* use borrowed references */
161 memcpy(stack,
Victor Stinnerd17a6932018-11-09 16:56:48 +0100162 _PyTuple_ITEMS(pto->args),
Victor Stinner0f7b0b32017-03-14 21:37:20 +0100163 pto_nargs * sizeof(PyObject*));
164 memcpy(&stack[pto_nargs],
165 args,
166 nargs * sizeof(PyObject*));
167 }
168
169 ret = _PyObject_FastCallDict(pto->fn, stack, nargs2, kwargs);
170 PyMem_Free(stack_buf);
171 return ret;
172}
173
174static PyObject *
175partial_call_impl(partialobject *pto, PyObject *args, PyObject *kwargs)
176{
177 PyObject *ret, *args2;
178
179 /* Note: tupleconcat() is optimized for empty tuples */
180 args2 = PySequence_Concat(pto->args, args);
181 if (args2 == NULL) {
182 return NULL;
183 }
184 assert(PyTuple_Check(args2));
185
186 ret = PyObject_Call(pto->fn, args2, kwargs);
187 Py_DECREF(args2);
188 return ret;
189}
190
191static PyObject *
192partial_call(partialobject *pto, PyObject *args, PyObject *kwargs)
193{
194 PyObject *kwargs2, *res;
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000195
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000196 assert (PyCallable_Check(pto->fn));
197 assert (PyTuple_Check(pto->args));
Serhiy Storchaka38741282016-02-02 18:45:17 +0200198 assert (PyDict_Check(pto->kw));
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000199
Serhiy Storchaka5ab81d72016-12-16 16:18:57 +0200200 if (PyDict_GET_SIZE(pto->kw) == 0) {
Victor Stinner0f7b0b32017-03-14 21:37:20 +0100201 /* kwargs can be NULL */
202 kwargs2 = kwargs;
203 Py_XINCREF(kwargs2);
Victor Stinnerf4d28d42016-08-23 16:22:35 +0200204 }
205 else {
Victor Stinner561ca802017-02-23 18:26:43 +0100206 /* bpo-27840, bpo-29318: dictionary of keyword parameters must be
207 copied, because a function using "**kwargs" can modify the
208 dictionary. */
Victor Stinner0f7b0b32017-03-14 21:37:20 +0100209 kwargs2 = PyDict_Copy(pto->kw);
210 if (kwargs2 == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000211 return NULL;
212 }
Victor Stinnerf4d28d42016-08-23 16:22:35 +0200213
Victor Stinner0f7b0b32017-03-14 21:37:20 +0100214 if (kwargs != NULL) {
215 if (PyDict_Merge(kwargs2, kwargs, 1) != 0) {
216 Py_DECREF(kwargs2);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000217 return NULL;
218 }
219 }
220 }
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000221
Victor Stinner0f7b0b32017-03-14 21:37:20 +0100222
223 if (pto->use_fastcall) {
224 res = partial_fastcall(pto,
Victor Stinnerd17a6932018-11-09 16:56:48 +0100225 _PyTuple_ITEMS(args),
Victor Stinner0f7b0b32017-03-14 21:37:20 +0100226 PyTuple_GET_SIZE(args),
227 kwargs2);
Victor Stinnerf4d28d42016-08-23 16:22:35 +0200228 }
229 else {
Victor Stinner0f7b0b32017-03-14 21:37:20 +0100230 res = partial_call_impl(pto, args, kwargs2);
Victor Stinnerf4d28d42016-08-23 16:22:35 +0200231 }
Victor Stinner0f7b0b32017-03-14 21:37:20 +0100232 Py_XDECREF(kwargs2);
233 return res;
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000234}
235
236static int
237partial_traverse(partialobject *pto, visitproc visit, void *arg)
238{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000239 Py_VISIT(pto->fn);
240 Py_VISIT(pto->args);
241 Py_VISIT(pto->kw);
242 Py_VISIT(pto->dict);
243 return 0;
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000244}
245
246PyDoc_STRVAR(partial_doc,
247"partial(func, *args, **keywords) - new function with partial application\n\
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000248 of the given arguments and keywords.\n");
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000249
250#define OFF(x) offsetof(partialobject, x)
251static PyMemberDef partial_memberlist[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000252 {"func", T_OBJECT, OFF(fn), READONLY,
253 "function object to use in future partial calls"},
254 {"args", T_OBJECT, OFF(args), READONLY,
255 "tuple of arguments to future partial calls"},
256 {"keywords", T_OBJECT, OFF(kw), READONLY,
257 "dictionary of keyword arguments to future partial calls"},
258 {NULL} /* Sentinel */
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000259};
260
Georg Brandlc2fb6c72006-02-21 17:49:57 +0000261static PyGetSetDef partial_getsetlist[] = {
Benjamin Peterson23d7f122012-02-19 20:02:57 -0500262 {"__dict__", PyObject_GenericGetDict, PyObject_GenericSetDict},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000263 {NULL} /* Sentinel */
Raymond Hettingerc8b6d1b2005-03-08 06:14:50 +0000264};
265
Alexander Belopolsky41e422a2010-12-01 20:05:49 +0000266static PyObject *
267partial_repr(partialobject *pto)
268{
Serhiy Storchaka179f9602016-06-12 11:44:06 +0300269 PyObject *result = NULL;
Alexander Belopolsky41e422a2010-12-01 20:05:49 +0000270 PyObject *arglist;
Alexander Belopolsky41e422a2010-12-01 20:05:49 +0000271 Py_ssize_t i, n;
Serhiy Storchaka38741282016-02-02 18:45:17 +0200272 PyObject *key, *value;
Serhiy Storchaka179f9602016-06-12 11:44:06 +0300273 int status;
274
275 status = Py_ReprEnter((PyObject *)pto);
276 if (status != 0) {
277 if (status < 0)
278 return NULL;
Nick Coghlan457fc9a2016-09-10 20:00:02 +1000279 return PyUnicode_FromString("...");
Serhiy Storchaka179f9602016-06-12 11:44:06 +0300280 }
Alexander Belopolsky41e422a2010-12-01 20:05:49 +0000281
282 arglist = PyUnicode_FromString("");
Serhiy Storchaka179f9602016-06-12 11:44:06 +0300283 if (arglist == NULL)
284 goto done;
Alexander Belopolsky41e422a2010-12-01 20:05:49 +0000285 /* Pack positional arguments */
286 assert (PyTuple_Check(pto->args));
287 n = PyTuple_GET_SIZE(pto->args);
288 for (i = 0; i < n; i++) {
Serhiy Storchaka179f9602016-06-12 11:44:06 +0300289 Py_SETREF(arglist, PyUnicode_FromFormat("%U, %R", arglist,
290 PyTuple_GET_ITEM(pto->args, i)));
291 if (arglist == NULL)
292 goto done;
Alexander Belopolsky41e422a2010-12-01 20:05:49 +0000293 }
294 /* Pack keyword arguments */
Serhiy Storchaka38741282016-02-02 18:45:17 +0200295 assert (PyDict_Check(pto->kw));
296 for (i = 0; PyDict_Next(pto->kw, &i, &key, &value);) {
Michael Seifert6c3d5272017-03-15 06:26:33 +0100297 /* Prevent key.__str__ from deleting the value. */
298 Py_INCREF(value);
299 Py_SETREF(arglist, PyUnicode_FromFormat("%U, %S=%R", arglist,
Serhiy Storchaka179f9602016-06-12 11:44:06 +0300300 key, value));
Michael Seifert6c3d5272017-03-15 06:26:33 +0100301 Py_DECREF(value);
Serhiy Storchaka179f9602016-06-12 11:44:06 +0300302 if (arglist == NULL)
303 goto done;
Alexander Belopolsky41e422a2010-12-01 20:05:49 +0000304 }
305 result = PyUnicode_FromFormat("%s(%R%U)", Py_TYPE(pto)->tp_name,
306 pto->fn, arglist);
307 Py_DECREF(arglist);
Serhiy Storchaka179f9602016-06-12 11:44:06 +0300308
309 done:
310 Py_ReprLeave((PyObject *)pto);
Alexander Belopolsky41e422a2010-12-01 20:05:49 +0000311 return result;
312}
313
Jack Diederiche0cbd692009-04-01 04:27:09 +0000314/* Pickle strategy:
315 __reduce__ by itself doesn't support getting kwargs in the unpickle
316 operation so we define a __setstate__ that replaces all the information
317 about the partial. If we only replaced part of it someone would use
Ezio Melotti13925002011-03-16 11:05:33 +0200318 it as a hook to do strange things.
Jack Diederiche0cbd692009-04-01 04:27:09 +0000319 */
320
Antoine Pitrou69f71142009-05-24 21:25:49 +0000321static PyObject *
Jack Diederiche0cbd692009-04-01 04:27:09 +0000322partial_reduce(partialobject *pto, PyObject *unused)
323{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000324 return Py_BuildValue("O(O)(OOOO)", Py_TYPE(pto), pto->fn, pto->fn,
325 pto->args, pto->kw,
326 pto->dict ? pto->dict : Py_None);
Jack Diederiche0cbd692009-04-01 04:27:09 +0000327}
328
Antoine Pitrou69f71142009-05-24 21:25:49 +0000329static PyObject *
Serhiy Storchaka19c4e0d2013-02-04 12:47:24 +0200330partial_setstate(partialobject *pto, PyObject *state)
Jack Diederiche0cbd692009-04-01 04:27:09 +0000331{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000332 PyObject *fn, *fnargs, *kw, *dict;
Serhiy Storchaka38741282016-02-02 18:45:17 +0200333
334 if (!PyTuple_Check(state) ||
335 !PyArg_ParseTuple(state, "OOOO", &fn, &fnargs, &kw, &dict) ||
336 !PyCallable_Check(fn) ||
337 !PyTuple_Check(fnargs) ||
338 (kw != Py_None && !PyDict_Check(kw)))
339 {
340 PyErr_SetString(PyExc_TypeError, "invalid partial state");
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000341 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000342 }
Serhiy Storchaka38741282016-02-02 18:45:17 +0200343
344 if(!PyTuple_CheckExact(fnargs))
345 fnargs = PySequence_Tuple(fnargs);
346 else
347 Py_INCREF(fnargs);
348 if (fnargs == NULL)
349 return NULL;
350
351 if (kw == Py_None)
352 kw = PyDict_New();
353 else if(!PyDict_CheckExact(kw))
354 kw = PyDict_Copy(kw);
355 else
356 Py_INCREF(kw);
357 if (kw == NULL) {
358 Py_DECREF(fnargs);
359 return NULL;
360 }
361
Serhiy Storchaka38741282016-02-02 18:45:17 +0200362 if (dict == Py_None)
363 dict = NULL;
364 else
365 Py_INCREF(dict);
366
Victor Stinner0f7b0b32017-03-14 21:37:20 +0100367 Py_INCREF(fn);
Jeroen Demeyerc145f3b2019-05-30 12:43:59 +0200368 pto->use_fastcall = (_PyVectorcall_Function(fn) != NULL);
Serhiy Storchaka864b63c2016-04-11 09:53:37 +0300369 Py_SETREF(pto->fn, fn);
370 Py_SETREF(pto->args, fnargs);
371 Py_SETREF(pto->kw, kw);
Serhiy Storchaka48842712016-04-06 09:45:48 +0300372 Py_XSETREF(pto->dict, dict);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000373 Py_RETURN_NONE;
Jack Diederiche0cbd692009-04-01 04:27:09 +0000374}
375
376static PyMethodDef partial_methods[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000377 {"__reduce__", (PyCFunction)partial_reduce, METH_NOARGS},
Serhiy Storchaka19c4e0d2013-02-04 12:47:24 +0200378 {"__setstate__", (PyCFunction)partial_setstate, METH_O},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000379 {NULL, NULL} /* sentinel */
Jack Diederiche0cbd692009-04-01 04:27:09 +0000380};
381
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000382static PyTypeObject partial_type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000383 PyVarObject_HEAD_INIT(NULL, 0)
384 "functools.partial", /* tp_name */
385 sizeof(partialobject), /* tp_basicsize */
386 0, /* tp_itemsize */
387 /* methods */
388 (destructor)partial_dealloc, /* tp_dealloc */
Jeroen Demeyer530f5062019-05-31 04:13:39 +0200389 0, /* tp_vectorcall_offset */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000390 0, /* tp_getattr */
391 0, /* tp_setattr */
Jeroen Demeyer530f5062019-05-31 04:13:39 +0200392 0, /* tp_as_async */
Alexander Belopolsky41e422a2010-12-01 20:05:49 +0000393 (reprfunc)partial_repr, /* tp_repr */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000394 0, /* tp_as_number */
395 0, /* tp_as_sequence */
396 0, /* tp_as_mapping */
397 0, /* tp_hash */
398 (ternaryfunc)partial_call, /* tp_call */
399 0, /* tp_str */
400 PyObject_GenericGetAttr, /* tp_getattro */
401 PyObject_GenericSetAttr, /* tp_setattro */
402 0, /* tp_as_buffer */
403 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
404 Py_TPFLAGS_BASETYPE, /* tp_flags */
405 partial_doc, /* tp_doc */
406 (traverseproc)partial_traverse, /* tp_traverse */
407 0, /* tp_clear */
408 0, /* tp_richcompare */
409 offsetof(partialobject, weakreflist), /* tp_weaklistoffset */
410 0, /* tp_iter */
411 0, /* tp_iternext */
412 partial_methods, /* tp_methods */
413 partial_memberlist, /* tp_members */
414 partial_getsetlist, /* tp_getset */
415 0, /* tp_base */
416 0, /* tp_dict */
417 0, /* tp_descr_get */
418 0, /* tp_descr_set */
419 offsetof(partialobject, dict), /* tp_dictoffset */
420 0, /* tp_init */
421 0, /* tp_alloc */
422 partial_new, /* tp_new */
423 PyObject_GC_Del, /* tp_free */
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000424};
425
426
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700427/* cmp_to_key ***************************************************************/
428
429typedef struct {
Victor Stinner446c8d52011-04-05 12:21:35 +0200430 PyObject_HEAD
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700431 PyObject *cmp;
432 PyObject *object;
433} keyobject;
434
435static void
436keyobject_dealloc(keyobject *ko)
437{
438 Py_DECREF(ko->cmp);
439 Py_XDECREF(ko->object);
440 PyObject_FREE(ko);
441}
442
443static int
444keyobject_traverse(keyobject *ko, visitproc visit, void *arg)
445{
446 Py_VISIT(ko->cmp);
447 if (ko->object)
448 Py_VISIT(ko->object);
449 return 0;
450}
451
Benjamin Peterson3bd97292011-04-05 17:25:14 -0500452static int
453keyobject_clear(keyobject *ko)
454{
455 Py_CLEAR(ko->cmp);
456 if (ko->object)
457 Py_CLEAR(ko->object);
458 return 0;
459}
460
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700461static PyMemberDef keyobject_members[] = {
462 {"obj", T_OBJECT,
463 offsetof(keyobject, object), 0,
464 PyDoc_STR("Value wrapped by a key function.")},
465 {NULL}
466};
467
468static PyObject *
Raymond Hettingera5632862011-04-09 12:57:00 -0700469keyobject_call(keyobject *ko, PyObject *args, PyObject *kwds);
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700470
471static PyObject *
472keyobject_richcompare(PyObject *ko, PyObject *other, int op);
473
474static PyTypeObject keyobject_type = {
475 PyVarObject_HEAD_INIT(&PyType_Type, 0)
476 "functools.KeyWrapper", /* tp_name */
477 sizeof(keyobject), /* tp_basicsize */
478 0, /* tp_itemsize */
479 /* methods */
480 (destructor)keyobject_dealloc, /* tp_dealloc */
Jeroen Demeyer530f5062019-05-31 04:13:39 +0200481 0, /* tp_vectorcall_offset */
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700482 0, /* tp_getattr */
483 0, /* tp_setattr */
Jeroen Demeyer530f5062019-05-31 04:13:39 +0200484 0, /* tp_as_async */
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700485 0, /* tp_repr */
486 0, /* tp_as_number */
487 0, /* tp_as_sequence */
488 0, /* tp_as_mapping */
489 0, /* tp_hash */
490 (ternaryfunc)keyobject_call, /* tp_call */
491 0, /* tp_str */
492 PyObject_GenericGetAttr, /* tp_getattro */
493 0, /* tp_setattro */
494 0, /* tp_as_buffer */
495 Py_TPFLAGS_DEFAULT, /* tp_flags */
496 0, /* tp_doc */
497 (traverseproc)keyobject_traverse, /* tp_traverse */
Benjamin Peterson3bd97292011-04-05 17:25:14 -0500498 (inquiry)keyobject_clear, /* tp_clear */
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700499 keyobject_richcompare, /* tp_richcompare */
500 0, /* tp_weaklistoffset */
501 0, /* tp_iter */
502 0, /* tp_iternext */
503 0, /* tp_methods */
504 keyobject_members, /* tp_members */
505 0, /* tp_getset */
506};
507
508static PyObject *
509keyobject_call(keyobject *ko, PyObject *args, PyObject *kwds)
510{
511 PyObject *object;
512 keyobject *result;
513 static char *kwargs[] = {"obj", NULL};
514
515 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:K", kwargs, &object))
516 return NULL;
517 result = PyObject_New(keyobject, &keyobject_type);
518 if (!result)
519 return NULL;
520 Py_INCREF(ko->cmp);
521 result->cmp = ko->cmp;
522 Py_INCREF(object);
523 result->object = object;
524 return (PyObject *)result;
525}
526
527static PyObject *
528keyobject_richcompare(PyObject *ko, PyObject *other, int op)
529{
530 PyObject *res;
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700531 PyObject *x;
532 PyObject *y;
533 PyObject *compare;
534 PyObject *answer;
Victor Stinnerf7a4c482016-08-19 18:52:35 +0200535 PyObject* stack[2];
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700536
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700537 if (Py_TYPE(other) != &keyobject_type){
538 PyErr_Format(PyExc_TypeError, "other argument must be K instance");
539 return NULL;
540 }
541 compare = ((keyobject *) ko)->cmp;
542 assert(compare != NULL);
543 x = ((keyobject *) ko)->object;
544 y = ((keyobject *) other)->object;
545 if (!x || !y){
546 PyErr_Format(PyExc_AttributeError, "object");
547 return NULL;
548 }
549
550 /* Call the user's comparison function and translate the 3-way
551 * result into true or false (or error).
552 */
Victor Stinnerf7a4c482016-08-19 18:52:35 +0200553 stack[0] = x;
554 stack[1] = y;
Victor Stinner559bb6a2016-08-22 22:48:54 +0200555 res = _PyObject_FastCall(compare, stack, 2);
Victor Stinnerf7a4c482016-08-19 18:52:35 +0200556 if (res == NULL) {
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700557 return NULL;
Victor Stinnerf7a4c482016-08-19 18:52:35 +0200558 }
559
Serhiy Storchakaba85d692017-03-30 09:09:41 +0300560 answer = PyObject_RichCompare(res, _PyLong_Zero, op);
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700561 Py_DECREF(res);
562 return answer;
563}
564
565static PyObject *
Victor Stinner446c8d52011-04-05 12:21:35 +0200566functools_cmp_to_key(PyObject *self, PyObject *args, PyObject *kwds)
567{
568 PyObject *cmp;
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700569 static char *kwargs[] = {"mycmp", NULL};
Victor Stinner446c8d52011-04-05 12:21:35 +0200570 keyobject *object;
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700571
572 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:cmp_to_key", kwargs, &cmp))
573 return NULL;
Victor Stinner446c8d52011-04-05 12:21:35 +0200574 object = PyObject_New(keyobject, &keyobject_type);
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700575 if (!object)
576 return NULL;
577 Py_INCREF(cmp);
578 object->cmp = cmp;
579 object->object = NULL;
580 return (PyObject *)object;
581}
582
583PyDoc_STRVAR(functools_cmp_to_key_doc,
584"Convert a cmp= function into a key= function.");
585
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000586/* reduce (used to be a builtin) ********************************************/
587
588static PyObject *
589functools_reduce(PyObject *self, PyObject *args)
590{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000591 PyObject *seq, *func, *result = NULL, *it;
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000592
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000593 if (!PyArg_UnpackTuple(args, "reduce", 2, 3, &func, &seq, &result))
594 return NULL;
595 if (result != NULL)
596 Py_INCREF(result);
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000597
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000598 it = PyObject_GetIter(seq);
599 if (it == NULL) {
Alexander Belopolskye29e6bf2010-08-16 18:55:46 +0000600 if (PyErr_ExceptionMatches(PyExc_TypeError))
601 PyErr_SetString(PyExc_TypeError,
602 "reduce() arg 2 must support iteration");
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000603 Py_XDECREF(result);
604 return NULL;
605 }
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000606
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000607 if ((args = PyTuple_New(2)) == NULL)
608 goto Fail;
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000609
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000610 for (;;) {
611 PyObject *op2;
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000612
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000613 if (args->ob_refcnt > 1) {
614 Py_DECREF(args);
615 if ((args = PyTuple_New(2)) == NULL)
616 goto Fail;
617 }
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000618
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000619 op2 = PyIter_Next(it);
620 if (op2 == NULL) {
621 if (PyErr_Occurred())
622 goto Fail;
623 break;
624 }
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000625
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000626 if (result == NULL)
627 result = op2;
628 else {
Sergey Fedoseeve5f62072019-06-02 01:32:18 +0500629 /* Update the args tuple in-place */
630 assert(args->ob_refcnt == 1);
631 Py_XSETREF(_PyTuple_ITEMS(args)[0], result);
632 Py_XSETREF(_PyTuple_ITEMS(args)[1], op2);
633 if ((result = PyObject_Call(func, args, NULL)) == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000634 goto Fail;
Sergey Fedoseeve5f62072019-06-02 01:32:18 +0500635 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000636 }
637 }
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000638
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000639 Py_DECREF(args);
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000640
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000641 if (result == NULL)
642 PyErr_SetString(PyExc_TypeError,
643 "reduce() of empty sequence with no initial value");
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000644
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000645 Py_DECREF(it);
646 return result;
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000647
648Fail:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000649 Py_XDECREF(args);
650 Py_XDECREF(result);
651 Py_DECREF(it);
652 return NULL;
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000653}
654
655PyDoc_STRVAR(functools_reduce_doc,
656"reduce(function, sequence[, initial]) -> value\n\
657\n\
658Apply a function of two arguments cumulatively to the items of a sequence,\n\
659from left to right, so as to reduce the sequence to a single value.\n\
660For example, reduce(lambda x, y: x+y, [1, 2, 3, 4, 5]) calculates\n\
661((((1+2)+3)+4)+5). If initial is present, it is placed before the items\n\
662of the sequence in the calculation, and serves as a default when the\n\
663sequence is empty.");
664
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300665/* lru_cache object **********************************************************/
666
Raymond Hettinger2dda72a2019-02-08 18:55:02 -0800667/* There are four principal algorithmic differences from the pure python version:
668
669 1). The C version relies on the GIL instead of having its own reentrant lock.
670
671 2). The prev/next link fields use borrowed references.
672
673 3). For a full cache, the pure python version rotates the location of the
674 root entry so that it never has to move individual links and it can
675 limit updates to just the key and result fields. However, in the C
676 version, links are temporarily removed while the cache dict updates are
677 occurring. Afterwards, they are appended or prepended back into the
678 doubly-linked lists.
679
680 4) In the Python version, the _HashSeq class is used to prevent __hash__
681 from being called more than once. In the C version, the "known hash"
682 variants of dictionary calls as used to the same effect.
683
684*/
685
686
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300687/* this object is used delimit args and keywords in the cache keys */
688static PyObject *kwd_mark = NULL;
689
690struct lru_list_elem;
691struct lru_cache_object;
692
693typedef struct lru_list_elem {
694 PyObject_HEAD
695 struct lru_list_elem *prev, *next; /* borrowed links */
Serhiy Storchakab9d98d52015-10-02 12:47:11 +0300696 Py_hash_t hash;
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300697 PyObject *key, *result;
698} lru_list_elem;
699
700static void
701lru_list_elem_dealloc(lru_list_elem *link)
702{
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300703 Py_XDECREF(link->key);
704 Py_XDECREF(link->result);
INADA Naoki3070b712017-12-26 02:03:24 +0900705 PyObject_Del(link);
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300706}
707
708static PyTypeObject lru_list_elem_type = {
709 PyVarObject_HEAD_INIT(&PyType_Type, 0)
710 "functools._lru_list_elem", /* tp_name */
711 sizeof(lru_list_elem), /* tp_basicsize */
712 0, /* tp_itemsize */
713 /* methods */
714 (destructor)lru_list_elem_dealloc, /* tp_dealloc */
Jeroen Demeyer530f5062019-05-31 04:13:39 +0200715 0, /* tp_vectorcall_offset */
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300716 0, /* tp_getattr */
717 0, /* tp_setattr */
Jeroen Demeyer530f5062019-05-31 04:13:39 +0200718 0, /* tp_as_async */
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300719 0, /* tp_repr */
720 0, /* tp_as_number */
721 0, /* tp_as_sequence */
722 0, /* tp_as_mapping */
723 0, /* tp_hash */
724 0, /* tp_call */
725 0, /* tp_str */
726 0, /* tp_getattro */
727 0, /* tp_setattro */
728 0, /* tp_as_buffer */
INADA Naoki3070b712017-12-26 02:03:24 +0900729 Py_TPFLAGS_DEFAULT, /* tp_flags */
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300730};
731
732
733typedef PyObject *(*lru_cache_ternaryfunc)(struct lru_cache_object *, PyObject *, PyObject *);
734
735typedef struct lru_cache_object {
736 lru_list_elem root; /* includes PyObject_HEAD */
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300737 lru_cache_ternaryfunc wrapper;
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300738 int typed;
Raymond Hettingerd8080c02019-01-26 03:02:00 -0500739 PyObject *cache;
740 Py_ssize_t hits;
741 PyObject *func;
742 Py_ssize_t maxsize;
743 Py_ssize_t misses;
744 PyObject *cache_info_type;
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300745 PyObject *dict;
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300746} lru_cache_object;
747
748static PyTypeObject lru_cache_type;
749
750static PyObject *
751lru_cache_make_key(PyObject *args, PyObject *kwds, int typed)
752{
Raymond Hettingerdda44682017-01-08 18:04:30 -0800753 PyObject *key, *keyword, *value;
754 Py_ssize_t key_size, pos, key_pos, kwds_size;
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300755
Raymond Hettinger14adbd42019-04-20 07:20:44 -1000756 kwds_size = kwds ? PyDict_GET_SIZE(kwds) : 0;
757
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300758 /* short path, key will match args anyway, which is a tuple */
Raymond Hettinger14adbd42019-04-20 07:20:44 -1000759 if (!typed && !kwds_size) {
Raymond Hettingerd8080c02019-01-26 03:02:00 -0500760 if (PyTuple_GET_SIZE(args) == 1) {
761 key = PyTuple_GET_ITEM(args, 0);
762 if (PyUnicode_CheckExact(key) || PyLong_CheckExact(key)) {
763 /* For common scalar keys, save space by
764 dropping the enclosing args tuple */
765 Py_INCREF(key);
766 return key;
767 }
768 }
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300769 Py_INCREF(args);
770 return args;
771 }
772
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300773 key_size = PyTuple_GET_SIZE(args);
Raymond Hettingerdda44682017-01-08 18:04:30 -0800774 if (kwds_size)
775 key_size += kwds_size * 2 + 1;
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300776 if (typed)
Raymond Hettingerdda44682017-01-08 18:04:30 -0800777 key_size += PyTuple_GET_SIZE(args) + kwds_size;
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300778
779 key = PyTuple_New(key_size);
780 if (key == NULL)
Raymond Hettingerdda44682017-01-08 18:04:30 -0800781 return NULL;
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300782
783 key_pos = 0;
784 for (pos = 0; pos < PyTuple_GET_SIZE(args); ++pos) {
785 PyObject *item = PyTuple_GET_ITEM(args, pos);
786 Py_INCREF(item);
787 PyTuple_SET_ITEM(key, key_pos++, item);
788 }
Raymond Hettingerdda44682017-01-08 18:04:30 -0800789 if (kwds_size) {
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300790 Py_INCREF(kwd_mark);
791 PyTuple_SET_ITEM(key, key_pos++, kwd_mark);
Raymond Hettingerdda44682017-01-08 18:04:30 -0800792 for (pos = 0; PyDict_Next(kwds, &pos, &keyword, &value);) {
793 Py_INCREF(keyword);
794 PyTuple_SET_ITEM(key, key_pos++, keyword);
795 Py_INCREF(value);
796 PyTuple_SET_ITEM(key, key_pos++, value);
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300797 }
Raymond Hettingerdda44682017-01-08 18:04:30 -0800798 assert(key_pos == PyTuple_GET_SIZE(args) + kwds_size * 2 + 1);
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300799 }
800 if (typed) {
801 for (pos = 0; pos < PyTuple_GET_SIZE(args); ++pos) {
802 PyObject *item = (PyObject *)Py_TYPE(PyTuple_GET_ITEM(args, pos));
803 Py_INCREF(item);
804 PyTuple_SET_ITEM(key, key_pos++, item);
805 }
Raymond Hettingerdda44682017-01-08 18:04:30 -0800806 if (kwds_size) {
807 for (pos = 0; PyDict_Next(kwds, &pos, &keyword, &value);) {
808 PyObject *item = (PyObject *)Py_TYPE(value);
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300809 Py_INCREF(item);
810 PyTuple_SET_ITEM(key, key_pos++, item);
811 }
812 }
813 }
814 assert(key_pos == key_size);
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300815 return key;
816}
817
818static PyObject *
819uncached_lru_cache_wrapper(lru_cache_object *self, PyObject *args, PyObject *kwds)
820{
Raymond Hettingerffdf1c32019-01-31 15:03:38 -0800821 PyObject *result;
822
823 self->misses++;
824 result = PyObject_Call(self->func, args, kwds);
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300825 if (!result)
826 return NULL;
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300827 return result;
828}
829
830static PyObject *
831infinite_lru_cache_wrapper(lru_cache_object *self, PyObject *args, PyObject *kwds)
832{
833 PyObject *result;
Serhiy Storchakab9d98d52015-10-02 12:47:11 +0300834 Py_hash_t hash;
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300835 PyObject *key = lru_cache_make_key(args, kwds, self->typed);
836 if (!key)
837 return NULL;
Serhiy Storchakab9d98d52015-10-02 12:47:11 +0300838 hash = PyObject_Hash(key);
Yury Selivanov46a02db2016-11-09 18:55:45 -0500839 if (hash == -1) {
840 Py_DECREF(key);
Serhiy Storchakab9d98d52015-10-02 12:47:11 +0300841 return NULL;
Yury Selivanov46a02db2016-11-09 18:55:45 -0500842 }
Serhiy Storchakab9d98d52015-10-02 12:47:11 +0300843 result = _PyDict_GetItem_KnownHash(self->cache, key, hash);
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300844 if (result) {
845 Py_INCREF(result);
846 self->hits++;
847 Py_DECREF(key);
848 return result;
849 }
850 if (PyErr_Occurred()) {
851 Py_DECREF(key);
852 return NULL;
853 }
Raymond Hettingerffdf1c32019-01-31 15:03:38 -0800854 self->misses++;
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300855 result = PyObject_Call(self->func, args, kwds);
856 if (!result) {
857 Py_DECREF(key);
858 return NULL;
859 }
Serhiy Storchakab9d98d52015-10-02 12:47:11 +0300860 if (_PyDict_SetItem_KnownHash(self->cache, key, result, hash) < 0) {
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300861 Py_DECREF(result);
862 Py_DECREF(key);
863 return NULL;
864 }
865 Py_DECREF(key);
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300866 return result;
867}
868
869static void
Raymond Hettingerd8080c02019-01-26 03:02:00 -0500870lru_cache_extract_link(lru_list_elem *link)
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300871{
Raymond Hettingerd8080c02019-01-26 03:02:00 -0500872 lru_list_elem *link_prev = link->prev;
873 lru_list_elem *link_next = link->next;
874 link_prev->next = link->next;
875 link_next->prev = link->prev;
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300876}
877
878static void
879lru_cache_append_link(lru_cache_object *self, lru_list_elem *link)
880{
881 lru_list_elem *root = &self->root;
882 lru_list_elem *last = root->prev;
883 last->next = root->prev = link;
884 link->prev = last;
885 link->next = root;
886}
887
Raymond Hettingerd8080c02019-01-26 03:02:00 -0500888static void
889lru_cache_prepend_link(lru_cache_object *self, lru_list_elem *link)
890{
891 lru_list_elem *root = &self->root;
892 lru_list_elem *first = root->next;
893 first->prev = root->next = link;
894 link->prev = root;
895 link->next = first;
896}
897
898/* General note on reentrancy:
899
900 There are four dictionary calls in the bounded_lru_cache_wrapper():
901 1) The initial check for a cache match. 2) The post user-function
902 check for a cache match. 3) The deletion of the oldest entry.
903 4) The addition of the newest entry.
904
905 In all four calls, we have a known hash which lets use avoid a call
906 to __hash__(). That leaves only __eq__ as a possible source of a
907 reentrant call.
908
909 The __eq__ method call is always made for a cache hit (dict access #1).
910 Accordingly, we have make sure not modify the cache state prior to
911 this call.
912
913 The __eq__ method call is never made for the deletion (dict access #3)
914 because it is an identity match.
915
916 For the other two accesses (#2 and #4), calls to __eq__ only occur
917 when some other entry happens to have an exactly matching hash (all
918 64-bits). Though rare, this can happen, so we have to make sure to
919 either call it at the top of its code path before any cache
920 state modifications (dict access #2) or be prepared to restore
921 invariants at the end of the code path (dict access #4).
922
923 Another possible source of reentrancy is a decref which can trigger
924 arbitrary code execution. To make the code easier to reason about,
925 the decrefs are deferred to the end of the each possible code path
926 so that we know the cache is a consistent state.
927 */
928
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300929static PyObject *
930bounded_lru_cache_wrapper(lru_cache_object *self, PyObject *args, PyObject *kwds)
931{
932 lru_list_elem *link;
Raymond Hettingerd8080c02019-01-26 03:02:00 -0500933 PyObject *key, *result, *testresult;
Serhiy Storchakab9d98d52015-10-02 12:47:11 +0300934 Py_hash_t hash;
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300935
936 key = lru_cache_make_key(args, kwds, self->typed);
937 if (!key)
938 return NULL;
Serhiy Storchakab9d98d52015-10-02 12:47:11 +0300939 hash = PyObject_Hash(key);
Yury Selivanov46a02db2016-11-09 18:55:45 -0500940 if (hash == -1) {
941 Py_DECREF(key);
Serhiy Storchakab9d98d52015-10-02 12:47:11 +0300942 return NULL;
Yury Selivanov46a02db2016-11-09 18:55:45 -0500943 }
Serhiy Storchakab9d98d52015-10-02 12:47:11 +0300944 link = (lru_list_elem *)_PyDict_GetItem_KnownHash(self->cache, key, hash);
Raymond Hettingerd8080c02019-01-26 03:02:00 -0500945 if (link != NULL) {
946 lru_cache_extract_link(link);
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300947 lru_cache_append_link(self, link);
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300948 result = link->result;
Raymond Hettingerd8080c02019-01-26 03:02:00 -0500949 self->hits++;
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300950 Py_INCREF(result);
951 Py_DECREF(key);
952 return result;
953 }
954 if (PyErr_Occurred()) {
955 Py_DECREF(key);
956 return NULL;
957 }
Raymond Hettingerd8080c02019-01-26 03:02:00 -0500958 self->misses++;
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300959 result = PyObject_Call(self->func, args, kwds);
960 if (!result) {
961 Py_DECREF(key);
962 return NULL;
963 }
Raymond Hettingerd8080c02019-01-26 03:02:00 -0500964 testresult = _PyDict_GetItem_KnownHash(self->cache, key, hash);
965 if (testresult != NULL) {
966 /* Getting here means that this same key was added to the cache
967 during the PyObject_Call(). Since the link update is already
968 done, we need only return the computed result. */
969 Py_DECREF(key);
970 return result;
971 }
972 if (PyErr_Occurred()) {
973 /* This is an unusual case since this same lookup
974 did not previously trigger an error during lookup.
975 Treat it the same as an error in user function
976 and return with the error set. */
977 Py_DECREF(key);
978 Py_DECREF(result);
979 return NULL;
980 }
981 /* This is the normal case. The new key wasn't found before
982 user function call and it is still not there. So we
983 proceed normally and update the cache with the new result. */
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300984
Raymond Hettingerd8080c02019-01-26 03:02:00 -0500985 assert(self->maxsize > 0);
986 if (PyDict_GET_SIZE(self->cache) < self->maxsize ||
987 self->root.next == &self->root)
988 {
989 /* Cache is not full, so put the result in a new link */
INADA Naoki3070b712017-12-26 02:03:24 +0900990 link = (lru_list_elem *)PyObject_New(lru_list_elem,
991 &lru_list_elem_type);
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300992 if (link == NULL) {
993 Py_DECREF(key);
994 Py_DECREF(result);
995 return NULL;
996 }
997
Serhiy Storchakab9d98d52015-10-02 12:47:11 +0300998 link->hash = hash;
Serhiy Storchaka46c56112015-05-24 21:53:49 +0300999 link->key = key;
1000 link->result = result;
Raymond Hettingerd8080c02019-01-26 03:02:00 -05001001 /* What is really needed here is a SetItem variant with a "no clobber"
1002 option. If the __eq__ call triggers a reentrant call that adds
1003 this same key, then this setitem call will update the cache dict
1004 with this new link, leaving the old link as an orphan (i.e. not
1005 having a cache dict entry that refers to it). */
Serhiy Storchakab9d98d52015-10-02 12:47:11 +03001006 if (_PyDict_SetItem_KnownHash(self->cache, key, (PyObject *)link,
1007 hash) < 0) {
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001008 Py_DECREF(link);
1009 return NULL;
1010 }
1011 lru_cache_append_link(self, link);
1012 Py_INCREF(result); /* for return */
Raymond Hettingerd8080c02019-01-26 03:02:00 -05001013 return result;
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001014 }
Raymond Hettingerd8080c02019-01-26 03:02:00 -05001015 /* Since the cache is full, we need to evict an old key and add
1016 a new key. Rather than free the old link and allocate a new
1017 one, we reuse the link for the new key and result and move it
1018 to front of the cache to mark it as recently used.
1019
1020 We try to assure all code paths (including errors) leave all
1021 of the links in place. Either the link is successfully
1022 updated and moved or it is restored to its old position.
1023 However if an unrecoverable error is found, it doesn't
1024 make sense to reinsert the link, so we leave it out
1025 and the cache will no longer register as full.
1026 */
1027 PyObject *oldkey, *oldresult, *popresult;
1028
1029 /* Extract the oldest item. */
1030 assert(self->root.next != &self->root);
1031 link = self->root.next;
1032 lru_cache_extract_link(link);
1033 /* Remove it from the cache.
Raymond Hettinger2dda72a2019-02-08 18:55:02 -08001034 The cache dict holds one reference to the link.
1035 We created one other reference when the link was created.
1036 The linked list only has borrowed references. */
Raymond Hettingerd8080c02019-01-26 03:02:00 -05001037 popresult = _PyDict_Pop_KnownHash(self->cache, link->key,
1038 link->hash, Py_None);
1039 if (popresult == Py_None) {
1040 /* Getting here means that the user function call or another
1041 thread has already removed the old key from the dictionary.
Raymond Hettinger2dda72a2019-02-08 18:55:02 -08001042 This link is now an orphan. Since we don't want to leave the
Raymond Hettingerd8080c02019-01-26 03:02:00 -05001043 cache in an inconsistent state, we don't restore the link. */
1044 Py_DECREF(popresult);
1045 Py_DECREF(link);
1046 Py_DECREF(key);
1047 return result;
1048 }
1049 if (popresult == NULL) {
1050 /* An error arose while trying to remove the oldest key (the one
1051 being evicted) from the cache. We restore the link to its
1052 original position as the oldest link. Then we allow the
1053 error propagate upward; treating it the same as an error
1054 arising in the user function. */
1055 lru_cache_prepend_link(self, link);
1056 Py_DECREF(key);
1057 Py_DECREF(result);
1058 return NULL;
1059 }
1060 /* Keep a reference to the old key and old result to prevent their
1061 ref counts from going to zero during the update. That will
1062 prevent potentially arbitrary object clean-up code (i.e. __del__)
1063 from running while we're still adjusting the links. */
1064 oldkey = link->key;
1065 oldresult = link->result;
1066
1067 link->hash = hash;
1068 link->key = key;
1069 link->result = result;
1070 /* Note: The link is being added to the cache dict without the
1071 prev and next fields set to valid values. We have to wait
1072 for successful insertion in the cache dict before adding the
1073 link to the linked list. Otherwise, the potentially reentrant
Raymond Hettinger2dda72a2019-02-08 18:55:02 -08001074 __eq__ call could cause the then orphan link to be visited. */
Raymond Hettingerd8080c02019-01-26 03:02:00 -05001075 if (_PyDict_SetItem_KnownHash(self->cache, key, (PyObject *)link,
1076 hash) < 0) {
1077 /* Somehow the cache dict update failed. We no longer can
1078 restore the old link. Let the error propagate upward and
1079 leave the cache short one link. */
1080 Py_DECREF(popresult);
1081 Py_DECREF(link);
1082 Py_DECREF(oldkey);
1083 Py_DECREF(oldresult);
1084 return NULL;
1085 }
1086 lru_cache_append_link(self, link);
1087 Py_INCREF(result); /* for return */
1088 Py_DECREF(popresult);
1089 Py_DECREF(oldkey);
1090 Py_DECREF(oldresult);
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001091 return result;
1092}
1093
1094static PyObject *
1095lru_cache_new(PyTypeObject *type, PyObject *args, PyObject *kw)
1096{
Serhiy Storchaka374164c2015-07-25 12:10:21 +03001097 PyObject *func, *maxsize_O, *cache_info_type, *cachedict;
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001098 int typed;
1099 lru_cache_object *obj;
1100 Py_ssize_t maxsize;
1101 PyObject *(*wrapper)(lru_cache_object *, PyObject *, PyObject *);
1102 static char *keywords[] = {"user_function", "maxsize", "typed",
1103 "cache_info_type", NULL};
1104
1105 if (!PyArg_ParseTupleAndKeywords(args, kw, "OOpO:lru_cache", keywords,
1106 &func, &maxsize_O, &typed,
1107 &cache_info_type)) {
1108 return NULL;
1109 }
1110
1111 if (!PyCallable_Check(func)) {
1112 PyErr_SetString(PyExc_TypeError,
1113 "the first argument must be callable");
1114 return NULL;
1115 }
1116
1117 /* select the caching function, and make/inc maxsize_O */
1118 if (maxsize_O == Py_None) {
1119 wrapper = infinite_lru_cache_wrapper;
1120 /* use this only to initialize lru_cache_object attribute maxsize */
1121 maxsize = -1;
1122 } else if (PyIndex_Check(maxsize_O)) {
1123 maxsize = PyNumber_AsSsize_t(maxsize_O, PyExc_OverflowError);
1124 if (maxsize == -1 && PyErr_Occurred())
1125 return NULL;
Raymond Hettingerd8080c02019-01-26 03:02:00 -05001126 if (maxsize < 0) {
1127 maxsize = 0;
1128 }
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001129 if (maxsize == 0)
1130 wrapper = uncached_lru_cache_wrapper;
1131 else
1132 wrapper = bounded_lru_cache_wrapper;
1133 } else {
1134 PyErr_SetString(PyExc_TypeError, "maxsize should be integer or None");
1135 return NULL;
1136 }
1137
Serhiy Storchaka374164c2015-07-25 12:10:21 +03001138 if (!(cachedict = PyDict_New()))
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001139 return NULL;
1140
Serhiy Storchaka374164c2015-07-25 12:10:21 +03001141 obj = (lru_cache_object *)type->tp_alloc(type, 0);
1142 if (obj == NULL) {
1143 Py_DECREF(cachedict);
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001144 return NULL;
1145 }
1146
1147 obj->root.prev = &obj->root;
1148 obj->root.next = &obj->root;
Raymond Hettingerd8080c02019-01-26 03:02:00 -05001149 obj->wrapper = wrapper;
1150 obj->typed = typed;
1151 obj->cache = cachedict;
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001152 Py_INCREF(func);
1153 obj->func = func;
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001154 obj->misses = obj->hits = 0;
Raymond Hettingerd8080c02019-01-26 03:02:00 -05001155 obj->maxsize = maxsize;
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001156 Py_INCREF(cache_info_type);
1157 obj->cache_info_type = cache_info_type;
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001158 return (PyObject *)obj;
1159}
1160
1161static lru_list_elem *
1162lru_cache_unlink_list(lru_cache_object *self)
1163{
1164 lru_list_elem *root = &self->root;
1165 lru_list_elem *link = root->next;
1166 if (link == root)
1167 return NULL;
1168 root->prev->next = NULL;
1169 root->next = root->prev = root;
1170 return link;
1171}
1172
1173static void
1174lru_cache_clear_list(lru_list_elem *link)
1175{
1176 while (link != NULL) {
1177 lru_list_elem *next = link->next;
1178 Py_DECREF(link);
1179 link = next;
1180 }
1181}
1182
1183static void
1184lru_cache_dealloc(lru_cache_object *obj)
1185{
INADA Naokia6296d32017-08-24 14:55:17 +09001186 lru_list_elem *list;
1187 /* bpo-31095: UnTrack is needed before calling any callbacks */
1188 PyObject_GC_UnTrack(obj);
1189
1190 list = lru_cache_unlink_list(obj);
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001191 Py_XDECREF(obj->cache);
Raymond Hettingerd8080c02019-01-26 03:02:00 -05001192 Py_XDECREF(obj->func);
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001193 Py_XDECREF(obj->cache_info_type);
Raymond Hettingerd8080c02019-01-26 03:02:00 -05001194 Py_XDECREF(obj->dict);
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001195 lru_cache_clear_list(list);
1196 Py_TYPE(obj)->tp_free(obj);
1197}
1198
1199static PyObject *
1200lru_cache_call(lru_cache_object *self, PyObject *args, PyObject *kwds)
1201{
1202 return self->wrapper(self, args, kwds);
1203}
1204
1205static PyObject *
Serhiy Storchakae7070f02015-06-08 11:19:24 +03001206lru_cache_descr_get(PyObject *self, PyObject *obj, PyObject *type)
1207{
1208 if (obj == Py_None || obj == NULL) {
1209 Py_INCREF(self);
1210 return self;
1211 }
1212 return PyMethod_New(self, obj);
1213}
1214
1215static PyObject *
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001216lru_cache_cache_info(lru_cache_object *self, PyObject *unused)
1217{
Raymond Hettingerd8080c02019-01-26 03:02:00 -05001218 if (self->maxsize == -1) {
1219 return PyObject_CallFunction(self->cache_info_type, "nnOn",
1220 self->hits, self->misses, Py_None,
1221 PyDict_GET_SIZE(self->cache));
1222 }
1223 return PyObject_CallFunction(self->cache_info_type, "nnnn",
1224 self->hits, self->misses, self->maxsize,
Serhiy Storchaka5ab81d72016-12-16 16:18:57 +02001225 PyDict_GET_SIZE(self->cache));
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001226}
1227
1228static PyObject *
1229lru_cache_cache_clear(lru_cache_object *self, PyObject *unused)
1230{
1231 lru_list_elem *list = lru_cache_unlink_list(self);
1232 self->hits = self->misses = 0;
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001233 PyDict_Clear(self->cache);
1234 lru_cache_clear_list(list);
1235 Py_RETURN_NONE;
1236}
1237
Serhiy Storchaka45120f22015-10-24 09:49:56 +03001238static PyObject *
1239lru_cache_reduce(PyObject *self, PyObject *unused)
1240{
1241 return PyObject_GetAttrString(self, "__qualname__");
1242}
1243
Serhiy Storchakae4d65e32015-12-28 23:58:07 +02001244static PyObject *
1245lru_cache_copy(PyObject *self, PyObject *unused)
1246{
1247 Py_INCREF(self);
1248 return self;
1249}
1250
1251static PyObject *
1252lru_cache_deepcopy(PyObject *self, PyObject *unused)
1253{
1254 Py_INCREF(self);
1255 return self;
1256}
1257
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001258static int
1259lru_cache_tp_traverse(lru_cache_object *self, visitproc visit, void *arg)
1260{
1261 lru_list_elem *link = self->root.next;
1262 while (link != &self->root) {
1263 lru_list_elem *next = link->next;
INADA Naoki3070b712017-12-26 02:03:24 +09001264 Py_VISIT(link->key);
1265 Py_VISIT(link->result);
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001266 link = next;
1267 }
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001268 Py_VISIT(self->func);
1269 Py_VISIT(self->cache);
1270 Py_VISIT(self->cache_info_type);
1271 Py_VISIT(self->dict);
1272 return 0;
1273}
1274
1275static int
1276lru_cache_tp_clear(lru_cache_object *self)
1277{
1278 lru_list_elem *list = lru_cache_unlink_list(self);
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001279 Py_CLEAR(self->func);
1280 Py_CLEAR(self->cache);
1281 Py_CLEAR(self->cache_info_type);
1282 Py_CLEAR(self->dict);
1283 lru_cache_clear_list(list);
1284 return 0;
1285}
1286
1287
1288PyDoc_STRVAR(lru_cache_doc,
1289"Create a cached callable that wraps another function.\n\
1290\n\
1291user_function: the function being cached\n\
1292\n\
1293maxsize: 0 for no caching\n\
1294 None for unlimited cache size\n\
1295 n for a bounded cache\n\
1296\n\
1297typed: False cache f(3) and f(3.0) as identical calls\n\
1298 True cache f(3) and f(3.0) as distinct calls\n\
1299\n\
1300cache_info_type: namedtuple class with the fields:\n\
1301 hits misses currsize maxsize\n"
1302);
1303
1304static PyMethodDef lru_cache_methods[] = {
1305 {"cache_info", (PyCFunction)lru_cache_cache_info, METH_NOARGS},
1306 {"cache_clear", (PyCFunction)lru_cache_cache_clear, METH_NOARGS},
Serhiy Storchaka45120f22015-10-24 09:49:56 +03001307 {"__reduce__", (PyCFunction)lru_cache_reduce, METH_NOARGS},
Serhiy Storchakae4d65e32015-12-28 23:58:07 +02001308 {"__copy__", (PyCFunction)lru_cache_copy, METH_VARARGS},
1309 {"__deepcopy__", (PyCFunction)lru_cache_deepcopy, METH_VARARGS},
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001310 {NULL}
1311};
1312
1313static PyGetSetDef lru_cache_getsetlist[] = {
1314 {"__dict__", PyObject_GenericGetDict, PyObject_GenericSetDict},
1315 {NULL}
1316};
1317
1318static PyTypeObject lru_cache_type = {
1319 PyVarObject_HEAD_INIT(NULL, 0)
1320 "functools._lru_cache_wrapper", /* tp_name */
1321 sizeof(lru_cache_object), /* tp_basicsize */
1322 0, /* tp_itemsize */
1323 /* methods */
1324 (destructor)lru_cache_dealloc, /* tp_dealloc */
Jeroen Demeyer530f5062019-05-31 04:13:39 +02001325 0, /* tp_vectorcall_offset */
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001326 0, /* tp_getattr */
1327 0, /* tp_setattr */
Jeroen Demeyer530f5062019-05-31 04:13:39 +02001328 0, /* tp_as_async */
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001329 0, /* tp_repr */
1330 0, /* tp_as_number */
1331 0, /* tp_as_sequence */
1332 0, /* tp_as_mapping */
1333 0, /* tp_hash */
1334 (ternaryfunc)lru_cache_call, /* tp_call */
1335 0, /* tp_str */
1336 0, /* tp_getattro */
1337 0, /* tp_setattro */
1338 0, /* tp_as_buffer */
Jeroen Demeyereb65e242019-05-28 14:42:53 +02001339 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE |
1340 Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_METHOD_DESCRIPTOR,
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001341 /* tp_flags */
1342 lru_cache_doc, /* tp_doc */
1343 (traverseproc)lru_cache_tp_traverse,/* tp_traverse */
1344 (inquiry)lru_cache_tp_clear, /* tp_clear */
1345 0, /* tp_richcompare */
1346 0, /* tp_weaklistoffset */
1347 0, /* tp_iter */
1348 0, /* tp_iternext */
1349 lru_cache_methods, /* tp_methods */
1350 0, /* tp_members */
1351 lru_cache_getsetlist, /* tp_getset */
1352 0, /* tp_base */
1353 0, /* tp_dict */
Serhiy Storchakae7070f02015-06-08 11:19:24 +03001354 lru_cache_descr_get, /* tp_descr_get */
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001355 0, /* tp_descr_set */
1356 offsetof(lru_cache_object, dict), /* tp_dictoffset */
1357 0, /* tp_init */
1358 0, /* tp_alloc */
1359 lru_cache_new, /* tp_new */
1360};
1361
Raymond Hettinger9c323f82005-02-28 19:39:44 +00001362/* module level code ********************************************************/
1363
1364PyDoc_STRVAR(module_doc,
Thomas Wouters4d70c3d2006-06-08 14:42:34 +00001365"Tools that operate on functions.");
Raymond Hettinger9c323f82005-02-28 19:39:44 +00001366
1367static PyMethodDef module_methods[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001368 {"reduce", functools_reduce, METH_VARARGS, functools_reduce_doc},
Serhiy Storchaka62be7422018-11-27 13:27:31 +02001369 {"cmp_to_key", (PyCFunction)(void(*)(void))functools_cmp_to_key,
Victor Stinner446c8d52011-04-05 12:21:35 +02001370 METH_VARARGS | METH_KEYWORDS, functools_cmp_to_key_doc},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001371 {NULL, NULL} /* sentinel */
Raymond Hettinger9c323f82005-02-28 19:39:44 +00001372};
1373
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001374static void
1375module_free(void *m)
1376{
1377 Py_CLEAR(kwd_mark);
1378}
Martin v. Löwis1a214512008-06-11 05:26:20 +00001379
1380static struct PyModuleDef _functoolsmodule = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001381 PyModuleDef_HEAD_INIT,
1382 "_functools",
1383 module_doc,
1384 -1,
1385 module_methods,
1386 NULL,
1387 NULL,
1388 NULL,
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001389 module_free,
Martin v. Löwis1a214512008-06-11 05:26:20 +00001390};
1391
Raymond Hettinger9c323f82005-02-28 19:39:44 +00001392PyMODINIT_FUNC
Martin v. Löwis1a214512008-06-11 05:26:20 +00001393PyInit__functools(void)
Raymond Hettinger9c323f82005-02-28 19:39:44 +00001394{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001395 int i;
1396 PyObject *m;
Serhiy Storchaka4ab46d72017-09-17 21:11:04 +03001397 const char *name;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001398 PyTypeObject *typelist[] = {
1399 &partial_type,
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001400 &lru_cache_type,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001401 NULL
1402 };
Raymond Hettinger9c323f82005-02-28 19:39:44 +00001403
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001404 m = PyModule_Create(&_functoolsmodule);
1405 if (m == NULL)
1406 return NULL;
Raymond Hettinger9c323f82005-02-28 19:39:44 +00001407
Victor Stinnera5ed5f02016-12-06 18:45:50 +01001408 kwd_mark = _PyObject_CallNoArg((PyObject *)&PyBaseObject_Type);
Serhiy Storchaka46c56112015-05-24 21:53:49 +03001409 if (!kwd_mark) {
1410 Py_DECREF(m);
1411 return NULL;
1412 }
1413
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001414 for (i=0 ; typelist[i] != NULL ; i++) {
1415 if (PyType_Ready(typelist[i]) < 0) {
1416 Py_DECREF(m);
1417 return NULL;
1418 }
Serhiy Storchaka4ab46d72017-09-17 21:11:04 +03001419 name = _PyType_Name(typelist[i]);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001420 Py_INCREF(typelist[i]);
Serhiy Storchaka4ab46d72017-09-17 21:11:04 +03001421 PyModule_AddObject(m, name, (PyObject *)typelist[i]);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001422 }
1423 return m;
Raymond Hettinger9c323f82005-02-28 19:39:44 +00001424}