Mercurial > cpython-lru_cache-weakref
view Modules/_functoolsmodule.c @ 49955:878d40468c4e legacy-trunk
Issue #4384: Added logging integration with warnings module using captureWarnings(). This change includes a NullHandler which does nothing; it will be of use to library developers who want to avoid the "No handlers could be found for logger XXX" message which can appear if the library user doesn't configure logging.
| author | Vinay Sajip <vinay_sajip@yahoo.co.uk> |
|---|---|
| date | Wed, 03 Dec 2008 23:22:58 +0000 |
| parents | b3abff17e2dd |
| children | e38335d4df91 184ca6293218 |
line wrap: on
line source
#include "Python.h" #include "structmember.h" /* _functools module written and maintained by Hye-Shik Chang <perky@FreeBSD.org> with adaptations by Raymond Hettinger <python@rcn.com> Copyright (c) 2004, 2005, 2006 Python Software Foundation. All rights reserved. */ /* reduce() *************************************************************/ static PyObject * functools_reduce(PyObject *self, PyObject *args) { PyObject *seq, *func, *result = NULL, *it; if (!PyArg_UnpackTuple(args, "reduce", 2, 3, &func, &seq, &result)) return NULL; if (result != NULL) Py_INCREF(result); it = PyObject_GetIter(seq); if (it == NULL) { PyErr_SetString(PyExc_TypeError, "reduce() arg 2 must support iteration"); Py_XDECREF(result); return NULL; } if ((args = PyTuple_New(2)) == NULL) goto Fail; for (;;) { PyObject *op2; if (args->ob_refcnt > 1) { Py_DECREF(args); if ((args = PyTuple_New(2)) == NULL) goto Fail; } op2 = PyIter_Next(it); if (op2 == NULL) { if (PyErr_Occurred()) goto Fail; break; } if (result == NULL) result = op2; else { PyTuple_SetItem(args, 0, result); PyTuple_SetItem(args, 1, op2); if ((result = PyEval_CallObject(func, args)) == NULL) goto Fail; } } Py_DECREF(args); if (result == NULL) PyErr_SetString(PyExc_TypeError, "reduce() of empty sequence with no initial value"); Py_DECREF(it); return result; Fail: Py_XDECREF(args); Py_XDECREF(result); Py_DECREF(it); return NULL; } PyDoc_STRVAR(reduce_doc, "reduce(function, sequence[, initial]) -> value\n\ \n\ Apply a function of two arguments cumulatively to the items of a sequence,\n\ from left to right, so as to reduce the sequence to a single value.\n\ For example, reduce(lambda x, y: x+y, [1, 2, 3, 4, 5]) calculates\n\ ((((1+2)+3)+4)+5). If initial is present, it is placed before the items\n\ of the sequence in the calculation, and serves as a default when the\n\ sequence is empty."); /* partial object **********************************************************/ typedef struct { PyObject_HEAD PyObject *fn; PyObject *args; PyObject *kw; PyObject *dict; PyObject *weakreflist; /* List of weak references */ } partialobject; static PyTypeObject partial_type; static PyObject * partial_new(PyTypeObject *type, PyObject *args, PyObject *kw) { PyObject *func; partialobject *pto; if (PyTuple_GET_SIZE(args) < 1) { PyErr_SetString(PyExc_TypeError, "type 'partial' takes at least one argument"); return NULL; } func = PyTuple_GET_ITEM(args, 0); if (!PyCallable_Check(func)) { PyErr_SetString(PyExc_TypeError, "the first argument must be callable"); return NULL; } /* create partialobject structure */ pto = (partialobject *)type->tp_alloc(type, 0); if (pto == NULL) return NULL; pto->fn = func; Py_INCREF(func); pto->args = PyTuple_GetSlice(args, 1, PY_SSIZE_T_MAX); if (pto->args == NULL) { pto->kw = NULL; Py_DECREF(pto); return NULL; } if (kw != NULL) { pto->kw = PyDict_Copy(kw); if (pto->kw == NULL) { Py_DECREF(pto); return NULL; } } else { pto->kw = Py_None; Py_INCREF(Py_None); } pto->weakreflist = NULL; pto->dict = NULL; return (PyObject *)pto; } static void partial_dealloc(partialobject *pto) { PyObject_GC_UnTrack(pto); if (pto->weakreflist != NULL) PyObject_ClearWeakRefs((PyObject *) pto); Py_XDECREF(pto->fn); Py_XDECREF(pto->args); Py_XDECREF(pto->kw); Py_XDECREF(pto->dict); Py_TYPE(pto)->tp_free(pto); } static PyObject * partial_call(partialobject *pto, PyObject *args, PyObject *kw) { PyObject *ret; PyObject *argappl = NULL, *kwappl = NULL; assert (PyCallable_Check(pto->fn)); assert (PyTuple_Check(pto->args)); assert (pto->kw == Py_None || PyDict_Check(pto->kw)); if (PyTuple_GET_SIZE(pto->args) == 0) { argappl = args; Py_INCREF(args); } else if (PyTuple_GET_SIZE(args) == 0) { argappl = pto->args; Py_INCREF(pto->args); } else { argappl = PySequence_Concat(pto->args, args); if (argappl == NULL) return NULL; } if (pto->kw == Py_None) { kwappl = kw; Py_XINCREF(kw); } else { kwappl = PyDict_Copy(pto->kw); if (kwappl == NULL) { Py_DECREF(argappl); return NULL; } if (kw != NULL) { if (PyDict_Merge(kwappl, kw, 1) != 0) { Py_DECREF(argappl); Py_DECREF(kwappl); return NULL; } } } ret = PyObject_Call(pto->fn, argappl, kwappl); Py_DECREF(argappl); Py_XDECREF(kwappl); return ret; } static int partial_traverse(partialobject *pto, visitproc visit, void *arg) { Py_VISIT(pto->fn); Py_VISIT(pto->args); Py_VISIT(pto->kw); Py_VISIT(pto->dict); return 0; } PyDoc_STRVAR(partial_doc, "partial(func, *args, **keywords) - new function with partial application\n\ of the given arguments and keywords.\n"); #define OFF(x) offsetof(partialobject, x) static PyMemberDef partial_memberlist[] = { {"func", T_OBJECT, OFF(fn), READONLY, "function object to use in future partial calls"}, {"args", T_OBJECT, OFF(args), READONLY, "tuple of arguments to future partial calls"}, {"keywords", T_OBJECT, OFF(kw), READONLY, "dictionary of keyword arguments to future partial calls"}, {NULL} /* Sentinel */ }; static PyObject * partial_get_dict(partialobject *pto) { if (pto->dict == NULL) { pto->dict = PyDict_New(); if (pto->dict == NULL) return NULL; } Py_INCREF(pto->dict); return pto->dict; } static int partial_set_dict(partialobject *pto, PyObject *value) { PyObject *tmp; /* It is illegal to del p.__dict__ */ if (value == NULL) { PyErr_SetString(PyExc_TypeError, "a partial object's dictionary may not be deleted"); return -1; } /* Can only set __dict__ to a dictionary */ if (!PyDict_Check(value)) { PyErr_SetString(PyExc_TypeError, "setting partial object's dictionary to a non-dict"); return -1; } tmp = pto->dict; Py_INCREF(value); pto->dict = value; Py_XDECREF(tmp); return 0; } static PyGetSetDef partial_getsetlist[] = { {"__dict__", (getter)partial_get_dict, (setter)partial_set_dict}, {NULL} /* Sentinel */ }; static PyTypeObject partial_type = { PyVarObject_HEAD_INIT(NULL, 0) "functools.partial", /* tp_name */ sizeof(partialobject), /* tp_basicsize */ 0, /* tp_itemsize */ /* methods */ (destructor)partial_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ 0, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ (ternaryfunc)partial_call, /* tp_call */ 0, /* tp_str */ PyObject_GenericGetAttr, /* tp_getattro */ PyObject_GenericSetAttr, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */ partial_doc, /* tp_doc */ (traverseproc)partial_traverse, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ offsetof(partialobject, weakreflist), /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ 0, /* tp_methods */ partial_memberlist, /* tp_members */ partial_getsetlist, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ offsetof(partialobject, dict), /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ partial_new, /* tp_new */ PyObject_GC_Del, /* tp_free */ }; /* module level code ********************************************************/ PyDoc_STRVAR(module_doc, "Tools that operate on functions."); static PyMethodDef module_methods[] = { {"reduce", functools_reduce, METH_VARARGS, reduce_doc}, {NULL, NULL} /* sentinel */ }; PyMODINIT_FUNC init_functools(void) { int i; PyObject *m; char *name; PyTypeObject *typelist[] = { &partial_type, NULL }; m = Py_InitModule3("_functools", module_methods, module_doc); if (m == NULL) return; for (i=0 ; typelist[i] != NULL ; i++) { if (PyType_Ready(typelist[i]) < 0) return; name = strchr(typelist[i]->tp_name, '.'); assert (name != NULL); Py_INCREF(typelist[i]); PyModule_AddObject(m, name+1, (PyObject *)typelist[i]); } }
