==== Patch level 1 Source: [No source] Target: 3c29c6a5-77b3-3375-88d4-e67de2b791a3:jython/...:2304 (cvs::pserver:anonymous@cvs.sourceforge.net:/cvsroot/jython:jython/...) Log: Allow programmers to set the signatures of the java proxy classes. === org/python/compiler/JavaMaker.java ================================================================== --- org/python/compiler/JavaMaker.java (revision 2304) +++ org/python/compiler/JavaMaker.java (patch sig1 level 1) @@ -4,8 +4,14 @@ import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.Hashtable; +import java.util.Enumeration; import org.python.core.PyObject; +import org.python.core.PyFunction; import org.python.core.PyProxy; +import org.python.core.PyCode; +import org.python.core.PyTableCode; +import org.python.core.PyString; +import org.python.core.PyArray; import org.python.core.Py; public class JavaMaker extends ProxyMaker implements ClassConstants @@ -16,6 +22,7 @@ //Hashtable methods; PyObject methods; public boolean frozen, main; + Hashtable builtMethodNames = new Hashtable(); public JavaMaker(Class superclass, Class[] interfaces, String pythonClass, String pythonModule, String myClass, @@ -42,6 +49,11 @@ this.methods = methods; } + public void build() throws Exception { + super.build(); + buildPythonMethods(); + } + private void makeStrings(Code code, String[] list) throws Exception { if (list != null) { int n = list.length; @@ -109,11 +121,14 @@ addMain(); } -// public void addMethods(Class c) throws Exception { -// if (methods != null) { -// super.addMethods(c); -// } -// } + public void addMethods(Class c, Hashtable seen) throws Exception { + super.addMethods(c, seen); + for (Enumeration e = seen.keys(); e.hasMoreElements(); ) { + String s = (String)e.nextElement(); + String name = s.substring(0, s.indexOf(':')); + builtMethodNames.put(name, name); + } + } public void addMethod(Method method, int access) throws Exception { //System.out.println("add: "+method.getName()+", "+ @@ -165,4 +180,98 @@ code.invokestatic(runMain); code.return_(); } + + public void buildPythonMethods() throws Exception { + PyObject iter = methods.__iter__(); + for (PyObject pyName; (pyName = iter.__iternext__()) != null; ) { + String name = pyName.toString(); + PyObject value = methods.__finditem__(name); + if (shouldAddPythonMethod(name, value)) { + addPythonMethod(name, value); + } + } + } + + public boolean shouldAddPythonMethod(String name, PyObject value) { + return + !name.startsWith("super__") && + !name.startsWith("__") && + !builtMethodNames.containsKey(name) && + value instanceof PyFunction; + } + + + public void addPythonMethod(String name, PyObject value) throws Exception { + builtMethodNames.put(name, name); + MakerMethodInfo info = inspectMethod(value); + String sig = makeSignature(info.paramTypes, info.returnType); + + Code code = classfile.addMethod(name, sig, Modifier.PUBLIC); + code.aload(0); + code.ldc(name); + int jgetattr = code.pool.Methodref( + "org/python/core/Py", + "jgetattr", + "(" + $pyProxy + $str + ")" + $pyObj); + code.invokestatic(jgetattr); + callMethod(code, name, info.paramTypes, info.returnType, new Class[0]); + } + + MakerMethodInfo inspectMethod(PyObject method) { + PyFunction func = (PyFunction)method; + PyObject sig = func.__findattr__("sig"); + if (sig != null) { + return fromPythonSig(sig); + } + + PyCode code = func.func_code; + if (!(code instanceof PyTableCode)) { + return new MakerMethodInfo(Object.class, new Class[0]); + } + + PyTableCode tc = (PyTableCode)code; + int argCount = tc.co_argcount - 1; // for self argument + Class[] args = new Class[argCount]; + for (int i = 0; i < args.length; i++) { + args[i] = Object.class; + } + return new MakerMethodInfo(Object.class, args); + } + + MakerMethodInfo fromPythonSig(PyObject sig) { + PyObject[] sigParts = Py.unpackSequence(sig, 2); + Class ret = fromTypeSpec(sigParts[0]); + int arglen = sigParts[1].__len__(); + PyObject[] argParts = Py.unpackSequence(sigParts[1], arglen); + Class[] paramTypes = new Class[arglen]; + for (int i = 0; i < arglen; ++i) { + paramTypes[i] = fromTypeSpec(argParts[i]); + } + return new MakerMethodInfo(ret, paramTypes); + } + + Class fromTypeSpec(PyObject spec) { + if (spec == Py.None) { + return Void.TYPE; + } else if (spec instanceof PyString) { + String str = spec.toString(); + if (str.length() == 0) { + return Void.TYPE; + } + return PyArray.char2class(str.charAt(0)); + } else { + return (Class)spec.__tojava__(Class.class); + } + } } + +class MakerMethodInfo +{ + Class returnType; + Class[] paramTypes; + + MakerMethodInfo(Class ret, Class[] params) { + returnType = ret; + paramTypes = params; + } +} === org/python/compiler/Code.java ================================================================== --- org/python/compiler/Code.java (revision 2304) +++ org/python/compiler/Code.java (patch sig1 level 1) @@ -21,7 +21,7 @@ public class Code extends Attribute { - ConstantPool pool; + public ConstantPool pool; public int stack; int max_stack; public DataOutputStream code; === Lib/test/test_jy_sig.py ================================================================== --- Lib/test/test_jy_sig.py (revision 2304) +++ Lib/test/test_jy_sig.py (patch sig1 level 1) @@ -0,0 +1,49 @@ +""" +Test signatures in the Java Proxy code. +""" + +import unittest +import java + +class Bar(java.lang.Object): + def __init__(self, key): + self.message = 'hello!' + self.key = key + def hello(self): + self.message = 'hi' + def storeObj(self, something): + self.obj = something + def sum(self, a, b): + return a+b + sum.sig = ('i', ['i', 'i']) + def storeMe(self, str): + self.message = str + storeMe.sig = (None, [java.lang.String]) + +class TestSig(unittest.TestCase): + def testBasic(self): + b = Bar(2) + + hello = b.getClass().getMethod('hello', []) + hello.invoke(b, []) + self.assertEquals('hi', b.message) + + iType = java.lang.Integer.TYPE + sum = b.getClass().getMethod('sum', [iType, iType]) + tot = sum.invoke(b, [27, 34]) + self.assertEquals(61, tot) + + storeMe = b.getClass().getMethod('storeMe', [java.lang.String]) + storeMe.invoke(b, ['sigh']) + self.assertEquals('sigh', b.message) + + storeObj = b.getClass().getMethod('storeObj', [java.lang.Object]) + storeObj.invoke(b, [3]) + self.assertEquals(3, b.obj) + + def draftTestConstructor(self): + pass + +if __name__ == "__main__": + import test_support + test_support.run_unittest(TestSig) ==== BEGIN SVK PATCH BLOCK ==== Version: svk 1.00 (darwin) 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 pFxRiSBXagUs/g9aw1NC ==== END SVK PATCH BLOCK ====