3 #include "structmember.h"
5 /* _functools module written and maintained
6 by Hye-Shik Chang <perky@FreeBSD.org>
7 with adaptations by Raymond Hettinger <python@rcn.com>
8 Copyright (c) 2004, 2005, 2006 Python Software Foundation.
12 /* partial object **********************************************************/
20 PyObject
*weakreflist
; /* List of weak references */
23 static PyTypeObject partial_type
;
26 partial_new(PyTypeObject
*type
, PyObject
*args
, PyObject
*kw
)
31 if (PyTuple_GET_SIZE(args
) < 1) {
32 PyErr_SetString(PyExc_TypeError
,
33 "type 'partial' takes at least one argument");
37 func
= PyTuple_GET_ITEM(args
, 0);
38 if (!PyCallable_Check(func
)) {
39 PyErr_SetString(PyExc_TypeError
,
40 "the first argument must be callable");
44 /* create partialobject structure */
45 pto
= (partialobject
*)type
->tp_alloc(type
, 0);
51 pto
->args
= PyTuple_GetSlice(args
, 1, PY_SSIZE_T_MAX
);
52 if (pto
->args
== NULL
) {
58 pto
->kw
= PyDict_Copy(kw
);
59 if (pto
->kw
== NULL
) {
68 pto
->weakreflist
= NULL
;
71 return (PyObject
*)pto
;
75 partial_dealloc(partialobject
*pto
)
77 PyObject_GC_UnTrack(pto
);
78 if (pto
->weakreflist
!= NULL
)
79 PyObject_ClearWeakRefs((PyObject
*) pto
);
81 Py_XDECREF(pto
->args
);
83 Py_XDECREF(pto
->dict
);
84 Py_TYPE(pto
)->tp_free(pto
);
88 partial_call(partialobject
*pto
, PyObject
*args
, PyObject
*kw
)
91 PyObject
*argappl
= NULL
, *kwappl
= NULL
;
93 assert (PyCallable_Check(pto
->fn
));
94 assert (PyTuple_Check(pto
->args
));
95 assert (pto
->kw
== Py_None
|| PyDict_Check(pto
->kw
));
97 if (PyTuple_GET_SIZE(pto
->args
) == 0) {
100 } else if (PyTuple_GET_SIZE(args
) == 0) {
102 Py_INCREF(pto
->args
);
104 argappl
= PySequence_Concat(pto
->args
, args
);
109 if (pto
->kw
== Py_None
) {
113 kwappl
= PyDict_Copy(pto
->kw
);
114 if (kwappl
== NULL
) {
119 if (PyDict_Merge(kwappl
, kw
, 1) != 0) {
127 ret
= PyObject_Call(pto
->fn
, argappl
, kwappl
);
134 partial_traverse(partialobject
*pto
, visitproc visit
, void *arg
)
143 PyDoc_STRVAR(partial_doc
,
144 "partial(func, *args, **keywords) - new function with partial application\n\
145 of the given arguments and keywords.\n");
147 #define OFF(x) offsetof(partialobject, x)
148 static PyMemberDef partial_memberlist
[] = {
149 {"func", T_OBJECT
, OFF(fn
), READONLY
,
150 "function object to use in future partial calls"},
151 {"args", T_OBJECT
, OFF(args
), READONLY
,
152 "tuple of arguments to future partial calls"},
153 {"keywords", T_OBJECT
, OFF(kw
), READONLY
,
154 "dictionary of keyword arguments to future partial calls"},
155 {NULL
} /* Sentinel */
159 partial_get_dict(partialobject
*pto
)
161 if (pto
->dict
== NULL
) {
162 pto
->dict
= PyDict_New();
163 if (pto
->dict
== NULL
)
166 Py_INCREF(pto
->dict
);
171 partial_set_dict(partialobject
*pto
, PyObject
*value
)
175 /* It is illegal to del p.__dict__ */
177 PyErr_SetString(PyExc_TypeError
,
178 "a partial object's dictionary may not be deleted");
181 /* Can only set __dict__ to a dictionary */
182 if (!PyDict_Check(value
)) {
183 PyErr_SetString(PyExc_TypeError
,
184 "setting partial object's dictionary to a non-dict");
194 static PyGetSetDef partial_getsetlist
[] = {
195 {"__dict__", (getter
)partial_get_dict
, (setter
)partial_set_dict
},
196 {NULL
} /* Sentinel */
199 static PyTypeObject partial_type
= {
200 PyVarObject_HEAD_INIT(NULL
, 0)
201 "functools.partial", /* tp_name */
202 sizeof(partialobject
), /* tp_basicsize */
205 (destructor
)partial_dealloc
, /* tp_dealloc */
211 0, /* tp_as_number */
212 0, /* tp_as_sequence */
213 0, /* tp_as_mapping */
215 (ternaryfunc
)partial_call
, /* tp_call */
217 PyObject_GenericGetAttr
, /* tp_getattro */
218 PyObject_GenericSetAttr
, /* tp_setattro */
219 0, /* tp_as_buffer */
220 Py_TPFLAGS_DEFAULT
| Py_TPFLAGS_HAVE_GC
|
221 Py_TPFLAGS_BASETYPE
| Py_TPFLAGS_HAVE_WEAKREFS
, /* tp_flags */
222 partial_doc
, /* tp_doc */
223 (traverseproc
)partial_traverse
, /* tp_traverse */
225 0, /* tp_richcompare */
226 offsetof(partialobject
, weakreflist
), /* tp_weaklistoffset */
230 partial_memberlist
, /* tp_members */
231 partial_getsetlist
, /* tp_getset */
234 0, /* tp_descr_get */
235 0, /* tp_descr_set */
236 offsetof(partialobject
, dict
), /* tp_dictoffset */
239 partial_new
, /* tp_new */
240 PyObject_GC_Del
, /* tp_free */
244 /* module level code ********************************************************/
246 PyDoc_STRVAR(module_doc
,
247 "Tools that operate on functions.");
249 static PyMethodDef module_methods
[] = {
250 {NULL
, NULL
} /* sentinel */
259 PyTypeObject
*typelist
[] = {
264 m
= Py_InitModule3("_functools", module_methods
, module_doc
);
268 for (i
=0 ; typelist
[i
] != NULL
; i
++) {
269 if (PyType_Ready(typelist
[i
]) < 0)
271 name
= strchr(typelist
[i
]->tp_name
, '.');
272 assert (name
!= NULL
);
273 Py_INCREF(typelist
[i
]);
274 PyModule_AddObject(m
, name
+1, (PyObject
*)typelist
[i
]);