| 1 |
|
|---|
| 2 | #include "Python.h"
|
|---|
| 3 | #include "structmember.h"
|
|---|
| 4 |
|
|---|
| 5 | /* _functools module written and maintained
|
|---|
| 6 | by Hye-Shik Chang <[email protected]>
|
|---|
| 7 | with adaptations by Raymond Hettinger <[email protected]>
|
|---|
| 8 | Copyright (c) 2004, 2005, 2006 Python Software Foundation.
|
|---|
| 9 | All rights reserved.
|
|---|
| 10 | */
|
|---|
| 11 |
|
|---|
| 12 | /* partial object **********************************************************/
|
|---|
| 13 |
|
|---|
| 14 | typedef struct {
|
|---|
| 15 | PyObject_HEAD
|
|---|
| 16 | PyObject *fn;
|
|---|
| 17 | PyObject *args;
|
|---|
| 18 | PyObject *kw;
|
|---|
| 19 | PyObject *dict;
|
|---|
| 20 | PyObject *weakreflist; /* List of weak references */
|
|---|
| 21 | } partialobject;
|
|---|
| 22 |
|
|---|
| 23 | static PyTypeObject partial_type;
|
|---|
| 24 |
|
|---|
| 25 | static PyObject *
|
|---|
| 26 | partial_new(PyTypeObject *type, PyObject *args, PyObject *kw)
|
|---|
| 27 | {
|
|---|
| 28 | PyObject *func;
|
|---|
| 29 | partialobject *pto;
|
|---|
| 30 |
|
|---|
| 31 | if (PyTuple_GET_SIZE(args) < 1) {
|
|---|
| 32 | PyErr_SetString(PyExc_TypeError,
|
|---|
| 33 | "type 'partial' takes at least one argument");
|
|---|
| 34 | return NULL;
|
|---|
| 35 | }
|
|---|
| 36 |
|
|---|
| 37 | func = PyTuple_GET_ITEM(args, 0);
|
|---|
| 38 | if (!PyCallable_Check(func)) {
|
|---|
| 39 | PyErr_SetString(PyExc_TypeError,
|
|---|
| 40 | "the first argument must be callable");
|
|---|
| 41 | return NULL;
|
|---|
| 42 | }
|
|---|
| 43 |
|
|---|
| 44 | /* create partialobject structure */
|
|---|
| 45 | pto = (partialobject *)type->tp_alloc(type, 0);
|
|---|
| 46 | if (pto == NULL)
|
|---|
| 47 | return NULL;
|
|---|
| 48 |
|
|---|
| 49 | pto->fn = func;
|
|---|
| 50 | Py_INCREF(func);
|
|---|
| 51 | pto->args = PyTuple_GetSlice(args, 1, PY_SSIZE_T_MAX);
|
|---|
| 52 | if (pto->args == NULL) {
|
|---|
| 53 | pto->kw = NULL;
|
|---|
| 54 | Py_DECREF(pto);
|
|---|
| 55 | return NULL;
|
|---|
| 56 | }
|
|---|
| 57 | if (kw != NULL) {
|
|---|
| 58 | pto->kw = PyDict_Copy(kw);
|
|---|
| 59 | if (pto->kw == NULL) {
|
|---|
| 60 | Py_DECREF(pto);
|
|---|
| 61 | return NULL;
|
|---|
| 62 | }
|
|---|
| 63 | } else {
|
|---|
| 64 | pto->kw = Py_None;
|
|---|
| 65 | Py_INCREF(Py_None);
|
|---|
| 66 | }
|
|---|
| 67 |
|
|---|
| 68 | pto->weakreflist = NULL;
|
|---|
| 69 | pto->dict = NULL;
|
|---|
| 70 |
|
|---|
| 71 | return (PyObject *)pto;
|
|---|
| 72 | }
|
|---|
| 73 |
|
|---|
| 74 | static void
|
|---|
| 75 | partial_dealloc(partialobject *pto)
|
|---|
| 76 | {
|
|---|
| 77 | PyObject_GC_UnTrack(pto);
|
|---|
| 78 | if (pto->weakreflist != NULL)
|
|---|
| 79 | PyObject_ClearWeakRefs((PyObject *) pto);
|
|---|
| 80 | Py_XDECREF(pto->fn);
|
|---|
| 81 | Py_XDECREF(pto->args);
|
|---|
| 82 | Py_XDECREF(pto->kw);
|
|---|
| 83 | Py_XDECREF(pto->dict);
|
|---|
| 84 | pto->ob_type->tp_free(pto);
|
|---|
| 85 | }
|
|---|
| 86 |
|
|---|
| 87 | static PyObject *
|
|---|
| 88 | partial_call(partialobject *pto, PyObject *args, PyObject *kw)
|
|---|
| 89 | {
|
|---|
| 90 | PyObject *ret;
|
|---|
| 91 | PyObject *argappl = NULL, *kwappl = NULL;
|
|---|
| 92 |
|
|---|
| 93 | assert (PyCallable_Check(pto->fn));
|
|---|
| 94 | assert (PyTuple_Check(pto->args));
|
|---|
| 95 | assert (pto->kw == Py_None || PyDict_Check(pto->kw));
|
|---|
| 96 |
|
|---|
| 97 | if (PyTuple_GET_SIZE(pto->args) == 0) {
|
|---|
| 98 | argappl = args;
|
|---|
| 99 | Py_INCREF(args);
|
|---|
| 100 | } else if (PyTuple_GET_SIZE(args) == 0) {
|
|---|
| 101 | argappl = pto->args;
|
|---|
| 102 | Py_INCREF(pto->args);
|
|---|
| 103 | } else {
|
|---|
| 104 | argappl = PySequence_Concat(pto->args, args);
|
|---|
| 105 | if (argappl == NULL)
|
|---|
| 106 | return NULL;
|
|---|
| 107 | }
|
|---|
| 108 |
|
|---|
| 109 | if (pto->kw == Py_None) {
|
|---|
| 110 | kwappl = kw;
|
|---|
| 111 | Py_XINCREF(kw);
|
|---|
| 112 | } else {
|
|---|
| 113 | kwappl = PyDict_Copy(pto->kw);
|
|---|
| 114 | if (kwappl == NULL) {
|
|---|
| 115 | Py_DECREF(argappl);
|
|---|
| 116 | return NULL;
|
|---|
| 117 | }
|
|---|
| 118 | if (kw != NULL) {
|
|---|
| 119 | if (PyDict_Merge(kwappl, kw, 1) != 0) {
|
|---|
| 120 | Py_DECREF(argappl);
|
|---|
| 121 | Py_DECREF(kwappl);
|
|---|
| 122 | return NULL;
|
|---|
| 123 | }
|
|---|
| 124 | }
|
|---|
|
|---|