Index: src/org/python/core/PyTableCode.java =================================================================== --- src/org/python/core/PyTableCode.java (revision 4251) +++ src/org/python/core/PyTableCode.java (working copy) @@ -112,21 +112,11 @@ throwReadonly(name); } - private static PyTuple toPyStringTuple(String[] ar) { - if (ar == null) return Py.EmptyTuple; - int sz = ar.length; - PyString[] pystr = new PyString[sz]; - for (int i = 0; i < sz; i++) { - pystr[i] = new PyString(ar[i]); - } - return new PyTuple(pystr); - } - public PyObject __findattr__(String name) { // have to craft co_varnames specially - if (name == "co_varnames") return toPyStringTuple(co_varnames); - if (name == "co_cellvars") return toPyStringTuple(co_cellvars); - if (name == "co_freevars") return toPyStringTuple(co_freevars); + if (name == "co_varnames") return PyCode.toPyStringTuple(co_varnames); + if (name == "co_cellvars") return PyCode.toPyStringTuple(co_cellvars); + if (name == "co_freevars") return PyCode.toPyStringTuple(co_freevars); return super.__findattr__(name); } Index: src/org/python/core/PyCode.java =================================================================== --- src/org/python/core/PyCode.java (revision 4251) +++ src/org/python/core/PyCode.java (working copy) @@ -37,4 +37,14 @@ PyObject globals, PyObject[] defaults, PyObject closure); + static PyTuple toPyStringTuple(String[] ar) { + if (ar == null) return Py.EmptyTuple; + int sz = ar.length; + PyString[] pystr = new PyString[sz]; + for (int i = 0; i < sz; i++) { + pystr[i] = new PyString(ar[i]); + } + return new PyTuple(pystr); + } + } Index: src/org/python/core/PyReflectedFunction.java =================================================================== --- src/org/python/core/PyReflectedFunction.java (revision 4251) +++ src/org/python/core/PyReflectedFunction.java (working copy) @@ -38,6 +38,14 @@ public boolean _doset(PyObject container) { throw Py.TypeError("java function not settable: "+__name__); } + + public PyCode getFunc_code() { + return new JavaCode(this); + } + + public PyObject[] getFunc_defaults() { + return null; + } public PyObject getDoc() { return __doc__; Index: src/org/python/core/Py.java =================================================================== --- src/org/python/core/Py.java (revision 4251) +++ src/org/python/core/Py.java (working copy) @@ -1935,6 +1935,28 @@ { return func.__call__(arg1, arg2, arg3); } + + public PyObject __findattr__(String name) { + if (func instanceof PyReflectedFunction) { + PyReflectedFunction pyfunc = (PyReflectedFunction) func; + if (name == "co_argcount") return new PyInteger(pyfunc.argslist[0].args.length); + if (name == "co_firstlineno") return new PyInteger(-1); + if (name == "co_varnames") { + ReflectedArgs refargs = pyfunc.argslist[0]; + String[] out = new String[refargs.args.length]; + for(int i = 0; i < out.length; i++) { + out[i] = refargs.args[i].getName(); + } + return toPyStringTuple(out); + } + if (name == "co_cellvars") return toPyStringTuple(new String[0]); + if (name == "co_freevars") return toPyStringTuple(new String[0]); + if (name == "co_filename") return new PyString(""); + if (name == "co_flags") return new PyInteger(0); + if (name == "co_nlocals") return new PyInteger(pyfunc.nargs); + } + return super.__findattr__(name); + } } /** Index: src/org/python/modules/types.java =================================================================== --- src/org/python/modules/types.java (revision 4251) +++ src/org/python/modules/types.java (working copy) @@ -45,6 +45,7 @@ dict.__setitem__("ModuleType", PyType.fromClass(PyModule.class)); dict.__setitem__("NoneType", PyType.fromClass(PyNone.class)); dict.__setitem__("ObjectType", PyType.fromClass(PyObject.class)); + dict.__setitem__("ReflectedFunctionType", PyType.fromClass(PyReflectedFunction.class)); dict.__setitem__("SliceType", PyType.fromClass(PySlice.class)); dict.__setitem__("StringType", PyType.fromClass(PyString.class)); dict.__setitem__("TracebackType", Index: Lib/inspect.py =================================================================== --- Lib/inspect.py (revision 4251) +++ Lib/inspect.py (working copy) @@ -99,7 +99,7 @@ func_doc (same as __doc__) func_globals global namespace in which this function was defined func_name (same as __name__)""" - return isinstance(object, types.FunctionType) + return isinstance(object, types.FunctionType) or isinstance(object, types.ReflectedFunctionType) def istraceback(object): """Return true if the object is a traceback.