root/releases/pkgcore/0.2.1/src/functoolsmodule.c @ marienz%2540gentoo.org-20061119201324-2fb0008e4120bac2

Revision marienz%2540gentoo.org-20061119201324-2fb0008e4120bac2, 6.3 KB (checked in by Marien Zwart <marienz@…>, 2 years ago)

Move everything from src/extensions to src/

Line 
1
2#include "Python.h"
3#include "structmember.h"
4
5#include "py24-compatibility.h"
6
7/* _functools module written and maintained
8   by Hye-Shik Chang <perky@FreeBSD.org>
9   with adaptations by Raymond Hettinger <python@rcn.com>
10   Copyright (c) 2004, 2005, 2006 Python Software Foundation.
11   All rights reserved.
12*/
13
14/* partial object **********************************************************/
15
16typedef struct {
17        PyObject_HEAD
18        PyObject *fn;
19        PyObject *args;
20        PyObject *kw;
21        PyObject *dict;
22        PyObject *weakreflist; /* List of weak references */
23} partialobject;
24
25static PyTypeObject partial_type;
26
27static PyObject *
28partial_new(PyTypeObject *type, PyObject *args, PyObject *kw)
29{
30        PyObject *func;
31        partialobject *pto;
32
33        if (PyTuple_GET_SIZE(args) < 1) {
34                PyErr_SetString(PyExc_TypeError,
35                                "type 'partial' takes at least one argument");
36                return NULL;
37        }
38
39        func = PyTuple_GET_ITEM(args, 0);
40        if (!PyCallable_Check(func)) {
41                PyErr_SetString(PyExc_TypeError,
42                                "the first argument must be callable");
43                return NULL;
44        }
45
46        /* create partialobject structure */
47        pto = (partialobject *)type->tp_alloc(type, 0);
48        if (pto == NULL)
49                return NULL;
50
51        pto->fn = func;
52        Py_INCREF(func);
53        pto->args = PyTuple_GetSlice(args, 1, PY_SSIZE_T_MAX);
54        if (pto->args == NULL) {
55                pto->kw = NULL;
56                Py_DECREF(pto);
57                return NULL;
58        }
59        if (kw != NULL) {
60                pto->kw = PyDict_Copy(kw);
61                if (pto->kw == NULL) {
62                        Py_DECREF(pto);
63                        return NULL;
64                }
65        } else {
66                pto->kw = Py_None;
67                Py_INCREF(Py_None);
68        }
69
70        pto->weakreflist = NULL;
71        pto->dict = NULL;
72
73        return (PyObject *)pto;
74}
75
76static void
77partial_dealloc(partialobject *pto)
78{
79        PyObject_GC_UnTrack(pto);
80        if (pto->weakreflist != NULL)
81                PyObject_ClearWeakRefs((PyObject *) pto);
82        Py_XDECREF(pto->fn);
83        Py_XDECREF(pto->args);
84        Py_XDECREF(pto->kw);
85        Py_XDECREF(pto->dict);
86        pto->ob_type->tp_free(pto);
87}
88
89static PyObject *
90partial_call(partialobject *pto, PyObject *args, PyObject *kw)
91{
92        PyObject *ret;
93        PyObject *argappl = NULL, *kwappl = NULL;
94
95        assert (PyCallable_Check(pto->fn));
96        assert (PyTuple_Check(pto->args));
97        assert (pto->kw == Py_None  ||  PyDict_Check(pto->kw));
98
99        if (PyTuple_GET_SIZE(pto->args) == 0) {
100                argappl = args;
101                Py_INCREF(args);
102        } else if (PyTuple_GET_SIZE(args) == 0) {
103                argappl = pto->args;
104                Py_INCREF(pto->args);
105        } else {
106                argappl = PySequence_Concat(pto->args, args);
107                if (argappl == NULL)
108                        return NULL;
109        }
110
111        if (pto->kw == Py_None) {
112                kwappl = kw;
113                Py_XINCREF(kw);
114        } else {
115                kwappl = PyDict_Copy(pto->kw);
116                if (kwappl == NULL) {
117                        Py_DECREF(argappl);
118                        return NULL;
119                }
120                if (kw != NULL) {
121                        if (PyDict_Merge(kwappl, kw, 1) != 0) {
122                                Py_DECREF(argappl);
123                                Py_DECREF(kwappl);
124                                return NULL;
125                        }
126                }
127        }
128
129        ret = PyObject_Call(pto->fn, argappl, kwappl);
130        Py_DECREF(argappl);
131        Py_XDECREF(kwappl);
132        return ret;
133}
134
135static int
136partial_traverse(partialobject *pto, visitproc visit, void *arg)
137{
138        Py_VISIT(pto->fn);
139        Py_VISIT(pto->args);
140        Py_VISIT(pto->kw);
141        Py_VISIT(pto->dict);
142        return 0;
143}
144
145PyDoc_STRVAR(partial_doc,
146"partial(func, *args, **keywords) - new function with partial application\n\
147        of the given arguments and keywords.\n");
148
149#define OFF(x) offsetof(partialobject, x)
150static PyMemberDef partial_memberlist[] = {
151        {"func",        T_OBJECT,       OFF(fn),        READONLY,
152         "function object to use in future partial calls"},
153        {"args",        T_OBJECT,       OFF(args),      READONLY,
154         "tuple of arguments to future partial calls"},
155        {"keywords",    T_OBJECT,       OFF(kw),        READONLY,
156         "dictionary of keyword arguments to future partial calls"},
157        {NULL}  /* Sentinel */
158};
159
160static PyObject *
161partial_get_dict(partialobject *pto)
162{
163        if (pto->dict == NULL) {
164                pto->dict = PyDict_New();
165                if (pto->dict == NULL)
166                        return NULL;
167        }
168        Py_INCREF(pto->dict);
169        return pto->dict;
170}
171
172static int
173partial_set_dict(partialobject *pto, PyObject *value)
174{
175        PyObject *tmp;
176
177        /* It is illegal to del p.__dict__ */
178        if (value == NULL) {
179                PyErr_SetString(PyExc_TypeError,
180                                "a partial object's dictionary may not be deleted");
181                return -1;
182        }
183        /* Can only set __dict__ to a dictionary */
184        if (!PyDict_Check(value)) {
185                PyErr_SetString(PyExc_TypeError,
186                                "setting partial object's dictionary to a non-dict");
187                return -1;
188        }
189        tmp = pto->dict;
190        Py_INCREF(value);
191        pto->dict = value;
192        Py_XDECREF(tmp);
193        return 0;
194}
195
196static PyGetSetDef partial_getsetlist[] = {
197        {"__dict__", (getter)partial_get_dict, (setter)partial_set_dict},
198        {NULL} /* Sentinel */
199};
200
201static PyTypeObject partial_type = {
202        PyObject_HEAD_INIT(NULL)
203        0,                              /* ob_size */
204        "functools.partial",            /* tp_name */
205        sizeof(partialobject),          /* tp_basicsize */
206        0,                              /* tp_itemsize */
207        /* methods */
208        (destructor)partial_dealloc,    /* tp_dealloc */
209        0,                              /* tp_print */
210        0,                              /* tp_getattr */
211        0,                              /* tp_setattr */
212        0,                              /* tp_compare */
213        0,                              /* tp_repr */
214        0,                              /* tp_as_number */
215        0,                              /* tp_as_sequence */
216        0,                              /* tp_as_mapping */
217        0,                              /* tp_hash */
218        (ternaryfunc)partial_call,      /* tp_call */
219        0,                              /* tp_str */
220        PyObject_GenericGetAttr,        /* tp_getattro */
221        PyObject_GenericSetAttr,        /* tp_setattro */
222        0,                              /* tp_as_buffer */
223        Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
224                Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
225        partial_doc,                    /* tp_doc */
226        (traverseproc)partial_traverse, /* tp_traverse */
227        0,                              /* tp_clear */
228        0,                              /* tp_richcompare */
229        offsetof(partialobject, weakreflist),   /* tp_weaklistoffset */
230        0,                              /* tp_iter */
231        0,                              /* tp_iternext */
232        0,                              /* tp_methods */
233        partial_memberlist,             /* tp_members */
234        partial_getsetlist,             /* tp_getset */
235        0,                              /* tp_base */
236        0,                              /* tp_dict */
237        0,                              /* tp_descr_get */
238        0,                              /* tp_descr_set */
239        offsetof(partialobject, dict),  /* tp_dictoffset */
240        0,                              /* tp_init */
241        0,                              /* tp_alloc */
242        partial_new,                    /* tp_new */
243        PyObject_GC_Del,                /* tp_free */
244};
245
246
247/* module level code ********************************************************/
248
249PyDoc_STRVAR(module_doc,
250"Tools that operate on functions.");
251
252static PyMethodDef module_methods[] = {
253        {NULL,          NULL}           /* sentinel */
254};
255
256PyMODINIT_FUNC
257init_functools(void)
258{
259        int i;
260        PyObject *m;
261        char *name;
262        PyTypeObject *typelist[] = {
263                &partial_type,
264                NULL
265        };
266
267        m = Py_InitModule3("_functools", module_methods, module_doc);
268        if (m == NULL)
269                return;
270
271        for (i=0 ; typelist[i] != NULL ; i++) {
272                if (PyType_Ready(typelist[i]) < 0)
273                        return;
274                name = strchr(typelist[i]->tp_name, '.');
275                assert (name != NULL);
276                Py_INCREF(typelist[i]);
277                PyModule_AddObject(m, name+1, (PyObject *)typelist[i]);
278        }
279}
Note: See TracBrowser for help on using the browser.