|
From: <zy...@us...> - 2010-06-16 14:46:41
|
Revision: 7066
http://jython.svn.sourceforge.net/jython/?rev=7066&view=rev
Author: zyasoft
Date: 2010-06-16 14:46:34 +0000 (Wed, 16 Jun 2010)
Log Message:
-----------
Reflected method fixes:
Fixes #1605 by having PyComplex#__tojava__ refuse to convert to
anything but itself (restores old behavior before adding support for
faux floats)
Fixes #1615 by supporting varargs Java methods, so that a method
marked as test(String...) can be called as either test("abc", "xyz")
or, because it's reasonable in Java, test(["abc", "xyz"])
Modified Paths:
--------------
trunk/jython/Lib/test/test_joverload.py
trunk/jython/NEWS
trunk/jython/src/org/python/core/PyComplex.java
trunk/jython/src/org/python/core/PyReflectedFunction.java
trunk/jython/src/org/python/core/ReflectedArgs.java
Added Paths:
-----------
trunk/jython/tests/java/javatests/Reflection.java
Modified: trunk/jython/Lib/test/test_joverload.py
===================================================================
--- trunk/jython/Lib/test/test_joverload.py 2010-06-15 06:34:16 UTC (rev 7065)
+++ trunk/jython/Lib/test/test_joverload.py 2010-06-16 14:46:34 UTC (rev 7066)
@@ -3,9 +3,12 @@
# (can be adapted to test alternative re-implemations even while they are developed
# write a *Envl class and change/add to to_test for that)
+import sys
import unittest
import java
+from java.util import ArrayList
+from javatests import JOverload, Reflection
from org.python.core import PyReflectedFunction
class PyReflFuncEnvl:
@@ -25,7 +28,6 @@
meth_dict[name] = envl_class(name,[ m for m in meths if m.name == name ])
return meth_dict
-from javatests import JOverload
jo = JOverload()
to_test = [extract_ov_meths(JOverload,PyReflFuncEnvl)]
@@ -119,11 +121,55 @@
""")
+class VarargsDispatchTests(unittest.TestCase):
+
+ def test_strings(self):
+ t = Reflection.StringVarargs()
+ self.assertEqual(t.test("abc", "xyz"),
+ "String...:[abc, xyz]")
+ self.assertEqual(t.test("abc"),
+ "String...:[abc]")
+ self.assertEqual(t.test(),
+ "String...:[]")
+
+ self.assertEqual(t.test(["abc", "xyz"]),
+ "String...:[abc, xyz]")
+ self.assertEqual(t.test(["abc"]),
+ "String...:[abc]")
+ self.assertEqual(t.test([]),
+ "String...:[]")
+
+
+ def test_lists(self):
+ t = Reflection.ListVarargs()
+ self.assertEqual(t.test(ArrayList([1,2,3]), ArrayList([4,5,6])),
+ "List...:[[1, 2, 3], [4, 5, 6]]")
+ self.assertEqual(t.test(ArrayList([1,2,3])),
+ "List...:[[1, 2, 3]]")
+ self.assertEqual(t.test(),
+ "List...:[]")
+
+ self.assertEqual(t.test([ArrayList([1,2,3]), ArrayList([4,5,6])]),
+ "List...:[[1, 2, 3], [4, 5, 6]]")
+ self.assertEqual(t.test([ArrayList([1,2,3])]),
+ "List...:[[1, 2, 3]]")
+ self.assertEqual(t.test([]),
+ "List...:[]")
+
+
+class ComplexOverloadingTests(unittest.TestCase):
+
+ def test_complex(self):
+ o = Reflection.Overloaded()
+ self.assertEqual(o(2.), "class java.lang.Double=2.0")
+ self.assertEqual(o(1+2j), "class org.python.core.PyComplex=(1+2j)")
+
+
+
def printout(meth_dict,lbl,rng,args):
for i in rng:
print meth_dict['ov_%s%s' % (lbl,i)](jo,args)
-import sys
if __name__ == '__main__' and not sys.argv[1:] == ['break-out']:
try:
@@ -131,4 +177,4 @@
except ImportError:
unittest.main()
else:
- test_support.run_unittest(OverloadedDispatchTests)
+ test_support.run_unittest(OverloadedDispatchTests, VarargsDispatchTests, ComplexOverloadingTests)
Modified: trunk/jython/NEWS
===================================================================
--- trunk/jython/NEWS 2010-06-15 06:34:16 UTC (rev 7065)
+++ trunk/jython/NEWS 2010-06-16 14:46:34 UTC (rev 7066)
@@ -2,6 +2,8 @@
Jython 2.5.2a1
Bugs Fixed
+ - [ 1615 ] Can't invoke Java method that takes a variable number of arguments with zero arguments
+ - [ 1605 ] float preference over PyComplex as arg to __call__ breaks logic
- [ 1586 ] weakref reference count leak when kwargs are used
- [ 1601 ] Can't serialize PyCode object
- [ 1551 ] Java objects cannot be copied by the copy module
Modified: trunk/jython/src/org/python/core/PyComplex.java
===================================================================
--- trunk/jython/src/org/python/core/PyComplex.java 2010-06-15 06:34:16 UTC (rev 7065)
+++ trunk/jython/src/org/python/core/PyComplex.java 2010-06-16 14:46:34 UTC (rev 7066)
@@ -482,7 +482,17 @@
return _divmod(coerce(left), this).__finditem__(0);
}
+ // Special case __tojava__ for bug 1605, since we broke it with our support for faux floats.
+
@Override
+ public Object __tojava__(Class<?> c) {
+ if (c.isInstance(this)) {
+ return this;
+ }
+ return Py.NoConversion;
+ }
+
+ @Override
public PyObject __truediv__(PyObject right) {
return complex___truediv__(right);
}
Modified: trunk/jython/src/org/python/core/PyReflectedFunction.java
===================================================================
--- trunk/jython/src/org/python/core/PyReflectedFunction.java 2010-06-15 06:34:16 UTC (rev 7065)
+++ trunk/jython/src/org/python/core/PyReflectedFunction.java 2010-06-16 14:46:34 UTC (rev 7066)
@@ -55,9 +55,10 @@
private ReflectedArgs makeArgs(Method m) {
return new ReflectedArgs(m,
- m.getParameterTypes(),
- m.getDeclaringClass(),
- Modifier.isStatic(m.getModifiers()));
+ m.getParameterTypes(),
+ m.getDeclaringClass(),
+ Modifier.isStatic(m.getModifiers()),
+ m.isVarArgs());
}
public PyReflectedFunction copy() {
Modified: trunk/jython/src/org/python/core/ReflectedArgs.java
===================================================================
--- trunk/jython/src/org/python/core/ReflectedArgs.java 2010-06-15 06:34:16 UTC (rev 7065)
+++ trunk/jython/src/org/python/core/ReflectedArgs.java 2010-06-16 14:46:34 UTC (rev 7066)
@@ -10,6 +10,8 @@
public boolean isStatic;
+ public boolean isVarArgs;
+
public int flags;
public static final int StandardCall = 0;
@@ -19,10 +21,15 @@
public static final int PyArgsKeywordsCall = 2;
public ReflectedArgs(Object data, Class<?>[] args, Class<?> declaringClass, boolean isStatic) {
+ this(data, args, declaringClass, isStatic, false);
+ }
+
+ public ReflectedArgs(Object data, Class<?>[] args, Class<?> declaringClass, boolean isStatic, boolean isVarArgs) {
this.data = data;
this.args = args;
this.declaringClass = declaringClass;
this.isStatic = isStatic;
+ this.isVarArgs = isVarArgs; // only used for varargs matching; it should be added after the unboxed form
if (args.length == 1 && args[0] == PyObject[].class) {
this.flags = PyArgsCall;
@@ -90,6 +97,38 @@
}
int n = this.args.length;
+
+ // if we have a varargs method AND the last PyObject is not a list/tuple
+ // we need to do box (wrap with an array) the last pyArgs.length - n args
+ // (which might be empty)
+ //
+ // examples:
+ // test(String... x)
+ // test(List... x)
+ //
+ // in this last example, don't worry if someone is overly clever in calling this,
+ // they can always write their own version of PyReflectedFunction and put it in the proxy
+ // if that's what they need to do ;)
+
+ if (isVarArgs) {
+ if (pyArgs.length == 0 || !(pyArgs[pyArgs.length - 1] instanceof PySequenceList)) {
+ int non_varargs_len = n - 1;
+ if (pyArgs.length >= non_varargs_len) {
+ PyObject[] boxedPyArgs = new PyObject[n];
+ for (int i = 0; i < non_varargs_len; i++) {
+ boxedPyArgs[i] = pyArgs[i];
+ }
+ int varargs_len = pyArgs.length - non_varargs_len;
+ PyObject[] varargs = new PyObject[varargs_len];
+ for (int i = 0; i < varargs_len; i++) {
+ varargs[i] = pyArgs[non_varargs_len + i];
+ }
+ boxedPyArgs[non_varargs_len] = new PyList(varargs);
+ pyArgs = boxedPyArgs;
+ }
+ }
+ }
+
if (pyArgs.length != n) {
return false;
}
@@ -111,8 +150,11 @@
Object[] javaArgs = callData.args;
for (int i = 0; i < n; i++) {
- if ((javaArgs[i] = pyArgs[i].__tojava__(this.args[i])) == Py.NoConversion) {
- // Make error messages clearer
+ PyObject pyArg = pyArgs[i];
+ Class targetClass = this.args[i];
+ Object javaArg = pyArg.__tojava__(targetClass);
+ javaArgs[i] = javaArg;
+ if (javaArg == Py.NoConversion) {
if (i > callData.errArg) {
callData.errArg = i;
}
@@ -253,7 +295,7 @@
@Override
public String toString() {
- String s = declaringClass + ", " + isStatic + ", " + flags + ", " + data + "\n";
+ String s = declaringClass + ", static=" + isStatic + ", varargs=" + isVarArgs + ",flags=" + flags + ", " + data + "\n";
s = s + "\t(";
for (Class<?> arg : args) {
s += arg.getName() + ", ";
Added: trunk/jython/tests/java/javatests/Reflection.java
===================================================================
--- trunk/jython/tests/java/javatests/Reflection.java (rev 0)
+++ trunk/jython/tests/java/javatests/Reflection.java 2010-06-16 14:46:34 UTC (rev 7066)
@@ -0,0 +1,44 @@
+package javatests;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.python.core.Py;
+import org.python.core.PyComplex;
+import org.python.core.PyObject;
+
+public class Reflection {
+
+ public static class StringVarargs {
+
+ public String test(String... args) {
+ return "String...:" + Arrays.toString(args);
+ }
+ }
+
+ public static class ListVarargs {
+
+ public String test(List... args) {
+ return "List...:" + Arrays.toString(args);
+ }
+ }
+
+ public static class Overloaded {
+
+ public PyObject __call__(float x) {
+ return dump(x);
+ }
+
+ public PyObject __call__(double x) {
+ return dump(x);
+ }
+
+ public PyObject __call__(PyComplex x) {
+ return dump(x);
+ }
+
+ private PyObject dump(Object o) {
+ return Py.newString(o.getClass() + "=" + o);
+ }
+ }
+}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|