Index: core/PyFunction.java =================================================================== RCS file: /cvsroot/jython/jython/org/python/core/PyFunction.java,v retrieving revision 2.16 diff -u -r2.16 PyFunction.java --- core/PyFunction.java 6 Aug 2003 11:46:25 -0000 2.16 +++ core/PyFunction.java 24 Feb 2004 20:33:58 -0000 @@ -27,10 +27,9 @@ func_defaults = defaults; func_code = code; if (closure_cells != null) { - func_closure = new PyTuple(closure_cells); - } else { - func_closure = null; - } + func_closure = new PyTuple(closure_cells); + } // else func_closure is already null; no extra assignment needed + validateClosure(func_closure); } public PyFunction(PyObject globals, PyObject[] defaults, PyCode code, @@ -72,17 +71,48 @@ throw Py.TypeError("readonly attribute"); throw Py.AttributeError(name); } - + + private void validateClosureCell(PyObject o) { + if (!(o instanceof PyCell)) { + throw Py.TypeError("(closure) expected cell, found " + o.__class__.__name__); + } + } + + private void validateClosureSize(int size) + { + if (func_code instanceof PyTableCode) { + String[] freevars = ((PyTableCode)func_code).co_freevars; + int expectedSize = (freevars == null) ? 0 : freevars.length; + if (size != expectedSize) { + throw Py.ValueError( + func_code.co_name + + " requires closure of length " + expectedSize + + ", not " + size); + } + } + } + + private void validateClosure(PyObject o) { + if ((o == null )) { + validateClosureSize(0); + return; + } + + if (!(o instanceof PyTuple)) { + throw Py.TypeError("(closure) must be tuple"); + } + PyTuple t = (PyTuple)o; + validateClosureSize(t.__len__()); + for (int i = 0; i < t.__len__(); i++) { + validateClosureCell(t.get(i)); + } + } + public void __setattr__(String name, PyObject value) { - // TBD: in CPython, func_code, func_defaults, func_doc, __doc__ are - // writable. For now, only func_doc, __doc__ are writable in - // JPython. if (name == "func_doc" || name == "__doc__") __doc__ = value; else if (name == "func_closure") { - if (!(value instanceof PyTuple)) { - throw Py.TypeError("func_closure must be set to a tuple"); - } + validateClosure(value); func_closure = value; } // not yet implemented: Index: modules/newmodule.java =================================================================== RCS file: /cvsroot/jython/jython/org/python/modules/newmodule.java,v retrieving revision 1.4 diff -u -r1.4 newmodule.java --- modules/newmodule.java 11 Jul 2003 22:14:14 -0000 1.4 +++ modules/newmodule.java 24 Feb 2004 20:33:58 -0000 @@ -41,12 +41,8 @@ public static PyFunction function(PyCode code, PyObject globals, String name, PyObject[] argdefs) { - PyFunction f = new PyFunction(globals, argdefs, code, null,null); - if (name != null) - f.__name__ = name; - return f; + return function(code, globals, name, argdefs, null); } - public static PyFunction function(PyCode code, PyObject globals, String name, PyObject[] argdefs,