[Python-checkins] python/dist/src/Objects funcobject.c,2.50.4.2,2.50.4.3
jhylton@users.sourceforge.net
jhylton@users.sourceforge.net
Thu, 22 May 2003 11:11:23 -0700
Update of /cvsroot/python/python/dist/src/Objects
In directory sc8-pr-cvs1:/tmp/cvs-serv28591/Objects
Modified Files:
Tag: release22-maint
funcobject.c
Log Message:
Backport fix for SF bug 692776.
Add a tp_new slot to function objects that handles the case of a
function requiring a closure. Put the function type in the new
module, rather than having a function new.function(). Add tests.
Index: funcobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/funcobject.c,v
retrieving revision 2.50.4.2
retrieving revision 2.50.4.3
diff -C2 -d -r2.50.4.2 -r2.50.4.3
*** funcobject.c 9 May 2003 18:29:21 -0000 2.50.4.2
--- funcobject.c 22 May 2003 18:11:20 -0000 2.50.4.3
***************
*** 267,270 ****
--- 267,372 ----
};
+ static char func_doc[] =
+ "function(code, globals[, name[, argdefs[, closure]]])\n\
+ \n\
+ Create a function object from a code object and a dictionary.\n\
+ The optional name string overrides the name from the code object.\n\
+ The optional argdefs tuple specifies the default argument values.\n\
+ The optional closure tuple supplies the bindings for free variables.";
+
+ /* func_new() maintains the following invariants for closures. The
+ closure must correspond to the free variables of the code object.
+
+ if len(code.co_freevars) == 0:
+ closure = NULL
+ else:
+ len(closure) == len(code.co_freevars)
+ for every elt in closure, type(elt) == cell
+ */
+
+ static PyObject *
+ func_new(PyTypeObject* type, PyObject* args, PyObject* kw)
+ {
+ PyCodeObject *code;
+ PyObject *globals;
+ PyObject *name = Py_None;
+ PyObject *defaults = Py_None;
+ PyObject *closure = Py_None;
+ PyFunctionObject *newfunc;
+ int nfree, nclosure;
+ static char *kwlist[] = {"code", "globals", "name",
+ "argdefs", "closure", 0};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kw, "O!O!|OOO:function",
+ kwlist,
+ &PyCode_Type, &code,
+ &PyDict_Type, &globals,
+ &name, &defaults, &closure))
+ return NULL;
+ if (name != Py_None && !PyString_Check(name)) {
+ PyErr_SetString(PyExc_TypeError,
+ "arg 3 (name) must be None or string");
+ return NULL;
+ }
+ if (defaults != Py_None && !PyTuple_Check(defaults)) {
+ PyErr_SetString(PyExc_TypeError,
+ "arg 4 (defaults) must be None or tuple");
+ return NULL;
+ }
+ nfree = PyTuple_GET_SIZE(code->co_freevars);
+ if (!PyTuple_Check(closure)) {
+ if (nfree && closure == Py_None) {
+ PyErr_SetString(PyExc_TypeError,
+ "arg 5 (closure) must be tuple");
+ return NULL;
+ }
+ else if (closure != Py_None) {
+ PyErr_SetString(PyExc_TypeError,
+ "arg 5 (closure) must be None or tuple");
+ return NULL;
+ }
+ }
+
+ /* check that the closure is well-formed */
+ nclosure = closure == Py_None ? 0 : PyTuple_GET_SIZE(closure);
+ if (nfree != nclosure)
+ return PyErr_Format(PyExc_ValueError,
+ "%s requires closure of length %d, not %d",
+ PyString_AS_STRING(code->co_name),
+ nfree, nclosure);
+ if (nclosure) {
+ int i;
+ for (i = 0; i < nclosure; i++) {
+ PyObject *o = PyTuple_GET_ITEM(closure, i);
+ if (!PyCell_Check(o)) {
+ return PyErr_Format(PyExc_TypeError,
+ "arg 5 (closure) expected cell, found %s",
+ o->ob_type->tp_name);
+ }
+ }
+ }
+
+ newfunc = (PyFunctionObject *)PyFunction_New((PyObject *)code,
+ globals);
+ if (newfunc == NULL)
+ return NULL;
+
+ if (name != Py_None) {
+ Py_INCREF(name);
+ Py_DECREF(newfunc->func_name);
+ newfunc->func_name = name;
+ }
+ if (defaults != Py_None) {
+ Py_INCREF(defaults);
+ newfunc->func_defaults = defaults;
+ }
+ if (closure != Py_None) {
+ Py_INCREF(closure);
+ newfunc->func_closure = closure;
+ }
+
+ return (PyObject *)newfunc;
+ }
+
static void
func_dealloc(PyFunctionObject *op)
***************
*** 416,420 ****
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
! 0, /* tp_doc */
(traverseproc)func_traverse, /* tp_traverse */
0, /* tp_clear */
--- 518,522 ----
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
! func_doc, /* tp_doc */
(traverseproc)func_traverse, /* tp_traverse */
0, /* tp_clear */
***************
*** 431,434 ****
--- 533,539 ----
0, /* tp_descr_set */
offsetof(PyFunctionObject, func_dict), /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ func_new, /* tp_new */
};