ยปCore Development>Code coverage>Modules/_functoolsmodule.c

Python code coverage for Modules/_functoolsmodule.c

#countcontent
1n/a
2n/a#include "Python.h"
3n/a#include "structmember.h"
4n/a
5n/a/* _functools module written and maintained
6n/a by Hye-Shik Chang <perky@FreeBSD.org>
7n/a with adaptations by Raymond Hettinger <python@rcn.com>
8n/a Copyright (c) 2004, 2005, 2006 Python Software Foundation.
9n/a All rights reserved.
10n/a*/
11n/a
12n/a/* partial object **********************************************************/
13n/a
14n/atypedef struct {
15n/a PyObject_HEAD
16n/a PyObject *fn;
17n/a PyObject *args;
18n/a PyObject *kw;
19n/a PyObject *dict;
20n/a PyObject *weakreflist; /* List of weak references */
21n/a} partialobject;
22n/a
23n/astatic PyTypeObject partial_type;
24n/a
25n/astatic PyObject *
26n/apartial_new(PyTypeObject *type, PyObject *args, PyObject *kw)
27n/a{
28n/a PyObject *func, *pargs, *nargs, *pkw;
29n/a partialobject *pto;
30n/a
31n/a if (PyTuple_GET_SIZE(args) < 1) {
32n/a PyErr_SetString(PyExc_TypeError,
33n/a "type 'partial' takes at least one argument");
34n/a return NULL;
35n/a }
36n/a
37n/a pargs = pkw = NULL;
38n/a func = PyTuple_GET_ITEM(args, 0);
39n/a if (Py_TYPE(func) == &partial_type && type == &partial_type) {
40n/a partialobject *part = (partialobject *)func;
41n/a if (part->dict == NULL) {
42n/a pargs = part->args;
43n/a pkw = part->kw;
44n/a func = part->fn;
45n/a assert(PyTuple_Check(pargs));
46n/a assert(PyDict_Check(pkw));
47n/a }
48n/a }
49n/a if (!PyCallable_Check(func)) {
50n/a PyErr_SetString(PyExc_TypeError,
51n/a "the first argument must be callable");
52n/a return NULL;
53n/a }
54n/a
55n/a /* create partialobject structure */
56n/a pto = (partialobject *)type->tp_alloc(type, 0);
57n/a if (pto == NULL)
58n/a return NULL;
59n/a
60n/a pto->fn = func;
61n/a Py_INCREF(func);
62n/a
63n/a nargs = PyTuple_GetSlice(args, 1, PY_SSIZE_T_MAX);
64n/a if (nargs == NULL) {
65n/a Py_DECREF(pto);
66n/a return NULL;
67n/a }
68n/a if (pargs == NULL || PyTuple_GET_SIZE(pargs) == 0) {
69n/a pto->args = nargs;
70n/a Py_INCREF(nargs);
71n/a }
72n/a else if (PyTuple_GET_SIZE(nargs) == 0) {
73n/a pto->args = pargs;
74n/a Py_INCREF(pargs);
75n/a }
76n/a else {
77n/a pto->args = PySequence_Concat(pargs, nargs);
78n/a if (pto->args == NULL) {
79n/a Py_DECREF(nargs);
80n/a Py_DECREF(pto);
81n/a return NULL;
82n/a }
83n/a assert(PyTuple_Check(pto->args));
84n/a }
85n/a Py_DECREF(nargs);
86n/a
87n/a if (pkw == NULL || PyDict_GET_SIZE(pkw) == 0) {
88n/a if (kw == NULL) {
89n/a pto->kw = PyDict_New();
90n/a }
91n/a else {
92n/a Py_INCREF(kw);
93n/a pto->kw = kw;
94n/a }
95n/a }
96n/a else {
97n/a pto->kw = PyDict_Copy(pkw);
98n/a if (kw != NULL && pto->kw != NULL) {
99n/a if (PyDict_Merge(pto->kw, kw, 1) != 0) {
100n/a Py_DECREF(pto);
101n/a return NULL;
102n/a }
103n/a }
104n/a }
105n/a if (pto->kw == NULL) {
106n/a Py_DECREF(pto);
107n/a return NULL;
108n/a }
109n/a
110n/a return (PyObject *)pto;
111n/a}
112n/a
113n/astatic void
114n/apartial_dealloc(partialobject *pto)
115n/a{
116n/a PyObject_GC_UnTrack(pto);
117n/a if (pto->weakreflist != NULL)
118n/a PyObject_ClearWeakRefs((PyObject *) pto);
119n/a Py_XDECREF(pto->fn);
120n/a Py_XDECREF(pto->args);
121n/a Py_XDECREF(pto->kw);
122n/a Py_XDECREF(pto->dict);
123n/a Py_TYPE(pto)->tp_free(pto);
124n/a}
125n/a
126n/astatic PyObject *
127n/apartial_call(partialobject *pto, PyObject *args, PyObject *kw)
128n/a{
129n/a PyObject *ret;
130n/a PyObject *argappl, *kwappl;
131n/a PyObject **stack;
132n/a Py_ssize_t nargs;
133n/a
134n/a assert (PyCallable_Check(pto->fn));
135n/a assert (PyTuple_Check(pto->args));
136n/a assert (PyDict_Check(pto->kw));
137n/a
138n/a if (PyTuple_GET_SIZE(pto->args) == 0) {
139n/a stack = &PyTuple_GET_ITEM(args, 0);
140n/a nargs = PyTuple_GET_SIZE(args);
141n/a argappl = NULL;
142n/a }
143n/a else if (PyTuple_GET_SIZE(args) == 0) {
144n/a stack = &PyTuple_GET_ITEM(pto->args, 0);
145n/a nargs = PyTuple_GET_SIZE(pto->args);
146n/a argappl = NULL;
147n/a }
148n/a else {
149n/a stack = NULL;
150n/a argappl = PySequence_Concat(pto->args, args);
151n/a if (argappl == NULL) {
152n/a return NULL;
153n/a }
154n/a
155n/a assert(PyTuple_Check(argappl));
156n/a }
157n/a
158n/a if (PyDict_GET_SIZE(pto->kw) == 0) {
159n/a kwappl = kw;
160n/a Py_XINCREF(kwappl);
161n/a }
162n/a else {
163n/a kwappl = PyDict_Copy(pto->kw);
164n/a if (kwappl == NULL) {
165n/a Py_XDECREF(argappl);
166n/a return NULL;
167n/a }
168n/a
169n/a if (kw != NULL) {
170n/a if (PyDict_Merge(kwappl, kw, 1) != 0) {
171n/a Py_XDECREF(argappl);
172n/a Py_DECREF(kwappl);
173n/a return NULL;
174n/a }
175n/a }
176n/a }
177n/a
178n/a if (stack) {
179n/a ret = _PyObject_FastCallDict(pto->fn, stack, nargs, kwappl);
180n/a }
181n/a else {
182n/a ret = PyObject_Call(pto->fn, argappl, kwappl);
183n/a Py_DECREF(argappl);
184n/a }
185n/a Py_XDECREF(kwappl);
186n/a return ret;
187n/a}
188n/a
189n/astatic int
190n/apartial_traverse(partialobject *pto, visitproc visit, void *arg)
191n/a{
192n/a Py_VISIT(pto->fn);
193n/a Py_VISIT(pto->args);
194n/a Py_VISIT(pto->kw);
195n/a Py_VISIT(pto->dict);
196n/a return 0;
197n/a}
198n/a
199n/aPyDoc_STRVAR(partial_doc,
200n/a"partial(func, *args, **keywords) - new function with partial application\n\
201n/a of the given arguments and keywords.\n");
202n/a
203n/a#define OFF(x) offsetof(partialobject, x)
204n/astatic PyMemberDef partial_memberlist[] = {
205n/a {"func", T_OBJECT, OFF(fn), READONLY,
206n/a "function object to use in future partial calls"},
207n/a {"args", T_OBJECT, OFF(args), READONLY,
208n/a "tuple of arguments to future partial calls"},
209n/a {"keywords", T_OBJECT, OFF(kw), READONLY,
210n/a "dictionary of keyword arguments to future partial calls"},
211n/a {NULL} /* Sentinel */
212n/a};
213n/a
214n/astatic PyGetSetDef partial_getsetlist[] = {
215n/a {"__dict__", PyObject_GenericGetDict, PyObject_GenericSetDict},
216n/a {NULL} /* Sentinel */
217n/a};
218n/a
219n/astatic PyObject *
220n/apartial_repr(partialobject *pto)
221n/a{
222n/a PyObject *result = NULL;
223n/a PyObject *arglist;
224n/a Py_ssize_t i, n;
225n/a PyObject *key, *value;
226n/a int status;
227n/a
228n/a status = Py_ReprEnter((PyObject *)pto);
229n/a if (status != 0) {
230n/a if (status < 0)
231n/a return NULL;
232n/a return PyUnicode_FromString("...");
233n/a }
234n/a
235n/a arglist = PyUnicode_FromString("");
236n/a if (arglist == NULL)
237n/a goto done;
238n/a /* Pack positional arguments */
239n/a assert (PyTuple_Check(pto->args));
240n/a n = PyTuple_GET_SIZE(pto->args);
241n/a for (i = 0; i < n; i++) {
242n/a Py_SETREF(arglist, PyUnicode_FromFormat("%U, %R", arglist,
243n/a PyTuple_GET_ITEM(pto->args, i)));
244n/a if (arglist == NULL)
245n/a goto done;
246n/a }
247n/a /* Pack keyword arguments */
248n/a assert (PyDict_Check(pto->kw));
249n/a for (i = 0; PyDict_Next(pto->kw, &i, &key, &value);) {
250n/a Py_SETREF(arglist, PyUnicode_FromFormat("%U, %U=%R", arglist,
251n/a key, value));
252n/a if (arglist == NULL)
253n/a goto done;
254n/a }
255n/a result = PyUnicode_FromFormat("%s(%R%U)", Py_TYPE(pto)->tp_name,
256n/a pto->fn, arglist);
257n/a Py_DECREF(arglist);
258n/a
259n/a done:
260n/a Py_ReprLeave((PyObject *)pto);
261n/a return result;
262n/a}
263n/a
264n/a/* Pickle strategy:
265n/a __reduce__ by itself doesn't support getting kwargs in the unpickle
266n/a operation so we define a __setstate__ that replaces all the information
267n/a about the partial. If we only replaced part of it someone would use
268n/a it as a hook to do strange things.
269n/a */
270n/a
271n/astatic PyObject *
272n/apartial_reduce(partialobject *pto, PyObject *unused)
273n/a{
274n/a return Py_BuildValue("O(O)(OOOO)", Py_TYPE(pto), pto->fn, pto->fn,
275n/a pto->args, pto->kw,
276n/a pto->dict ? pto->dict : Py_None);
277n/a}
278n/a
279n/astatic PyObject *
280n/apartial_setstate(partialobject *pto, PyObject *state)
281n/a{
282n/a PyObject *fn, *fnargs, *kw, *dict;
283n/a
284n/a if (!PyTuple_Check(state) ||
285n/a !PyArg_ParseTuple(state, "OOOO", &fn, &fnargs, &kw, &dict) ||
286n/a !PyCallable_Check(fn) ||
287n/a !PyTuple_Check(fnargs) ||
288n/a (kw != Py_None && !PyDict_Check(kw)))
289n/a {
290n/a PyErr_SetString(PyExc_TypeError, "invalid partial state");
291n/a return NULL;
292n/a }
293n/a
294n/a if(!PyTuple_CheckExact(fnargs))
295n/a fnargs = PySequence_Tuple(fnargs);
296n/a else
297n/a Py_INCREF(fnargs);
298n/a if (fnargs == NULL)
299n/a return NULL;
300n/a
301n/a if (kw == Py_None)
302n/a kw = PyDict_New();
303n/a else if(!PyDict_CheckExact(kw))
304n/a kw = PyDict_Copy(kw);
305n/a else
306n/a Py_INCREF(kw);
307n/a if (kw == NULL) {
308n/a Py_DECREF(fnargs);
309n/a return NULL;
310n/a }
311n/a
312n/a Py_INCREF(fn);
313n/a if (dict == Py_None)
314n/a dict = NULL;
315n/a else
316n/a Py_INCREF(dict);
317n/a
318n/a Py_SETREF(pto->fn, fn);
319n/a Py_SETREF(pto->args, fnargs);
320n/a Py_SETREF(pto->kw, kw);
321n/a Py_XSETREF(pto->dict, dict);
322n/a Py_RETURN_NONE;
323n/a}
324n/a
325n/astatic PyMethodDef partial_methods[] = {
326n/a {"__reduce__", (PyCFunction)partial_reduce, METH_NOARGS},
327n/a {"__setstate__", (PyCFunction)partial_setstate, METH_O},
328n/a {NULL, NULL} /* sentinel */
329n/a};
330n/a
331n/astatic PyTypeObject partial_type = {
332n/a PyVarObject_HEAD_INIT(NULL, 0)
333n/a "functools.partial", /* tp_name */
334n/a sizeof(partialobject), /* tp_basicsize */
335n/a 0, /* tp_itemsize */
336n/a /* methods */
337n/a (destructor)partial_dealloc, /* tp_dealloc */
338n/a 0, /* tp_print */
339n/a 0, /* tp_getattr */
340n/a 0, /* tp_setattr */
341n/a 0, /* tp_reserved */
342n/a (reprfunc)partial_repr, /* tp_repr */
343n/a 0, /* tp_as_number */
344n/a 0, /* tp_as_sequence */
345n/a 0, /* tp_as_mapping */
346n/a 0, /* tp_hash */
347n/a (ternaryfunc)partial_call, /* tp_call */
348n/a 0, /* tp_str */
349n/a PyObject_GenericGetAttr, /* tp_getattro */
350n/a PyObject_GenericSetAttr, /* tp_setattro */
351n/a 0, /* tp_as_buffer */
352n/a Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
353n/a Py_TPFLAGS_BASETYPE, /* tp_flags */
354n/a partial_doc, /* tp_doc */
355n/a (traverseproc)partial_traverse, /* tp_traverse */
356n/a 0, /* tp_clear */
357n/a 0, /* tp_richcompare */
358n/a offsetof(partialobject, weakreflist), /* tp_weaklistoffset */
359n/a 0, /* tp_iter */
360n/a 0, /* tp_iternext */
361n/a partial_methods, /* tp_methods */
362n/a partial_memberlist, /* tp_members */
363n/a partial_getsetlist, /* tp_getset */
364n/a 0, /* tp_base */
365n/a 0, /* tp_dict */
366n/a 0, /* tp_descr_get */
367n/a 0, /* tp_descr_set */
368n/a offsetof(partialobject, dict), /* tp_dictoffset */
369n/a 0, /* tp_init */
370n/a 0, /* tp_alloc */
371n/a partial_new, /* tp_new */
372n/a PyObject_GC_Del, /* tp_free */
373n/a};
374n/a
375n/a
376n/a/* cmp_to_key ***************************************************************/
377n/a
378n/atypedef struct {
379n/a PyObject_HEAD
380n/a PyObject *cmp;
381n/a PyObject *object;
382n/a} keyobject;
383n/a
384n/astatic void
385n/akeyobject_dealloc(keyobject *ko)
386n/a{
387n/a Py_DECREF(ko->cmp);
388n/a Py_XDECREF(ko->object);
389n/a PyObject_FREE(ko);
390n/a}
391n/a
392n/astatic int
393n/akeyobject_traverse(keyobject *ko, visitproc visit, void *arg)
394n/a{
395n/a Py_VISIT(ko->cmp);
396n/a if (ko->object)
397n/a Py_VISIT(ko->object);
398n/a return 0;
399n/a}
400n/a
401n/astatic int
402n/akeyobject_clear(keyobject *ko)
403n/a{
404n/a Py_CLEAR(ko->cmp);
405n/a if (ko->object)
406n/a Py_CLEAR(ko->object);
407n/a return 0;
408n/a}
409n/a
410n/astatic PyMemberDef keyobject_members[] = {
411n/a {"obj", T_OBJECT,
412n/a offsetof(keyobject, object), 0,
413n/a PyDoc_STR("Value wrapped by a key function.")},
414n/a {NULL}
415n/a};
416n/a
417n/astatic PyObject *
418n/akeyobject_call(keyobject *ko, PyObject *args, PyObject *kwds);
419n/a
420n/astatic PyObject *
421n/akeyobject_richcompare(PyObject *ko, PyObject *other, int op);
422n/a
423n/astatic PyTypeObject keyobject_type = {
424n/a PyVarObject_HEAD_INIT(&PyType_Type, 0)
425n/a "functools.KeyWrapper", /* tp_name */
426n/a sizeof(keyobject), /* tp_basicsize */
427n/a 0, /* tp_itemsize */
428n/a /* methods */
429n/a (destructor)keyobject_dealloc, /* tp_dealloc */
430n/a 0, /* tp_print */
431n/a 0, /* tp_getattr */
432n/a 0, /* tp_setattr */
433n/a 0, /* tp_reserved */
434n/a 0, /* tp_repr */
435n/a 0, /* tp_as_number */
436n/a 0, /* tp_as_sequence */
437n/a 0, /* tp_as_mapping */
438n/a 0, /* tp_hash */
439n/a (ternaryfunc)keyobject_call, /* tp_call */
440n/a 0, /* tp_str */
441n/a PyObject_GenericGetAttr, /* tp_getattro */
442n/a 0, /* tp_setattro */
443n/a 0, /* tp_as_buffer */
444n/a Py_TPFLAGS_DEFAULT, /* tp_flags */
445n/a 0, /* tp_doc */
446n/a (traverseproc)keyobject_traverse, /* tp_traverse */
447n/a (inquiry)keyobject_clear, /* tp_clear */
448n/a keyobject_richcompare, /* tp_richcompare */
449n/a 0, /* tp_weaklistoffset */
450n/a 0, /* tp_iter */
451n/a 0, /* tp_iternext */
452n/a 0, /* tp_methods */
453n/a keyobject_members, /* tp_members */
454n/a 0, /* tp_getset */
455n/a};
456n/a
457n/astatic PyObject *
458n/akeyobject_call(keyobject *ko, PyObject *args, PyObject *kwds)
459n/a{
460n/a PyObject *object;
461n/a keyobject *result;
462n/a static char *kwargs[] = {"obj", NULL};
463n/a
464n/a if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:K", kwargs, &object))
465n/a return NULL;
466n/a result = PyObject_New(keyobject, &keyobject_type);
467n/a if (!result)
468n/a return NULL;
469n/a Py_INCREF(ko->cmp);
470n/a result->cmp = ko->cmp;
471n/a Py_INCREF(object);
472n/a result->object = object;
473n/a return (PyObject *)result;
474n/a}
475n/a
476n/astatic PyObject *
477n/akeyobject_richcompare(PyObject *ko, PyObject *other, int op)
478n/a{
479n/a PyObject *res;
480n/a PyObject *x;
481n/a PyObject *y;
482n/a PyObject *compare;
483n/a PyObject *answer;
484n/a static PyObject *zero;
485n/a PyObject* stack[2];
486n/a
487n/a if (zero == NULL) {
488n/a zero = PyLong_FromLong(0);
489n/a if (!zero)
490n/a return NULL;
491n/a }
492n/a
493n/a if (Py_TYPE(other) != &keyobject_type){
494n/a PyErr_Format(PyExc_TypeError, "other argument must be K instance");
495n/a return NULL;
496n/a }
497n/a compare = ((keyobject *) ko)->cmp;
498n/a assert(compare != NULL);
499n/a x = ((keyobject *) ko)->object;
500n/a y = ((keyobject *) other)->object;
501n/a if (!x || !y){
502n/a PyErr_Format(PyExc_AttributeError, "object");
503n/a return NULL;
504n/a }
505n/a
506n/a /* Call the user's comparison function and translate the 3-way
507n/a * result into true or false (or error).
508n/a */
509n/a stack[0] = x;
510n/a stack[1] = y;
511n/a res = _PyObject_FastCall(compare, stack, 2);
512n/a if (res == NULL) {
513n/a return NULL;
514n/a }
515n/a
516n/a answer = PyObject_RichCompare(res, zero, op);
517n/a Py_DECREF(res);
518n/a return answer;
519n/a}
520n/a
521n/astatic PyObject *
522n/afunctools_cmp_to_key(PyObject *self, PyObject *args, PyObject *kwds)
523n/a{
524n/a PyObject *cmp;
525n/a static char *kwargs[] = {"mycmp", NULL};
526n/a keyobject *object;
527n/a
528n/a if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:cmp_to_key", kwargs, &cmp))
529n/a return NULL;
530n/a object = PyObject_New(keyobject, &keyobject_type);
531n/a if (!object)
532n/a return NULL;
533n/a Py_INCREF(cmp);
534n/a object->cmp = cmp;
535n/a object->object = NULL;
536n/a return (PyObject *)object;
537n/a}
538n/a
539n/aPyDoc_STRVAR(functools_cmp_to_key_doc,
540n/a"Convert a cmp= function into a key= function.");
541n/a
542n/a/* reduce (used to be a builtin) ********************************************/
543n/a
544n/astatic PyObject *
545n/afunctools_reduce(PyObject *self, PyObject *args)
546n/a{
547n/a PyObject *seq, *func, *result = NULL, *it;
548n/a
549n/a if (!PyArg_UnpackTuple(args, "reduce", 2, 3, &func, &seq, &result))
550n/a return NULL;
551n/a if (result != NULL)
552n/a Py_INCREF(result);
553n/a
554n/a it = PyObject_GetIter(seq);
555n/a if (it == NULL) {
556n/a if (PyErr_ExceptionMatches(PyExc_TypeError))
557n/a PyErr_SetString(PyExc_TypeError,
558n/a "reduce() arg 2 must support iteration");
559n/a Py_XDECREF(result);
560n/a return NULL;
561n/a }
562n/a
563n/a if ((args = PyTuple_New(2)) == NULL)
564n/a goto Fail;
565n/a
566n/a for (;;) {
567n/a PyObject *op2;
568n/a
569n/a if (args->ob_refcnt > 1) {
570n/a Py_DECREF(args);
571n/a if ((args = PyTuple_New(2)) == NULL)
572n/a goto Fail;
573n/a }
574n/a
575n/a op2 = PyIter_Next(it);
576n/a if (op2 == NULL) {
577n/a if (PyErr_Occurred())
578n/a goto Fail;
579n/a break;
580n/a }
581n/a
582n/a if (result == NULL)
583n/a result = op2;
584n/a else {
585n/a PyTuple_SetItem(args, 0, result);
586n/a PyTuple_SetItem(args, 1, op2);
587n/a if ((result = PyEval_CallObject(func, args)) == NULL)
588n/a goto Fail;
589n/a }
590n/a }
591n/a
592n/a Py_DECREF(args);
593n/a
594n/a if (result == NULL)
595n/a PyErr_SetString(PyExc_TypeError,
596n/a "reduce() of empty sequence with no initial value");
597n/a
598n/a Py_DECREF(it);
599n/a return result;
600n/a
601n/aFail:
602n/a Py_XDECREF(args);
603n/a Py_XDECREF(result);
604n/a Py_DECREF(it);
605n/a return NULL;
606n/a}
607n/a
608n/aPyDoc_STRVAR(functools_reduce_doc,
609n/a"reduce(function, sequence[, initial]) -> value\n\
610n/a\n\
611n/aApply a function of two arguments cumulatively to the items of a sequence,\n\
612n/afrom left to right, so as to reduce the sequence to a single value.\n\
613n/aFor example, reduce(lambda x, y: x+y, [1, 2, 3, 4, 5]) calculates\n\
614n/a((((1+2)+3)+4)+5). If initial is present, it is placed before the items\n\
615n/aof the sequence in the calculation, and serves as a default when the\n\
616n/asequence is empty.");
617n/a
618n/a/* lru_cache object **********************************************************/
619n/a
620n/a/* this object is used delimit args and keywords in the cache keys */
621n/astatic PyObject *kwd_mark = NULL;
622n/a
623n/astruct lru_list_elem;
624n/astruct lru_cache_object;
625n/a
626n/atypedef struct lru_list_elem {
627n/a PyObject_HEAD
628n/a struct lru_list_elem *prev, *next; /* borrowed links */
629n/a Py_hash_t hash;
630n/a PyObject *key, *result;
631n/a} lru_list_elem;
632n/a
633n/astatic void
634n/alru_list_elem_dealloc(lru_list_elem *link)
635n/a{
636n/a _PyObject_GC_UNTRACK(link);
637n/a Py_XDECREF(link->key);
638n/a Py_XDECREF(link->result);
639n/a PyObject_GC_Del(link);
640n/a}
641n/a
642n/astatic int
643n/alru_list_elem_traverse(lru_list_elem *link, visitproc visit, void *arg)
644n/a{
645n/a Py_VISIT(link->key);
646n/a Py_VISIT(link->result);
647n/a return 0;
648n/a}
649n/a
650n/astatic int
651n/alru_list_elem_clear(lru_list_elem *link)
652n/a{
653n/a Py_CLEAR(link->key);
654n/a Py_CLEAR(link->result);
655n/a return 0;
656n/a}
657n/a
658n/astatic PyTypeObject lru_list_elem_type = {
659n/a PyVarObject_HEAD_INIT(&PyType_Type, 0)
660n/a "functools._lru_list_elem", /* tp_name */
661n/a sizeof(lru_list_elem), /* tp_basicsize */
662n/a 0, /* tp_itemsize */
663n/a /* methods */
664n/a (destructor)lru_list_elem_dealloc, /* tp_dealloc */
665n/a 0, /* tp_print */
666n/a 0, /* tp_getattr */
667n/a 0, /* tp_setattr */
668n/a 0, /* tp_reserved */
669n/a 0, /* tp_repr */
670n/a 0, /* tp_as_number */
671n/a 0, /* tp_as_sequence */
672n/a 0, /* tp_as_mapping */
673n/a 0, /* tp_hash */
674n/a 0, /* tp_call */
675n/a 0, /* tp_str */
676n/a 0, /* tp_getattro */
677n/a 0, /* tp_setattro */
678n/a 0, /* tp_as_buffer */
679n/a Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
680n/a 0, /* tp_doc */
681n/a (traverseproc)lru_list_elem_traverse, /* tp_traverse */
682n/a (inquiry)lru_list_elem_clear, /* tp_clear */
683n/a};
684n/a
685n/a
686n/atypedef PyObject *(*lru_cache_ternaryfunc)(struct lru_cache_object *, PyObject *, PyObject *);
687n/a
688n/atypedef struct lru_cache_object {
689n/a lru_list_elem root; /* includes PyObject_HEAD */
690n/a Py_ssize_t maxsize;
691n/a PyObject *maxsize_O;
692n/a PyObject *func;
693n/a lru_cache_ternaryfunc wrapper;
694n/a PyObject *cache;
695n/a PyObject *cache_info_type;
696n/a Py_ssize_t misses, hits;
697n/a int typed;
698n/a PyObject *dict;
699n/a int full;
700n/a} lru_cache_object;
701n/a
702n/astatic PyTypeObject lru_cache_type;
703n/a
704n/astatic PyObject *
705n/alru_cache_make_key(PyObject *args, PyObject *kwds, int typed)
706n/a{
707n/a PyObject *key, *keyword, *value;
708n/a Py_ssize_t key_size, pos, key_pos, kwds_size;
709n/a
710n/a /* short path, key will match args anyway, which is a tuple */
711n/a if (!typed && !kwds) {
712n/a Py_INCREF(args);
713n/a return args;
714n/a }
715n/a
716n/a kwds_size = kwds ? PyDict_GET_SIZE(kwds) : 0;
717n/a assert(kwds_size >= 0);
718n/a
719n/a key_size = PyTuple_GET_SIZE(args);
720n/a if (kwds_size)
721n/a key_size += kwds_size * 2 + 1;
722n/a if (typed)
723n/a key_size += PyTuple_GET_SIZE(args) + kwds_size;
724n/a
725n/a key = PyTuple_New(key_size);
726n/a if (key == NULL)
727n/a return NULL;
728n/a
729n/a key_pos = 0;
730n/a for (pos = 0; pos < PyTuple_GET_SIZE(args); ++pos) {
731n/a PyObject *item = PyTuple_GET_ITEM(args, pos);
732n/a Py_INCREF(item);
733n/a PyTuple_SET_ITEM(key, key_pos++, item);
734n/a }
735n/a if (kwds_size) {
736n/a Py_INCREF(kwd_mark);
737n/a PyTuple_SET_ITEM(key, key_pos++, kwd_mark);
738n/a for (pos = 0; PyDict_Next(kwds, &pos, &keyword, &value);) {
739n/a Py_INCREF(keyword);
740n/a PyTuple_SET_ITEM(key, key_pos++, keyword);
741n/a Py_INCREF(value);
742n/a PyTuple_SET_ITEM(key, key_pos++, value);
743n/a }
744n/a assert(key_pos == PyTuple_GET_SIZE(args) + kwds_size * 2 + 1);
745n/a }
746n/a if (typed) {
747n/a for (pos = 0; pos < PyTuple_GET_SIZE(args); ++pos) {
748n/a PyObject *item = (PyObject *)Py_TYPE(PyTuple_GET_ITEM(args, pos));
749n/a Py_INCREF(item);
750n/a PyTuple_SET_ITEM(key, key_pos++, item);
751n/a }
752n/a if (kwds_size) {
753n/a for (pos = 0; PyDict_Next(kwds, &pos, &keyword, &value);) {
754n/a PyObject *item = (PyObject *)Py_TYPE(value);
755n/a Py_INCREF(item);
756n/a PyTuple_SET_ITEM(key, key_pos++, item);
757n/a }
758n/a }
759n/a }
760n/a assert(key_pos == key_size);
761n/a return key;
762n/a}
763n/a
764n/astatic PyObject *
765n/auncached_lru_cache_wrapper(lru_cache_object *self, PyObject *args, PyObject *kwds)
766n/a{
767n/a PyObject *result = PyObject_Call(self->func, args, kwds);
768n/a if (!result)
769n/a return NULL;
770n/a self->misses++;
771n/a return result;
772n/a}
773n/a
774n/astatic PyObject *
775n/ainfinite_lru_cache_wrapper(lru_cache_object *self, PyObject *args, PyObject *kwds)
776n/a{
777n/a PyObject *result;
778n/a Py_hash_t hash;
779n/a PyObject *key = lru_cache_make_key(args, kwds, self->typed);
780n/a if (!key)
781n/a return NULL;
782n/a hash = PyObject_Hash(key);
783n/a if (hash == -1) {
784n/a Py_DECREF(key);
785n/a return NULL;
786n/a }
787n/a result = _PyDict_GetItem_KnownHash(self->cache, key, hash);
788n/a if (result) {
789n/a Py_INCREF(result);
790n/a self->hits++;
791n/a Py_DECREF(key);
792n/a return result;
793n/a }
794n/a if (PyErr_Occurred()) {
795n/a Py_DECREF(key);
796n/a return NULL;
797n/a }
798n/a result = PyObject_Call(self->func, args, kwds);
799n/a if (!result) {
800n/a Py_DECREF(key);
801n/a return NULL;
802n/a }
803n/a if (_PyDict_SetItem_KnownHash(self->cache, key, result, hash) < 0) {
804n/a Py_DECREF(result);
805n/a Py_DECREF(key);
806n/a return NULL;
807n/a }
808n/a Py_DECREF(key);
809n/a self->misses++;
810n/a return result;
811n/a}
812n/a
813n/astatic void
814n/alru_cache_extricate_link(lru_list_elem *link)
815n/a{
816n/a link->prev->next = link->next;
817n/a link->next->prev = link->prev;
818n/a}
819n/a
820n/astatic void
821n/alru_cache_append_link(lru_cache_object *self, lru_list_elem *link)
822n/a{
823n/a lru_list_elem *root = &self->root;
824n/a lru_list_elem *last = root->prev;
825n/a last->next = root->prev = link;
826n/a link->prev = last;
827n/a link->next = root;
828n/a}
829n/a
830n/astatic PyObject *
831n/abounded_lru_cache_wrapper(lru_cache_object *self, PyObject *args, PyObject *kwds)
832n/a{
833n/a lru_list_elem *link;
834n/a PyObject *key, *result;
835n/a Py_hash_t hash;
836n/a
837n/a key = lru_cache_make_key(args, kwds, self->typed);
838n/a if (!key)
839n/a return NULL;
840n/a hash = PyObject_Hash(key);
841n/a if (hash == -1) {
842n/a Py_DECREF(key);
843n/a return NULL;
844n/a }
845n/a link = (lru_list_elem *)_PyDict_GetItem_KnownHash(self->cache, key, hash);
846n/a if (link) {
847n/a lru_cache_extricate_link(link);
848n/a lru_cache_append_link(self, link);
849n/a self->hits++;
850n/a result = link->result;
851n/a Py_INCREF(result);
852n/a Py_DECREF(key);
853n/a return result;
854n/a }
855n/a if (PyErr_Occurred()) {
856n/a Py_DECREF(key);
857n/a return NULL;
858n/a }
859n/a result = PyObject_Call(self->func, args, kwds);
860n/a if (!result) {
861n/a Py_DECREF(key);
862n/a return NULL;
863n/a }
864n/a if (self->full && self->root.next != &self->root) {
865n/a /* Use the oldest item to store the new key and result. */
866n/a PyObject *oldkey, *oldresult, *popresult;
867n/a /* Extricate the oldest item. */
868n/a link = self->root.next;
869n/a lru_cache_extricate_link(link);
870n/a /* Remove it from the cache.
871n/a The cache dict holds one reference to the link,
872n/a and the linked list holds yet one reference to it. */
873n/a popresult = _PyDict_Pop_KnownHash(self->cache,
874n/a link->key, link->hash,
875n/a Py_None);
876n/a if (popresult == Py_None) {
877n/a /* Getting here means that this same key was added to the
878n/a cache while the lock was released. Since the link
879n/a update is already done, we need only return the
880n/a computed result and update the count of misses. */
881n/a Py_DECREF(popresult);
882n/a Py_DECREF(link);
883n/a Py_DECREF(key);
884n/a }
885n/a else if (popresult == NULL) {
886n/a lru_cache_append_link(self, link);
887n/a Py_DECREF(key);
888n/a Py_DECREF(result);
889n/a return NULL;
890n/a }
891n/a else {
892n/a Py_DECREF(popresult);
893n/a /* Keep a reference to the old key and old result to
894n/a prevent their ref counts from going to zero during the
895n/a update. That will prevent potentially arbitrary object
896n/a clean-up code (i.e. __del__) from running while we're
897n/a still adjusting the links. */
898n/a oldkey = link->key;
899n/a oldresult = link->result;
900n/a
901n/a link->hash = hash;
902n/a link->key = key;
903n/a link->result = result;
904n/a if (_PyDict_SetItem_KnownHash(self->cache, key, (PyObject *)link,
905n/a hash) < 0) {
906n/a Py_DECREF(link);
907n/a Py_DECREF(oldkey);
908n/a Py_DECREF(oldresult);
909n/a return NULL;
910n/a }
911n/a lru_cache_append_link(self, link);
912n/a Py_INCREF(result); /* for return */
913n/a Py_DECREF(oldkey);
914n/a Py_DECREF(oldresult);
915n/a }
916n/a } else {
917n/a /* Put result in a new link at the front of the queue. */
918n/a link = (lru_list_elem *)PyObject_GC_New(lru_list_elem,
919n/a &lru_list_elem_type);
920n/a if (link == NULL) {
921n/a Py_DECREF(key);
922n/a Py_DECREF(result);
923n/a return NULL;
924n/a }
925n/a
926n/a link->hash = hash;
927n/a link->key = key;
928n/a link->result = result;
929n/a _PyObject_GC_TRACK(link);
930n/a if (_PyDict_SetItem_KnownHash(self->cache, key, (PyObject *)link,
931n/a hash) < 0) {
932n/a Py_DECREF(link);
933n/a return NULL;
934n/a }
935n/a lru_cache_append_link(self, link);
936n/a Py_INCREF(result); /* for return */
937n/a self->full = (PyDict_GET_SIZE(self->cache) >= self->maxsize);
938n/a }
939n/a self->misses++;
940n/a return result;
941n/a}
942n/a
943n/astatic PyObject *
944n/alru_cache_new(PyTypeObject *type, PyObject *args, PyObject *kw)
945n/a{
946n/a PyObject *func, *maxsize_O, *cache_info_type, *cachedict;
947n/a int typed;
948n/a lru_cache_object *obj;
949n/a Py_ssize_t maxsize;
950n/a PyObject *(*wrapper)(lru_cache_object *, PyObject *, PyObject *);
951n/a static char *keywords[] = {"user_function", "maxsize", "typed",
952n/a "cache_info_type", NULL};
953n/a
954n/a if (!PyArg_ParseTupleAndKeywords(args, kw, "OOpO:lru_cache", keywords,
955n/a &func, &maxsize_O, &typed,
956n/a &cache_info_type)) {
957n/a return NULL;
958n/a }
959n/a
960n/a if (!PyCallable_Check(func)) {
961n/a PyErr_SetString(PyExc_TypeError,
962n/a "the first argument must be callable");
963n/a return NULL;
964n/a }
965n/a
966n/a /* select the caching function, and make/inc maxsize_O */
967n/a if (maxsize_O == Py_None) {
968n/a wrapper = infinite_lru_cache_wrapper;
969n/a /* use this only to initialize lru_cache_object attribute maxsize */
970n/a maxsize = -1;
971n/a } else if (PyIndex_Check(maxsize_O)) {
972n/a maxsize = PyNumber_AsSsize_t(maxsize_O, PyExc_OverflowError);
973n/a if (maxsize == -1 && PyErr_Occurred())
974n/a return NULL;
975n/a if (maxsize == 0)
976n/a wrapper = uncached_lru_cache_wrapper;
977n/a else
978n/a wrapper = bounded_lru_cache_wrapper;
979n/a } else {
980n/a PyErr_SetString(PyExc_TypeError, "maxsize should be integer or None");
981n/a return NULL;
982n/a }
983n/a
984n/a if (!(cachedict = PyDict_New()))
985n/a return NULL;
986n/a
987n/a obj = (lru_cache_object *)type->tp_alloc(type, 0);
988n/a if (obj == NULL) {
989n/a Py_DECREF(cachedict);
990n/a return NULL;
991n/a }
992n/a
993n/a obj->cache = cachedict;
994n/a obj->root.prev = &obj->root;
995n/a obj->root.next = &obj->root;
996n/a obj->maxsize = maxsize;
997n/a Py_INCREF(maxsize_O);
998n/a obj->maxsize_O = maxsize_O;
999n/a Py_INCREF(func);
1000n/a obj->func = func;
1001n/a obj->wrapper = wrapper;
1002n/a obj->misses = obj->hits = 0;
1003n/a obj->typed = typed;
1004n/a Py_INCREF(cache_info_type);
1005n/a obj->cache_info_type = cache_info_type;
1006n/a
1007n/a return (PyObject *)obj;
1008n/a}
1009n/a
1010n/astatic lru_list_elem *
1011n/alru_cache_unlink_list(lru_cache_object *self)
1012n/a{
1013n/a lru_list_elem *root = &self->root;
1014n/a lru_list_elem *link = root->next;
1015n/a if (link == root)
1016n/a return NULL;
1017n/a root->prev->next = NULL;
1018n/a root->next = root->prev = root;
1019n/a return link;
1020n/a}
1021n/a
1022n/astatic void
1023n/alru_cache_clear_list(lru_list_elem *link)
1024n/a{
1025n/a while (link != NULL) {
1026n/a lru_list_elem *next = link->next;
1027n/a Py_DECREF(link);
1028n/a link = next;
1029n/a }
1030n/a}
1031n/a
1032n/astatic void
1033n/alru_cache_dealloc(lru_cache_object *obj)
1034n/a{
1035n/a lru_list_elem *list = lru_cache_unlink_list(obj);
1036n/a Py_XDECREF(obj->maxsize_O);
1037n/a Py_XDECREF(obj->func);
1038n/a Py_XDECREF(obj->cache);
1039n/a Py_XDECREF(obj->dict);
1040n/a Py_XDECREF(obj->cache_info_type);
1041n/a lru_cache_clear_list(list);
1042n/a Py_TYPE(obj)->tp_free(obj);
1043n/a}
1044n/a
1045n/astatic PyObject *
1046n/alru_cache_call(lru_cache_object *self, PyObject *args, PyObject *kwds)
1047n/a{
1048n/a return self->wrapper(self, args, kwds);
1049n/a}
1050n/a
1051n/astatic PyObject *
1052n/alru_cache_descr_get(PyObject *self, PyObject *obj, PyObject *type)
1053n/a{
1054n/a if (obj == Py_None || obj == NULL) {
1055n/a Py_INCREF(self);
1056n/a return self;
1057n/a }
1058n/a return PyMethod_New(self, obj);
1059n/a}
1060n/a
1061n/astatic PyObject *
1062n/alru_cache_cache_info(lru_cache_object *self, PyObject *unused)
1063n/a{
1064n/a return PyObject_CallFunction(self->cache_info_type, "nnOn",
1065n/a self->hits, self->misses, self->maxsize_O,
1066n/a PyDict_GET_SIZE(self->cache));
1067n/a}
1068n/a
1069n/astatic PyObject *
1070n/alru_cache_cache_clear(lru_cache_object *self, PyObject *unused)
1071n/a{
1072n/a lru_list_elem *list = lru_cache_unlink_list(self);
1073n/a self->hits = self->misses = 0;
1074n/a self->full = 0;
1075n/a PyDict_Clear(self->cache);
1076n/a lru_cache_clear_list(list);
1077n/a Py_RETURN_NONE;
1078n/a}
1079n/a
1080n/astatic PyObject *
1081n/alru_cache_reduce(PyObject *self, PyObject *unused)
1082n/a{
1083n/a return PyObject_GetAttrString(self, "__qualname__");
1084n/a}
1085n/a
1086n/astatic PyObject *
1087n/alru_cache_copy(PyObject *self, PyObject *unused)
1088n/a{
1089n/a Py_INCREF(self);
1090n/a return self;
1091n/a}
1092n/a
1093n/astatic PyObject *
1094n/alru_cache_deepcopy(PyObject *self, PyObject *unused)
1095n/a{
1096n/a Py_INCREF(self);
1097n/a return self;
1098n/a}
1099n/a
1100n/astatic int
1101n/alru_cache_tp_traverse(lru_cache_object *self, visitproc visit, void *arg)
1102n/a{
1103n/a lru_list_elem *link = self->root.next;
1104n/a while (link != &self->root) {
1105n/a lru_list_elem *next = link->next;
1106n/a Py_VISIT(link);
1107n/a link = next;
1108n/a }
1109n/a Py_VISIT(self->maxsize_O);
1110n/a Py_VISIT(self->func);
1111n/a Py_VISIT(self->cache);
1112n/a Py_VISIT(self->cache_info_type);
1113n/a Py_VISIT(self->dict);
1114n/a return 0;
1115n/a}
1116n/a
1117n/astatic int
1118n/alru_cache_tp_clear(lru_cache_object *self)
1119n/a{
1120n/a lru_list_elem *list = lru_cache_unlink_list(self);
1121n/a Py_CLEAR(self->maxsize_O);
1122n/a Py_CLEAR(self->func);
1123n/a Py_CLEAR(self->cache);
1124n/a Py_CLEAR(self->cache_info_type);
1125n/a Py_CLEAR(self->dict);
1126n/a lru_cache_clear_list(list);
1127n/a return 0;
1128n/a}
1129n/a
1130n/a
1131n/aPyDoc_STRVAR(lru_cache_doc,
1132n/a"Create a cached callable that wraps another function.\n\
1133n/a\n\
1134n/auser_function: the function being cached\n\
1135n/a\n\
1136n/amaxsize: 0 for no caching\n\
1137n/a None for unlimited cache size\n\
1138n/a n for a bounded cache\n\
1139n/a\n\
1140n/atyped: False cache f(3) and f(3.0) as identical calls\n\
1141n/a True cache f(3) and f(3.0) as distinct calls\n\
1142n/a\n\
1143n/acache_info_type: namedtuple class with the fields:\n\
1144n/a hits misses currsize maxsize\n"
1145n/a);
1146n/a
1147n/astatic PyMethodDef lru_cache_methods[] = {
1148n/a {"cache_info", (PyCFunction)lru_cache_cache_info, METH_NOARGS},
1149n/a {"cache_clear", (PyCFunction)lru_cache_cache_clear, METH_NOARGS},
1150n/a {"__reduce__", (PyCFunction)lru_cache_reduce, METH_NOARGS},
1151n/a {"__copy__", (PyCFunction)lru_cache_copy, METH_VARARGS},
1152n/a {"__deepcopy__", (PyCFunction)lru_cache_deepcopy, METH_VARARGS},
1153n/a {NULL}
1154n/a};
1155n/a
1156n/astatic PyGetSetDef lru_cache_getsetlist[] = {
1157n/a {"__dict__", PyObject_GenericGetDict, PyObject_GenericSetDict},
1158n/a {NULL}
1159n/a};
1160n/a
1161n/astatic PyTypeObject lru_cache_type = {
1162n/a PyVarObject_HEAD_INIT(NULL, 0)
1163n/a "functools._lru_cache_wrapper", /* tp_name */
1164n/a sizeof(lru_cache_object), /* tp_basicsize */
1165n/a 0, /* tp_itemsize */
1166n/a /* methods */
1167n/a (destructor)lru_cache_dealloc, /* tp_dealloc */
1168n/a 0, /* tp_print */
1169n/a 0, /* tp_getattr */
1170n/a 0, /* tp_setattr */
1171n/a 0, /* tp_reserved */
1172n/a 0, /* tp_repr */
1173n/a 0, /* tp_as_number */
1174n/a 0, /* tp_as_sequence */
1175n/a 0, /* tp_as_mapping */
1176n/a 0, /* tp_hash */
1177n/a (ternaryfunc)lru_cache_call, /* tp_call */
1178n/a 0, /* tp_str */
1179n/a 0, /* tp_getattro */
1180n/a 0, /* tp_setattro */
1181n/a 0, /* tp_as_buffer */
1182n/a Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_HAVE_GC,
1183n/a /* tp_flags */
1184n/a lru_cache_doc, /* tp_doc */
1185n/a (traverseproc)lru_cache_tp_traverse,/* tp_traverse */
1186n/a (inquiry)lru_cache_tp_clear, /* tp_clear */
1187n/a 0, /* tp_richcompare */
1188n/a 0, /* tp_weaklistoffset */
1189n/a 0, /* tp_iter */
1190n/a 0, /* tp_iternext */
1191n/a lru_cache_methods, /* tp_methods */
1192n/a 0, /* tp_members */
1193n/a lru_cache_getsetlist, /* tp_getset */
1194n/a 0, /* tp_base */
1195n/a 0, /* tp_dict */
1196n/a lru_cache_descr_get, /* tp_descr_get */
1197n/a 0, /* tp_descr_set */
1198n/a offsetof(lru_cache_object, dict), /* tp_dictoffset */
1199n/a 0, /* tp_init */
1200n/a 0, /* tp_alloc */
1201n/a lru_cache_new, /* tp_new */
1202n/a};
1203n/a
1204n/a/* module level code ********************************************************/
1205n/a
1206n/aPyDoc_STRVAR(module_doc,
1207n/a"Tools that operate on functions.");
1208n/a
1209n/astatic PyMethodDef module_methods[] = {
1210n/a {"reduce", functools_reduce, METH_VARARGS, functools_reduce_doc},
1211n/a {"cmp_to_key", (PyCFunction)functools_cmp_to_key,
1212n/a METH_VARARGS | METH_KEYWORDS, functools_cmp_to_key_doc},
1213n/a {NULL, NULL} /* sentinel */
1214n/a};
1215n/a
1216n/astatic void
1217n/amodule_free(void *m)
1218n/a{
1219n/a Py_CLEAR(kwd_mark);
1220n/a}
1221n/a
1222n/astatic struct PyModuleDef _functoolsmodule = {
1223n/a PyModuleDef_HEAD_INIT,
1224n/a "_functools",
1225n/a module_doc,
1226n/a -1,
1227n/a module_methods,
1228n/a NULL,
1229n/a NULL,
1230n/a NULL,
1231n/a module_free,
1232n/a};
1233n/a
1234n/aPyMODINIT_FUNC
1235n/aPyInit__functools(void)
1236n/a{
1237n/a int i;
1238n/a PyObject *m;
1239n/a char *name;
1240n/a PyTypeObject *typelist[] = {
1241n/a &partial_type,
1242n/a &lru_cache_type,
1243n/a NULL
1244n/a };
1245n/a
1246n/a m = PyModule_Create(&_functoolsmodule);
1247n/a if (m == NULL)
1248n/a return NULL;
1249n/a
1250n/a kwd_mark = _PyObject_CallNoArg((PyObject *)&PyBaseObject_Type);
1251n/a if (!kwd_mark) {
1252n/a Py_DECREF(m);
1253n/a return NULL;
1254n/a }
1255n/a
1256n/a for (i=0 ; typelist[i] != NULL ; i++) {
1257n/a if (PyType_Ready(typelist[i]) < 0) {
1258n/a Py_DECREF(m);
1259n/a return NULL;
1260n/a }
1261n/a name = strchr(typelist[i]->tp_name, '.');
1262n/a assert (name != NULL);
1263n/a Py_INCREF(typelist[i]);
1264n/a PyModule_AddObject(m, name+1, (PyObject *)typelist[i]);
1265n/a }
1266n/a return m;
1267n/a}