root/masterdriverz/snakeoil-formatters/src/compatibility.c @ ferringb%2540gmail.com-20070429202721-8mqijyr56t6ntz7w

Revision ferringb%2540gmail.com-20070429202721-8mqijyr56t6ntz7w, 8.0 kB (checked in by Brian Harring <ferringb@…>, 21 months ago)

set of changes; move _functoolmodules to _compatibility, pull in py2.5's any/all, slave compatibility to that, tweak test_compatibility a bit so it's slightly saner in terms of not doing repeated/wasteful tests

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