1#include "Python.h" 2#include "pycore_call.h" // _PyObject_CallNoArgs() 3#include "pycore_long.h" // _PyLong_GetZero() 4#include "pycore_moduleobject.h" // _PyModule_GetState() 5#include "pycore_object.h" // _PyObject_GC_TRACK 6#include "pycore_pystate.h" // _PyThreadState_GET() 7#include "pycore_tuple.h" // _PyTuple_ITEMS() 8#include "structmember.h" // PyMemberDef 9 10/* _functools module written and maintained 11 by Hye-Shik Chang <perky@FreeBSD.org> 12 with adaptations by Raymond Hettinger <python@rcn.com> 13 Copyright (c) 2004, 2005, 2006 Python Software Foundation. 14 All rights reserved. 15*/ 16 17typedef struct _functools_state { 18 /* this object is used delimit args and keywords in the cache keys */ 19 PyObject *kwd_mark; 20 PyTypeObject *partial_type; 21 PyTypeObject *keyobject_type; 22 PyTypeObject *lru_list_elem_type; 23} _functools_state; 24 25static inline _functools_state * 26get_functools_state(PyObject *module) 27{ 28 void *state = _PyModule_GetState(module); 29 assert(state != NULL); 30 return (_functools_state *)state; 31} 32 33 34/* partial object **********************************************************/ 35 36typedef struct { 37 PyObject_HEAD 38 PyObject *fn; 39 PyObject *args; 40 PyObject *kw; 41 PyObject *dict; /* __dict__ */ 42 PyObject *weakreflist; /* List of weak references */ 43 vectorcallfunc vectorcall; 44} partialobject; 45 46static void partial_setvectorcall(partialobject *pto); 47static struct PyModuleDef _functools_module; 48static PyObject * 49partial_call(partialobject *pto, PyObject *args, PyObject *kwargs); 50 51static inline _functools_state * 52get_functools_state_by_type(PyTypeObject *type) 53{ 54 PyObject *module = PyType_GetModuleByDef(type, &_functools_module); 55 if (module == NULL) { 56 return NULL; 57 } 58 return get_functools_state(module); 59} 60 61static PyObject * 62partial_new(PyTypeObject *type, PyObject *args, PyObject *kw) 63{ 64 PyObject *func, *pargs, *nargs, *pkw; 65 partialobject *pto; 66 67 if (PyTuple_GET_SIZE(args) < 1) { 68 PyErr_SetString(PyExc_TypeError, 69 "type 'partial' takes at least one argument"); 70 return NULL; 71 } 72 73 pargs = pkw = NULL; 74 func = PyTuple_GET_ITEM(args, 0); 75 if (Py_TYPE(func)->tp_call == (ternaryfunc)partial_call) { 76 // The type of "func" might not be exactly the same type object 77 // as "type", but if it is called using partial_call, it must have the 78 // same memory layout (fn, args and kw members). 79 // We can use its underlying function directly and merge the arguments. 80 partialobject *part = (partialobject *)func; 81 if (part->dict == NULL) { 82 pargs = part->args; 83 pkw = part->kw; 84 func = part->fn; 85 assert(PyTuple_Check(pargs)); 86 assert(PyDict_Check(pkw)); 87 } 88 } 89 if (!PyCallable_Check(func)) { 90 PyErr_SetString(PyExc_TypeError, 91 "the first argument must be callable"); 92 return NULL; 93 } 94 95 /* create partialobject structure */ 96 pto = (partialobject *)type->tp_alloc(type, 0); 97 if (pto == NULL) 98 return NULL; 99 100 pto->fn = func; 101 Py_INCREF(func); 102 103 nargs = PyTuple_GetSlice(args, 1, PY_SSIZE_T_MAX); 104 if (nargs == NULL) { 105 Py_DECREF(pto); 106 return NULL; 107 } 108 if (pargs == NULL) { 109 pto->args = nargs; 110 } 111 else { 112 pto->args = PySequence_Concat(pargs, nargs); 113 Py_DECREF(nargs); 114 if (pto->args == NULL) { 115 Py_DECREF(pto); 116 return NULL; 117 } 118 assert(PyTuple_Check(pto->args)); 119 } 120 121 if (pkw == NULL || PyDict_GET_SIZE(pkw) == 0) { 122 if (kw == NULL) { 123 pto->kw = PyDict_New(); 124 } 125 else if (Py_REFCNT(kw) == 1) { 126 Py_INCREF(kw); 127 pto->kw = kw; 128 } 129 else { 130 pto->kw = PyDict_Copy(kw); 131 } 132 } 133 else { 134 pto->kw = PyDict_Copy(pkw); 135 if (kw != NULL && pto->kw != NULL) { 136 if (PyDict_Merge(pto->kw, kw, 1) != 0) { 137 Py_DECREF(pto); 138 return NULL; 139 } 140 } 141 } 142 if (pto->kw == NULL) { 143 Py_DECREF(pto); 144 return NULL; 145 } 146 147 partial_setvectorcall(pto); 148 return (PyObject *)pto; 149} 150 151static int 152partial_clear(partialobject *pto) 153{ 154 Py_CLEAR(pto->fn); 155 Py_CLEAR(pto->args); 156 Py_CLEAR(pto->kw); 157 Py_CLEAR(pto->dict); 158 return 0; 159} 160 161static int 162partial_traverse(partialobject *pto, visitproc visit, void *arg) 163{ 164 Py_VISIT(Py_TYPE(pto)); 165 Py_VISIT(pto->fn); 166 Py_VISIT(pto->args); 167 Py_VISIT(pto->kw); 168 Py_VISIT(pto->dict); 169 return 0; 170} 171 172static void 173partial_dealloc(partialobject *pto) 174{ 175 PyTypeObject *tp = Py_TYPE(pto); 176 /* bpo-31095: UnTrack is needed before calling any callbacks */ 177 PyObject_GC_UnTrack(pto); 178 if (pto->weakreflist != NULL) { 179 PyObject_ClearWeakRefs((PyObject *) pto); 180 } 181 (void)partial_clear(pto); 182 tp->tp_free(pto); 183 Py_DECREF(tp); 184} 185 186 187/* Merging keyword arguments using the vectorcall convention is messy, so 188 * if we would need to do that, we stop using vectorcall and fall back 189 * to using partial_call() instead. */ 190Py_NO_INLINE static PyObject * 191partial_vectorcall_fallback(PyThreadState *tstate, partialobject *pto, 192 PyObject *const *args, size_t nargsf, 193 PyObject *kwnames) 194{ 195 pto->vectorcall = NULL; 196 Py_ssize_t nargs = PyVectorcall_NARGS(nargsf); 197 return _PyObject_MakeTpCall(tstate, (PyObject *)pto, 198 args, nargs, kwnames); 199} 200 201static PyObject * 202partial_vectorcall(partialobject *pto, PyObject *const *args, 203 size_t nargsf, PyObject *kwnames) 204{ 205 PyThreadState *tstate = _PyThreadState_GET(); 206 207 /* pto->kw is mutable, so need to check every time */ 208 if (PyDict_GET_SIZE(pto->kw)) { 209 return partial_vectorcall_fallback(tstate, pto, args, nargsf, kwnames); 210 } 211 212 Py_ssize_t nargs = PyVectorcall_NARGS(nargsf); 213 Py_ssize_t nargs_total = nargs; 214 if (kwnames != NULL) { 215 nargs_total += PyTuple_GET_SIZE(kwnames); 216 } 217 218 PyObject **pto_args = _PyTuple_ITEMS(pto->args); 219 Py_ssize_t pto_nargs = PyTuple_GET_SIZE(pto->args); 220 221 /* Fast path if we're called without arguments */ 222 if (nargs_total == 0) { 223 return _PyObject_VectorcallTstate(tstate, pto->fn, 224 pto_args, pto_nargs, NULL); 225 } 226 227 /* Fast path using PY_VECTORCALL_ARGUMENTS_OFFSET to prepend a single 228 * positional argument */ 229 if (pto_nargs == 1 && (nargsf & PY_VECTORCALL_ARGUMENTS_OFFSET)) { 230 PyObject **newargs = (PyObject **)args - 1; 231 PyObject *tmp = newargs[0]; 232 newargs[0] = pto_args[0]; 233 PyObject *ret = _PyObject_VectorcallTstate(tstate, pto->fn, 234 newargs, nargs + 1, kwnames); 235 newargs[0] = tmp; 236 return ret; 237 } 238 239 Py_ssize_t newnargs_total = pto_nargs + nargs_total; 240 241 PyObject *small_stack[_PY_FASTCALL_SMALL_STACK]; 242 PyObject *ret; 243 PyObject **stack; 244 245 if (newnargs_total <= (Py_ssize_t)Py_ARRAY_LENGTH(small_stack)) { 246 stack = small_stack; 247 } 248 else { 249 stack = PyMem_Malloc(newnargs_total * sizeof(PyObject *)); 250 if (stack == NULL) { 251 PyErr_NoMemory(); 252 return NULL; 253 } 254 } 255 256 /* Copy to new stack, using borrowed references */ 257 memcpy(stack, pto_args, pto_nargs * sizeof(PyObject*)); 258 memcpy(stack + pto_nargs, args, nargs_total * sizeof(PyObject*)); 259 260 ret = _PyObject_VectorcallTstate(tstate, pto->fn, 261 stack, pto_nargs + nargs, kwnames); 262 if (stack != small_stack) { 263 PyMem_Free(stack); 264 } 265 return ret; 266} 267 268/* Set pto->vectorcall depending on the parameters of the partial object */ 269static void 270partial_setvectorcall(partialobject *pto) 271{ 272 if (_PyVectorcall_Function(pto->fn) == NULL) { 273 /* Don't use vectorcall if the underlying function doesn't support it */ 274 pto->vectorcall = NULL; 275 } 276 /* We could have a special case if there are no arguments, 277 * but that is unlikely (why use partial without arguments?), 278 * so we don't optimize that */ 279 else { 280 pto->vectorcall = (vectorcallfunc)partial_vectorcall; 281 } 282} 283 284 285static PyObject * 286partial_call(partialobject *pto, PyObject *args, PyObject *kwargs) 287{ 288 assert(PyCallable_Check(pto->fn)); 289 assert(PyTuple_Check(pto->args)); 290 assert(PyDict_Check(pto->kw)); 291 292 /* Merge keywords */ 293 PyObject *kwargs2; 294 if (PyDict_GET_SIZE(pto->kw) == 0) { 295 /* kwargs can be NULL */ 296 kwargs2 = kwargs; 297 Py_XINCREF(kwargs2); 298 } 299 else { 300 /* bpo-27840, bpo-29318: dictionary of keyword parameters must be 301 copied, because a function using "**kwargs" can modify the 302 dictionary. */ 303 kwargs2 = PyDict_Copy(pto->kw); 304 if (kwargs2 == NULL) { 305 return NULL; 306 } 307 308 if (kwargs != NULL) { 309 if (PyDict_Merge(kwargs2, kwargs, 1) != 0) { 310 Py_DECREF(kwargs2); 311 return NULL; 312 } 313 } 314 } 315 316 /* Merge positional arguments */ 317 /* Note: tupleconcat() is optimized for empty tuples */ 318 PyObject *args2 = PySequence_Concat(pto->args, args); 319 if (args2 == NULL) { 320 Py_XDECREF(kwargs2); 321 return NULL; 322 } 323 324 PyObject *res = PyObject_Call(pto->fn, args2, kwargs2); 325 Py_DECREF(args2); 326 Py_XDECREF(kwargs2); 327 return res; 328} 329 330PyDoc_STRVAR(partial_doc, 331"partial(func, *args, **keywords) - new function with partial application\n\ 332 of the given arguments and keywords.\n"); 333 334#define OFF(x) offsetof(partialobject, x) 335static PyMemberDef partial_memberlist[] = { 336 {"func", T_OBJECT, OFF(fn), READONLY, 337 "function object to use in future partial calls"}, 338 {"args", T_OBJECT, OFF(args), READONLY, 339 "tuple of arguments to future partial calls"}, 340 {"keywords", T_OBJECT, OFF(kw), READONLY, 341 "dictionary of keyword arguments to future partial calls"}, 342 {"__weaklistoffset__", T_PYSSIZET, 343 offsetof(partialobject, weakreflist), READONLY}, 344 {"__dictoffset__", T_PYSSIZET, 345 offsetof(partialobject, dict), READONLY}, 346 {"__vectorcalloffset__", T_PYSSIZET, 347 offsetof(partialobject, vectorcall), READONLY}, 348 {NULL} /* Sentinel */ 349}; 350 351static PyGetSetDef partial_getsetlist[] = { 352 {"__dict__", PyObject_GenericGetDict, PyObject_GenericSetDict}, 353 {NULL} /* Sentinel */ 354}; 355 356static PyObject * 357partial_repr(partialobject *pto) 358{ 359 PyObject *result = NULL; 360 PyObject *arglist; 361 Py_ssize_t i, n; 362 PyObject *key, *value; 363 int status; 364 365 status = Py_ReprEnter((PyObject *)pto); 366 if (status != 0) { 367 if (status < 0) 368 return NULL; 369 return PyUnicode_FromString("..."); 370 } 371 372 arglist = PyUnicode_FromString(""); 373 if (arglist == NULL) 374 goto done; 375 /* Pack positional arguments */ 376 assert (PyTuple_Check(pto->args)); 377 n = PyTuple_GET_SIZE(pto->args); 378 for (i = 0; i < n; i++) { 379 Py_SETREF(arglist, PyUnicode_FromFormat("%U, %R", arglist, 380 PyTuple_GET_ITEM(pto->args, i))); 381 if (arglist == NULL) 382 goto done; 383 } 384 /* Pack keyword arguments */ 385 assert (PyDict_Check(pto->kw)); 386 for (i = 0; PyDict_Next(pto->kw, &i, &key, &value);) { 387 /* Prevent key.__str__ from deleting the value. */ 388 Py_INCREF(value); 389 Py_SETREF(arglist, PyUnicode_FromFormat("%U, %S=%R", arglist, 390 key, value)); 391 Py_DECREF(value); 392 if (arglist == NULL) 393 goto done; 394 } 395 result = PyUnicode_FromFormat("%s(%R%U)", Py_TYPE(pto)->tp_name, 396 pto->fn, arglist); 397 Py_DECREF(arglist); 398 399 done: 400 Py_ReprLeave((PyObject *)pto); 401 return result; 402} 403 404/* Pickle strategy: 405 __reduce__ by itself doesn't support getting kwargs in the unpickle 406 operation so we define a __setstate__ that replaces all the information 407 about the partial. If we only replaced part of it someone would use 408 it as a hook to do strange things. 409 */ 410 411static PyObject * 412partial_reduce(partialobject *pto, PyObject *unused) 413{ 414 return Py_BuildValue("O(O)(OOOO)", Py_TYPE(pto), pto->fn, pto->fn, 415 pto->args, pto->kw, 416 pto->dict ? pto->dict : Py_None); 417} 418 419static PyObject * 420partial_setstate(partialobject *pto, PyObject *state) 421{ 422 PyObject *fn, *fnargs, *kw, *dict; 423 424 if (!PyTuple_Check(state) || 425 !PyArg_ParseTuple(state, "OOOO", &fn, &fnargs, &kw, &dict) || 426 !PyCallable_Check(fn) || 427 !PyTuple_Check(fnargs) || 428 (kw != Py_None && !PyDict_Check(kw))) 429 { 430 PyErr_SetString(PyExc_TypeError, "invalid partial state"); 431 return NULL; 432 } 433 434 if(!PyTuple_CheckExact(fnargs)) 435 fnargs = PySequence_Tuple(fnargs); 436 else 437 Py_INCREF(fnargs); 438 if (fnargs == NULL) 439 return NULL; 440 441 if (kw == Py_None) 442 kw = PyDict_New(); 443 else if(!PyDict_CheckExact(kw)) 444 kw = PyDict_Copy(kw); 445 else 446 Py_INCREF(kw); 447 if (kw == NULL) { 448 Py_DECREF(fnargs); 449 return NULL; 450 } 451 452 if (dict == Py_None) 453 dict = NULL; 454 else 455 Py_INCREF(dict); 456 457 Py_INCREF(fn); 458 Py_SETREF(pto->fn, fn); 459 Py_SETREF(pto->args, fnargs); 460 Py_SETREF(pto->kw, kw); 461 Py_XSETREF(pto->dict, dict); 462 partial_setvectorcall(pto); 463 Py_RETURN_NONE; 464} 465 466static PyMethodDef partial_methods[] = { 467 {"__reduce__", (PyCFunction)partial_reduce, METH_NOARGS}, 468 {"__setstate__", (PyCFunction)partial_setstate, METH_O}, 469 {"__class_getitem__", Py_GenericAlias, 470 METH_O|METH_CLASS, PyDoc_STR("See PEP 585")}, 471 {NULL, NULL} /* sentinel */ 472}; 473 474static PyType_Slot partial_type_slots[] = { 475 {Py_tp_dealloc, partial_dealloc}, 476 {Py_tp_repr, partial_repr}, 477 {Py_tp_call, partial_call}, 478 {Py_tp_getattro, PyObject_GenericGetAttr}, 479 {Py_tp_setattro, PyObject_GenericSetAttr}, 480 {Py_tp_doc, (void *)partial_doc}, 481 {Py_tp_traverse, partial_traverse}, 482 {Py_tp_clear, partial_clear}, 483 {Py_tp_methods, partial_methods}, 484 {Py_tp_members, partial_memberlist}, 485 {Py_tp_getset, partial_getsetlist}, 486 {Py_tp_new, partial_new}, 487 {Py_tp_free, PyObject_GC_Del}, 488 {0, 0} 489}; 490 491static PyType_Spec partial_type_spec = { 492 .name = "functools.partial", 493 .basicsize = sizeof(partialobject), 494 .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | 495 Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_VECTORCALL | 496 Py_TPFLAGS_IMMUTABLETYPE, 497 .slots = partial_type_slots 498}; 499 500 501/* cmp_to_key ***************************************************************/ 502 503typedef struct { 504 PyObject_HEAD 505 PyObject *cmp; 506 PyObject *object; 507} keyobject; 508 509static int 510keyobject_clear(keyobject *ko) 511{ 512 Py_CLEAR(ko->cmp); 513 Py_CLEAR(ko->object); 514 return 0; 515} 516 517static void 518keyobject_dealloc(keyobject *ko) 519{ 520 PyTypeObject *tp = Py_TYPE(ko); 521 PyObject_GC_UnTrack(ko); 522 (void)keyobject_clear(ko); 523 tp->tp_free(ko); 524 Py_DECREF(tp); 525} 526 527static int 528keyobject_traverse(keyobject *ko, visitproc visit, void *arg) 529{ 530 Py_VISIT(Py_TYPE(ko)); 531 Py_VISIT(ko->cmp); 532 Py_VISIT(ko->object); 533 return 0; 534} 535 536static PyMemberDef keyobject_members[] = { 537 {"obj", T_OBJECT, 538 offsetof(keyobject, object), 0, 539 PyDoc_STR("Value wrapped by a key function.")}, 540 {NULL} 541}; 542 543static PyObject * 544keyobject_call(keyobject *ko, PyObject *args, PyObject *kwds); 545 546static PyObject * 547keyobject_richcompare(PyObject *ko, PyObject *other, int op); 548 549static PyType_Slot keyobject_type_slots[] = { 550 {Py_tp_dealloc, keyobject_dealloc}, 551 {Py_tp_call, keyobject_call}, 552 {Py_tp_getattro, PyObject_GenericGetAttr}, 553 {Py_tp_traverse, keyobject_traverse}, 554 {Py_tp_clear, keyobject_clear}, 555 {Py_tp_richcompare, keyobject_richcompare}, 556 {Py_tp_members, keyobject_members}, 557 {0, 0} 558}; 559 560static PyType_Spec keyobject_type_spec = { 561 .name = "functools.KeyWrapper", 562 .basicsize = sizeof(keyobject), 563 .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION | 564 Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_IMMUTABLETYPE), 565 .slots = keyobject_type_slots 566}; 567 568static PyObject * 569keyobject_call(keyobject *ko, PyObject *args, PyObject *kwds) 570{ 571 PyObject *object; 572 keyobject *result; 573 static char *kwargs[] = {"obj", NULL}; 574 575 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:K", kwargs, &object)) 576 return NULL; 577 578 result = PyObject_GC_New(keyobject, Py_TYPE(ko)); 579 if (result == NULL) { 580 return NULL; 581 } 582 Py_INCREF(ko->cmp); 583 result->cmp = ko->cmp; 584 Py_INCREF(object); 585 result->object = object; 586 PyObject_GC_Track(result); 587 return (PyObject *)result; 588} 589 590static PyObject * 591keyobject_richcompare(PyObject *ko, PyObject *other, int op) 592{ 593 PyObject *res; 594 PyObject *x; 595 PyObject *y; 596 PyObject *compare; 597 PyObject *answer; 598 PyObject* stack[2]; 599 600 if (!Py_IS_TYPE(other, Py_TYPE(ko))) { 601 PyErr_Format(PyExc_TypeError, "other argument must be K instance"); 602 return NULL; 603 } 604 compare = ((keyobject *) ko)->cmp; 605 assert(compare != NULL); 606 x = ((keyobject *) ko)->object; 607 y = ((keyobject *) other)->object; 608 if (!x || !y){ 609 PyErr_Format(PyExc_AttributeError, "object"); 610 return NULL; 611 } 612 613 /* Call the user's comparison function and translate the 3-way 614 * result into true or false (or error). 615 */ 616 stack[0] = x; 617 stack[1] = y; 618 res = _PyObject_FastCall(compare, stack, 2); 619 if (res == NULL) { 620 return NULL; 621 } 622 623 answer = PyObject_RichCompare(res, _PyLong_GetZero(), op); 624 Py_DECREF(res); 625 return answer; 626} 627 628static PyObject * 629functools_cmp_to_key(PyObject *self, PyObject *args, PyObject *kwds) 630{ 631 PyObject *cmp; 632 static char *kwargs[] = {"mycmp", NULL}; 633 keyobject *object; 634 _functools_state *state; 635 636 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:cmp_to_key", kwargs, &cmp)) 637 return NULL; 638 639 state = get_functools_state(self); 640 object = PyObject_GC_New(keyobject, state->keyobject_type); 641 if (!object) 642 return NULL; 643 Py_INCREF(cmp); 644 object->cmp = cmp; 645 object->object = NULL; 646 PyObject_GC_Track(object); 647 return (PyObject *)object; 648} 649 650PyDoc_STRVAR(functools_cmp_to_key_doc, 651"Convert a cmp= function into a key= function."); 652 653/* reduce (used to be a builtin) ********************************************/ 654 655static PyObject * 656functools_reduce(PyObject *self, PyObject *args) 657{ 658 PyObject *seq, *func, *result = NULL, *it; 659 660 if (!PyArg_UnpackTuple(args, "reduce", 2, 3, &func, &seq, &result)) 661 return NULL; 662 if (result != NULL) 663 Py_INCREF(result); 664 665 it = PyObject_GetIter(seq); 666 if (it == NULL) { 667 if (PyErr_ExceptionMatches(PyExc_TypeError)) 668 PyErr_SetString(PyExc_TypeError, 669 "reduce() arg 2 must support iteration"); 670 Py_XDECREF(result); 671 return NULL; 672 } 673 674 if ((args = PyTuple_New(2)) == NULL) 675 goto Fail; 676 677 for (;;) { 678 PyObject *op2; 679 680 if (Py_REFCNT(args) > 1) { 681 Py_DECREF(args); 682 if ((args = PyTuple_New(2)) == NULL) 683 goto Fail; 684 } 685 686 op2 = PyIter_Next(it); 687 if (op2 == NULL) { 688 if (PyErr_Occurred()) 689 goto Fail; 690 break; 691 } 692 693 if (result == NULL) 694 result = op2; 695 else { 696 /* Update the args tuple in-place */ 697 assert(Py_REFCNT(args) == 1); 698 Py_XSETREF(_PyTuple_ITEMS(args)[0], result); 699 Py_XSETREF(_PyTuple_ITEMS(args)[1], op2); 700 if ((result = PyObject_Call(func, args, NULL)) == NULL) { 701 goto Fail; 702 } 703 // bpo-42536: The GC may have untracked this args tuple. Since we're 704 // recycling it, make sure it's tracked again: 705 if (!_PyObject_GC_IS_TRACKED(args)) { 706 _PyObject_GC_TRACK(args); 707 } 708 } 709 } 710 711 Py_DECREF(args); 712 713 if (result == NULL) 714 PyErr_SetString(PyExc_TypeError, 715 "reduce() of empty iterable with no initial value"); 716 717 Py_DECREF(it); 718 return result; 719 720Fail: 721 Py_XDECREF(args); 722 Py_XDECREF(result); 723 Py_DECREF(it); 724 return NULL; 725} 726 727PyDoc_STRVAR(functools_reduce_doc, 728"reduce(function, iterable[, initial]) -> value\n\ 729\n\ 730Apply a function of two arguments cumulatively to the items of a sequence\n\ 731or iterable, from left to right, so as to reduce the iterable to a single\n\ 732value. For example, reduce(lambda x, y: x+y, [1, 2, 3, 4, 5]) calculates\n\ 733((((1+2)+3)+4)+5). If initial is present, it is placed before the items\n\ 734of the iterable in the calculation, and serves as a default when the\n\ 735iterable is empty."); 736 737/* lru_cache object **********************************************************/ 738 739/* There are four principal algorithmic differences from the pure python version: 740 741 1). The C version relies on the GIL instead of having its own reentrant lock. 742 743 2). The prev/next link fields use borrowed references. 744 745 3). For a full cache, the pure python version rotates the location of the 746 root entry so that it never has to move individual links and it can 747 limit updates to just the key and result fields. However, in the C 748 version, links are temporarily removed while the cache dict updates are 749 occurring. Afterwards, they are appended or prepended back into the 750 doubly-linked lists. 751 752 4) In the Python version, the _HashSeq class is used to prevent __hash__ 753 from being called more than once. In the C version, the "known hash" 754 variants of dictionary calls as used to the same effect. 755 756*/ 757 758struct lru_list_elem; 759struct lru_cache_object; 760 761typedef struct lru_list_elem { 762 PyObject_HEAD 763 struct lru_list_elem *prev, *next; /* borrowed links */ 764 Py_hash_t hash; 765 PyObject *key, *result; 766} lru_list_elem; 767 768static void 769lru_list_elem_dealloc(lru_list_elem *link) 770{ 771 PyTypeObject *tp = Py_TYPE(link); 772 Py_XDECREF(link->key); 773 Py_XDECREF(link->result); 774 tp->tp_free(link); 775 Py_DECREF(tp); 776} 777 778static PyType_Slot lru_list_elem_type_slots[] = { 779 {Py_tp_dealloc, lru_list_elem_dealloc}, 780 {0, 0} 781}; 782 783static PyType_Spec lru_list_elem_type_spec = { 784 .name = "functools._lru_list_elem", 785 .basicsize = sizeof(lru_list_elem), 786 .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION | 787 Py_TPFLAGS_IMMUTABLETYPE, 788 .slots = lru_list_elem_type_slots 789}; 790 791 792typedef PyObject *(*lru_cache_ternaryfunc)(struct lru_cache_object *, PyObject *, PyObject *); 793 794typedef struct lru_cache_object { 795 lru_list_elem root; /* includes PyObject_HEAD */ 796 lru_cache_ternaryfunc wrapper; 797 int typed; 798 PyObject *cache; 799 Py_ssize_t hits; 800 PyObject *func; 801 Py_ssize_t maxsize; 802 Py_ssize_t misses; 803 /* the kwd_mark is used delimit args and keywords in the cache keys */ 804 PyObject *kwd_mark; 805 PyTypeObject *lru_list_elem_type; 806 PyObject *cache_info_type; 807 PyObject *dict; 808 PyObject *weakreflist; 809} lru_cache_object; 810 811static PyObject * 812lru_cache_make_key(PyObject *kwd_mark, PyObject *args, 813 PyObject *kwds, int typed) 814{ 815 PyObject *key, *keyword, *value; 816 Py_ssize_t key_size, pos, key_pos, kwds_size; 817 818 kwds_size = kwds ? PyDict_GET_SIZE(kwds) : 0; 819 820 /* short path, key will match args anyway, which is a tuple */ 821 if (!typed && !kwds_size) { 822 if (PyTuple_GET_SIZE(args) == 1) { 823 key = PyTuple_GET_ITEM(args, 0); 824 if (PyUnicode_CheckExact(key) || PyLong_CheckExact(key)) { 825 /* For common scalar keys, save space by 826 dropping the enclosing args tuple */ 827 Py_INCREF(key); 828 return key; 829 } 830 } 831 Py_INCREF(args); 832 return args; 833 } 834 835 key_size = PyTuple_GET_SIZE(args); 836 if (kwds_size) 837 key_size += kwds_size * 2 + 1; 838 if (typed) 839 key_size += PyTuple_GET_SIZE(args) + kwds_size; 840 841 key = PyTuple_New(key_size); 842 if (key == NULL) 843 return NULL; 844 845 key_pos = 0; 846 for (pos = 0; pos < PyTuple_GET_SIZE(args); ++pos) { 847 PyObject *item = PyTuple_GET_ITEM(args, pos); 848 Py_INCREF(item); 849 PyTuple_SET_ITEM(key, key_pos++, item); 850 } 851 if (kwds_size) { 852 Py_INCREF(kwd_mark); 853 PyTuple_SET_ITEM(key, key_pos++, kwd_mark); 854 for (pos = 0; PyDict_Next(kwds, &pos, &keyword, &value);) { 855 Py_INCREF(keyword); 856 PyTuple_SET_ITEM(key, key_pos++, keyword); 857 Py_INCREF(value); 858 PyTuple_SET_ITEM(key, key_pos++, value); 859 } 860 assert(key_pos == PyTuple_GET_SIZE(args) + kwds_size * 2 + 1); 861 } 862 if (typed) { 863 for (pos = 0; pos < PyTuple_GET_SIZE(args); ++pos) { 864 PyObject *item = (PyObject *)Py_TYPE(PyTuple_GET_ITEM(args, pos)); 865 Py_INCREF(item); 866 PyTuple_SET_ITEM(key, key_pos++, item); 867 } 868 if (kwds_size) { 869 for (pos = 0; PyDict_Next(kwds, &pos, &keyword, &value);) { 870 PyObject *item = (PyObject *)Py_TYPE(value); 871 Py_INCREF(item); 872 PyTuple_SET_ITEM(key, key_pos++, item); 873 } 874 } 875 } 876 assert(key_pos == key_size); 877 return key; 878} 879 880static PyObject * 881uncached_lru_cache_wrapper(lru_cache_object *self, PyObject *args, PyObject *kwds) 882{ 883 PyObject *result; 884 885 self->misses++; 886 result = PyObject_Call(self->func, args, kwds); 887 if (!result) 888 return NULL; 889 return result; 890} 891 892static PyObject * 893infinite_lru_cache_wrapper(lru_cache_object *self, PyObject *args, PyObject *kwds) 894{ 895 PyObject *result; 896 Py_hash_t hash; 897 PyObject *key = lru_cache_make_key(self->kwd_mark, args, kwds, self->typed); 898 if (!key) 899 return NULL; 900 hash = PyObject_Hash(key); 901 if (hash == -1) { 902 Py_DECREF(key); 903 return NULL; 904 } 905 result = _PyDict_GetItem_KnownHash(self->cache, key, hash); 906 if (result) { 907 Py_INCREF(result); 908 self->hits++; 909 Py_DECREF(key); 910 return result; 911 } 912 if (PyErr_Occurred()) { 913 Py_DECREF(key); 914 return NULL; 915 } 916 self->misses++; 917 result = PyObject_Call(self->func, args, kwds); 918 if (!result) { 919 Py_DECREF(key); 920 return NULL; 921 } 922 if (_PyDict_SetItem_KnownHash(self->cache, key, result, hash) < 0) { 923 Py_DECREF(result); 924 Py_DECREF(key); 925 return NULL; 926 } 927 Py_DECREF(key); 928 return result; 929} 930 931static void 932lru_cache_extract_link(lru_list_elem *link) 933{ 934 lru_list_elem *link_prev = link->prev; 935 lru_list_elem *link_next = link->next; 936 link_prev->next = link->next; 937 link_next->prev = link->prev; 938} 939 940static void 941lru_cache_append_link(lru_cache_object *self, lru_list_elem *link) 942{ 943 lru_list_elem *root = &self->root; 944 lru_list_elem *last = root->prev; 945 last->next = root->prev = link; 946 link->prev = last; 947 link->next = root; 948} 949 950static void 951lru_cache_prepend_link(lru_cache_object *self, lru_list_elem *link) 952{ 953 lru_list_elem *root = &self->root; 954 lru_list_elem *first = root->next; 955 first->prev = root->next = link; 956 link->prev = root; 957 link->next = first; 958} 959 960/* General note on reentrancy: 961 962 There are four dictionary calls in the bounded_lru_cache_wrapper(): 963 1) The initial check for a cache match. 2) The post user-function 964 check for a cache match. 3) The deletion of the oldest entry. 965 4) The addition of the newest entry. 966 967 In all four calls, we have a known hash which lets use avoid a call 968 to __hash__(). That leaves only __eq__ as a possible source of a 969 reentrant call. 970 971 The __eq__ method call is always made for a cache hit (dict access #1). 972 Accordingly, we have make sure not modify the cache state prior to 973 this call. 974 975 The __eq__ method call is never made for the deletion (dict access #3) 976 because it is an identity match. 977 978 For the other two accesses (#2 and #4), calls to __eq__ only occur 979 when some other entry happens to have an exactly matching hash (all 980 64-bits). Though rare, this can happen, so we have to make sure to 981 either call it at the top of its code path before any cache 982 state modifications (dict access #2) or be prepared to restore 983 invariants at the end of the code path (dict access #4). 984 985 Another possible source of reentrancy is a decref which can trigger 986 arbitrary code execution. To make the code easier to reason about, 987 the decrefs are deferred to the end of the each possible code path 988 so that we know the cache is a consistent state. 989 */ 990 991static PyObject * 992bounded_lru_cache_wrapper(lru_cache_object *self, PyObject *args, PyObject *kwds) 993{ 994 lru_list_elem *link; 995 PyObject *key, *result, *testresult; 996 Py_hash_t hash; 997 998 key = lru_cache_make_key(self->kwd_mark, args, kwds, self->typed); 999 if (!key) 1000 return NULL; 1001 hash = PyObject_Hash(key); 1002 if (hash == -1) { 1003 Py_DECREF(key); 1004 return NULL; 1005 } 1006 link = (lru_list_elem *)_PyDict_GetItem_KnownHash(self->cache, key, hash); 1007 if (link != NULL) { 1008 lru_cache_extract_link(link); 1009 lru_cache_append_link(self, link); 1010 result = link->result; 1011 self->hits++; 1012 Py_INCREF(result); 1013 Py_DECREF(key); 1014 return result; 1015 } 1016 if (PyErr_Occurred()) { 1017 Py_DECREF(key); 1018 return NULL; 1019 } 1020 self->misses++; 1021 result = PyObject_Call(self->func, args, kwds); 1022 if (!result) { 1023 Py_DECREF(key); 1024 return NULL; 1025 } 1026 testresult = _PyDict_GetItem_KnownHash(self->cache, key, hash); 1027 if (testresult != NULL) { 1028 /* Getting here means that this same key was added to the cache 1029 during the PyObject_Call(). Since the link update is already 1030 done, we need only return the computed result. */ 1031 Py_DECREF(key); 1032 return result; 1033 } 1034 if (PyErr_Occurred()) { 1035 /* This is an unusual case since this same lookup 1036 did not previously trigger an error during lookup. 1037 Treat it the same as an error in user function 1038 and return with the error set. */ 1039 Py_DECREF(key); 1040 Py_DECREF(result); 1041 return NULL; 1042 } 1043 /* This is the normal case. The new key wasn't found before 1044 user function call and it is still not there. So we 1045 proceed normally and update the cache with the new result. */ 1046 1047 assert(self->maxsize > 0); 1048 if (PyDict_GET_SIZE(self->cache) < self->maxsize || 1049 self->root.next == &self->root) 1050 { 1051 /* Cache is not full, so put the result in a new link */ 1052 link = (lru_list_elem *)PyObject_New(lru_list_elem, 1053 self->lru_list_elem_type); 1054 if (link == NULL) { 1055 Py_DECREF(key); 1056 Py_DECREF(result); 1057 return NULL; 1058 } 1059 1060 link->hash = hash; 1061 link->key = key; 1062 link->result = result; 1063 /* What is really needed here is a SetItem variant with a "no clobber" 1064 option. If the __eq__ call triggers a reentrant call that adds 1065 this same key, then this setitem call will update the cache dict 1066 with this new link, leaving the old link as an orphan (i.e. not 1067 having a cache dict entry that refers to it). */ 1068 if (_PyDict_SetItem_KnownHash(self->cache, key, (PyObject *)link, 1069 hash) < 0) { 1070 Py_DECREF(link); 1071 return NULL; 1072 } 1073 lru_cache_append_link(self, link); 1074 Py_INCREF(result); /* for return */ 1075 return result; 1076 } 1077 /* Since the cache is full, we need to evict an old key and add 1078 a new key. Rather than free the old link and allocate a new 1079 one, we reuse the link for the new key and result and move it 1080 to front of the cache to mark it as recently used. 1081 1082 We try to assure all code paths (including errors) leave all 1083 of the links in place. Either the link is successfully 1084 updated and moved or it is restored to its old position. 1085 However if an unrecoverable error is found, it doesn't 1086 make sense to reinsert the link, so we leave it out 1087 and the cache will no longer register as full. 1088 */ 1089 PyObject *oldkey, *oldresult, *popresult; 1090 1091 /* Extract the oldest item. */ 1092 assert(self->root.next != &self->root); 1093 link = self->root.next; 1094 lru_cache_extract_link(link); 1095 /* Remove it from the cache. 1096 The cache dict holds one reference to the link. 1097 We created one other reference when the link was created. 1098 The linked list only has borrowed references. */ 1099 popresult = _PyDict_Pop_KnownHash(self->cache, link->key, 1100 link->hash, Py_None); 1101 if (popresult == Py_None) { 1102 /* Getting here means that the user function call or another 1103 thread has already removed the old key from the dictionary. 1104 This link is now an orphan. Since we don't want to leave the 1105 cache in an inconsistent state, we don't restore the link. */ 1106 Py_DECREF(popresult); 1107 Py_DECREF(link); 1108 Py_DECREF(key); 1109 return result; 1110 } 1111 if (popresult == NULL) { 1112 /* An error arose while trying to remove the oldest key (the one 1113 being evicted) from the cache. We restore the link to its 1114 original position as the oldest link. Then we allow the 1115 error propagate upward; treating it the same as an error 1116 arising in the user function. */ 1117 lru_cache_prepend_link(self, link); 1118 Py_DECREF(key); 1119 Py_DECREF(result); 1120 return NULL; 1121 } 1122 /* Keep a reference to the old key and old result to prevent their 1123 ref counts from going to zero during the update. That will 1124 prevent potentially arbitrary object clean-up code (i.e. __del__) 1125 from running while we're still adjusting the links. */ 1126 oldkey = link->key; 1127 oldresult = link->result; 1128 1129 link->hash = hash; 1130 link->key = key; 1131 link->result = result; 1132 /* Note: The link is being added to the cache dict without the 1133 prev and next fields set to valid values. We have to wait 1134 for successful insertion in the cache dict before adding the 1135 link to the linked list. Otherwise, the potentially reentrant 1136 __eq__ call could cause the then orphan link to be visited. */ 1137 if (_PyDict_SetItem_KnownHash(self->cache, key, (PyObject *)link, 1138 hash) < 0) { 1139 /* Somehow the cache dict update failed. We no longer can 1140 restore the old link. Let the error propagate upward and 1141 leave the cache short one link. */ 1142 Py_DECREF(popresult); 1143 Py_DECREF(link); 1144 Py_DECREF(oldkey); 1145 Py_DECREF(oldresult); 1146 return NULL; 1147 } 1148 lru_cache_append_link(self, link); 1149 Py_INCREF(result); /* for return */ 1150 Py_DECREF(popresult); 1151 Py_DECREF(oldkey); 1152 Py_DECREF(oldresult); 1153 return result; 1154} 1155 1156static PyObject * 1157lru_cache_new(PyTypeObject *type, PyObject *args, PyObject *kw) 1158{ 1159 PyObject *func, *maxsize_O, *cache_info_type, *cachedict; 1160 int typed; 1161 lru_cache_object *obj; 1162 Py_ssize_t maxsize; 1163 PyObject *(*wrapper)(lru_cache_object *, PyObject *, PyObject *); 1164 _functools_state *state; 1165 static char *keywords[] = {"user_function", "maxsize", "typed", 1166 "cache_info_type", NULL}; 1167 1168 if (!PyArg_ParseTupleAndKeywords(args, kw, "OOpO:lru_cache", keywords, 1169 &func, &maxsize_O, &typed, 1170 &cache_info_type)) { 1171 return NULL; 1172 } 1173 1174 if (!PyCallable_Check(func)) { 1175 PyErr_SetString(PyExc_TypeError, 1176 "the first argument must be callable"); 1177 return NULL; 1178 } 1179 1180 state = get_functools_state_by_type(type); 1181 if (state == NULL) { 1182 return NULL; 1183 } 1184 1185 /* select the caching function, and make/inc maxsize_O */ 1186 if (maxsize_O == Py_None) { 1187 wrapper = infinite_lru_cache_wrapper; 1188 /* use this only to initialize lru_cache_object attribute maxsize */ 1189 maxsize = -1; 1190 } else if (PyIndex_Check(maxsize_O)) { 1191 maxsize = PyNumber_AsSsize_t(maxsize_O, PyExc_OverflowError); 1192 if (maxsize == -1 && PyErr_Occurred()) 1193 return NULL; 1194 if (maxsize < 0) { 1195 maxsize = 0; 1196 } 1197 if (maxsize == 0) 1198 wrapper = uncached_lru_cache_wrapper; 1199 else 1200 wrapper = bounded_lru_cache_wrapper; 1201 } else { 1202 PyErr_SetString(PyExc_TypeError, "maxsize should be integer or None"); 1203 return NULL; 1204 } 1205 1206 if (!(cachedict = PyDict_New())) 1207 return NULL; 1208 1209 obj = (lru_cache_object *)type->tp_alloc(type, 0); 1210 if (obj == NULL) { 1211 Py_DECREF(cachedict); 1212 return NULL; 1213 } 1214 1215 obj->root.prev = &obj->root; 1216 obj->root.next = &obj->root; 1217 obj->wrapper = wrapper; 1218 obj->typed = typed; 1219 obj->cache = cachedict; 1220 Py_INCREF(func); 1221 obj->func = func; 1222 obj->misses = obj->hits = 0; 1223 obj->maxsize = maxsize; 1224 Py_INCREF(state->kwd_mark); 1225 obj->kwd_mark = state->kwd_mark; 1226 Py_INCREF(state->lru_list_elem_type); 1227 obj->lru_list_elem_type = state->lru_list_elem_type; 1228 Py_INCREF(cache_info_type); 1229 obj->cache_info_type = cache_info_type; 1230 obj->dict = NULL; 1231 obj->weakreflist = NULL; 1232 return (PyObject *)obj; 1233} 1234 1235static lru_list_elem * 1236lru_cache_unlink_list(lru_cache_object *self) 1237{ 1238 lru_list_elem *root = &self->root; 1239 lru_list_elem *link = root->next; 1240 if (link == root) 1241 return NULL; 1242 root->prev->next = NULL; 1243 root->next = root->prev = root; 1244 return link; 1245} 1246 1247static void 1248lru_cache_clear_list(lru_list_elem *link) 1249{ 1250 while (link != NULL) { 1251 lru_list_elem *next = link->next; 1252 Py_DECREF(link); 1253 link = next; 1254 } 1255} 1256 1257static int 1258lru_cache_tp_clear(lru_cache_object *self) 1259{ 1260 lru_list_elem *list = lru_cache_unlink_list(self); 1261 Py_CLEAR(self->cache); 1262 Py_CLEAR(self->func); 1263 Py_CLEAR(self->kwd_mark); 1264 Py_CLEAR(self->lru_list_elem_type); 1265 Py_CLEAR(self->cache_info_type); 1266 Py_CLEAR(self->dict); 1267 lru_cache_clear_list(list); 1268 return 0; 1269} 1270 1271static void 1272lru_cache_dealloc(lru_cache_object *obj) 1273{ 1274 PyTypeObject *tp = Py_TYPE(obj); 1275 /* bpo-31095: UnTrack is needed before calling any callbacks */ 1276 PyObject_GC_UnTrack(obj); 1277 if (obj->weakreflist != NULL) { 1278 PyObject_ClearWeakRefs((PyObject*)obj); 1279 } 1280 1281 (void)lru_cache_tp_clear(obj); 1282 tp->tp_free(obj); 1283 Py_DECREF(tp); 1284} 1285 1286static PyObject * 1287lru_cache_call(lru_cache_object *self, PyObject *args, PyObject *kwds) 1288{ 1289 return self->wrapper(self, args, kwds); 1290} 1291 1292static PyObject * 1293lru_cache_descr_get(PyObject *self, PyObject *obj, PyObject *type) 1294{ 1295 if (obj == Py_None || obj == NULL) { 1296 Py_INCREF(self); 1297 return self; 1298 } 1299 return PyMethod_New(self, obj); 1300} 1301 1302static PyObject * 1303lru_cache_cache_info(lru_cache_object *self, PyObject *unused) 1304{ 1305 if (self->maxsize == -1) { 1306 return PyObject_CallFunction(self->cache_info_type, "nnOn", 1307 self->hits, self->misses, Py_None, 1308 PyDict_GET_SIZE(self->cache)); 1309 } 1310 return PyObject_CallFunction(self->cache_info_type, "nnnn", 1311 self->hits, self->misses, self->maxsize, 1312 PyDict_GET_SIZE(self->cache)); 1313} 1314 1315static PyObject * 1316lru_cache_cache_clear(lru_cache_object *self, PyObject *unused) 1317{ 1318 lru_list_elem *list = lru_cache_unlink_list(self); 1319 self->hits = self->misses = 0; 1320 PyDict_Clear(self->cache); 1321 lru_cache_clear_list(list); 1322 Py_RETURN_NONE; 1323} 1324 1325static PyObject * 1326lru_cache_reduce(PyObject *self, PyObject *unused) 1327{ 1328 return PyObject_GetAttrString(self, "__qualname__"); 1329} 1330 1331static PyObject * 1332lru_cache_copy(PyObject *self, PyObject *unused) 1333{ 1334 Py_INCREF(self); 1335 return self; 1336} 1337 1338static PyObject * 1339lru_cache_deepcopy(PyObject *self, PyObject *unused) 1340{ 1341 Py_INCREF(self); 1342 return self; 1343} 1344 1345static int 1346lru_cache_tp_traverse(lru_cache_object *self, visitproc visit, void *arg) 1347{ 1348 Py_VISIT(Py_TYPE(self)); 1349 lru_list_elem *link = self->root.next; 1350 while (link != &self->root) { 1351 lru_list_elem *next = link->next; 1352 Py_VISIT(link->key); 1353 Py_VISIT(link->result); 1354 Py_VISIT(Py_TYPE(link)); 1355 link = next; 1356 } 1357 Py_VISIT(self->cache); 1358 Py_VISIT(self->func); 1359 Py_VISIT(self->kwd_mark); 1360 Py_VISIT(self->lru_list_elem_type); 1361 Py_VISIT(self->cache_info_type); 1362 Py_VISIT(self->dict); 1363 return 0; 1364} 1365 1366 1367PyDoc_STRVAR(lru_cache_doc, 1368"Create a cached callable that wraps another function.\n\ 1369\n\ 1370user_function: the function being cached\n\ 1371\n\ 1372maxsize: 0 for no caching\n\ 1373 None for unlimited cache size\n\ 1374 n for a bounded cache\n\ 1375\n\ 1376typed: False cache f(3) and f(3.0) as identical calls\n\ 1377 True cache f(3) and f(3.0) as distinct calls\n\ 1378\n\ 1379cache_info_type: namedtuple class with the fields:\n\ 1380 hits misses currsize maxsize\n" 1381); 1382 1383static PyMethodDef lru_cache_methods[] = { 1384 {"cache_info", (PyCFunction)lru_cache_cache_info, METH_NOARGS}, 1385 {"cache_clear", (PyCFunction)lru_cache_cache_clear, METH_NOARGS}, 1386 {"__reduce__", (PyCFunction)lru_cache_reduce, METH_NOARGS}, 1387 {"__copy__", (PyCFunction)lru_cache_copy, METH_VARARGS}, 1388 {"__deepcopy__", (PyCFunction)lru_cache_deepcopy, METH_VARARGS}, 1389 {NULL} 1390}; 1391 1392static PyGetSetDef lru_cache_getsetlist[] = { 1393 {"__dict__", PyObject_GenericGetDict, PyObject_GenericSetDict}, 1394 {NULL} 1395}; 1396 1397static PyMemberDef lru_cache_memberlist[] = { 1398 {"__dictoffset__", T_PYSSIZET, 1399 offsetof(lru_cache_object, dict), READONLY}, 1400 {"__weaklistoffset__", T_PYSSIZET, 1401 offsetof(lru_cache_object, weakreflist), READONLY}, 1402 {NULL} /* Sentinel */ 1403}; 1404 1405static PyType_Slot lru_cache_type_slots[] = { 1406 {Py_tp_dealloc, lru_cache_dealloc}, 1407 {Py_tp_call, lru_cache_call}, 1408 {Py_tp_doc, (void *)lru_cache_doc}, 1409 {Py_tp_traverse, lru_cache_tp_traverse}, 1410 {Py_tp_clear, lru_cache_tp_clear}, 1411 {Py_tp_methods, lru_cache_methods}, 1412 {Py_tp_members, lru_cache_memberlist}, 1413 {Py_tp_getset, lru_cache_getsetlist}, 1414 {Py_tp_descr_get, lru_cache_descr_get}, 1415 {Py_tp_new, lru_cache_new}, 1416 {0, 0} 1417}; 1418 1419static PyType_Spec lru_cache_type_spec = { 1420 .name = "functools._lru_cache_wrapper", 1421 .basicsize = sizeof(lru_cache_object), 1422 .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | 1423 Py_TPFLAGS_METHOD_DESCRIPTOR | Py_TPFLAGS_IMMUTABLETYPE, 1424 .slots = lru_cache_type_slots 1425}; 1426 1427 1428/* module level code ********************************************************/ 1429 1430PyDoc_STRVAR(_functools_doc, 1431"Tools that operate on functions."); 1432 1433static PyMethodDef _functools_methods[] = { 1434 {"reduce", functools_reduce, METH_VARARGS, functools_reduce_doc}, 1435 {"cmp_to_key", _PyCFunction_CAST(functools_cmp_to_key), 1436 METH_VARARGS | METH_KEYWORDS, functools_cmp_to_key_doc}, 1437 {NULL, NULL} /* sentinel */ 1438}; 1439 1440static int 1441_functools_exec(PyObject *module) 1442{ 1443 _functools_state *state = get_functools_state(module); 1444 state->kwd_mark = _PyObject_CallNoArgs((PyObject *)&PyBaseObject_Type); 1445 if (state->kwd_mark == NULL) { 1446 return -1; 1447 } 1448 1449 state->partial_type = (PyTypeObject *)PyType_FromModuleAndSpec(module, 1450 &partial_type_spec, NULL); 1451 if (state->partial_type == NULL) { 1452 return -1; 1453 } 1454 if (PyModule_AddType(module, state->partial_type) < 0) { 1455 return -1; 1456 } 1457 1458 PyObject *lru_cache_type = PyType_FromModuleAndSpec(module, 1459 &lru_cache_type_spec, NULL); 1460 if (lru_cache_type == NULL) { 1461 return -1; 1462 } 1463 if (PyModule_AddType(module, (PyTypeObject *)lru_cache_type) < 0) { 1464 Py_DECREF(lru_cache_type); 1465 return -1; 1466 } 1467 Py_DECREF(lru_cache_type); 1468 1469 state->keyobject_type = (PyTypeObject *)PyType_FromModuleAndSpec(module, 1470 &keyobject_type_spec, NULL); 1471 if (state->keyobject_type == NULL) { 1472 return -1; 1473 } 1474 // keyobject_type is used only internally. 1475 // So we don't expose it in module namespace. 1476 1477 state->lru_list_elem_type = (PyTypeObject *)PyType_FromModuleAndSpec( 1478 module, &lru_list_elem_type_spec, NULL); 1479 if (state->lru_list_elem_type == NULL) { 1480 return -1; 1481 } 1482 // lru_list_elem is used only in _lru_cache_wrapper. 1483 // So we don't expose it in module namespace. 1484 1485 return 0; 1486} 1487 1488static int 1489_functools_traverse(PyObject *module, visitproc visit, void *arg) 1490{ 1491 _functools_state *state = get_functools_state(module); 1492 Py_VISIT(state->kwd_mark); 1493 Py_VISIT(state->partial_type); 1494 Py_VISIT(state->keyobject_type); 1495 Py_VISIT(state->lru_list_elem_type); 1496 return 0; 1497} 1498 1499static int 1500_functools_clear(PyObject *module) 1501{ 1502 _functools_state *state = get_functools_state(module); 1503 Py_CLEAR(state->kwd_mark); 1504 Py_CLEAR(state->partial_type); 1505 Py_CLEAR(state->keyobject_type); 1506 Py_CLEAR(state->lru_list_elem_type); 1507 return 0; 1508} 1509 1510static void 1511_functools_free(void *module) 1512{ 1513 _functools_clear((PyObject *)module); 1514} 1515 1516static struct PyModuleDef_Slot _functools_slots[] = { 1517 {Py_mod_exec, _functools_exec}, 1518 {0, NULL} 1519}; 1520 1521static struct PyModuleDef _functools_module = { 1522 PyModuleDef_HEAD_INIT, 1523 .m_name = "_functools", 1524 .m_doc = _functools_doc, 1525 .m_size = sizeof(_functools_state), 1526 .m_methods = _functools_methods, 1527 .m_slots = _functools_slots, 1528 .m_traverse = _functools_traverse, 1529 .m_clear = _functools_clear, 1530 .m_free = _functools_free, 1531}; 1532 1533PyMODINIT_FUNC 1534PyInit__functools(void) 1535{ 1536 return PyModuleDef_Init(&_functools_module); 1537} 1538