[Jython-checkins] jython: Sort all methods in PyJavaType in the right order. See #2391

darjus.loktevic jython-checkins at python.org
Wed Jan 13 00:57:21 EST 2016


https://hg.python.org/jython/rev/ac294f546003
changeset:   7873:ac294f546003
user:        Jaime Saiz <jsaiz at sciops.esa.int>
date:        Wed Jan 13 16:55:29 2016 +1100
summary:
  Sort all methods in PyJavaType in the right order. See #2391

files:
  ACKNOWLEDGMENTS                                  |   1 +
  src/org/python/core/PyJavaType.java              |  79 ++++++++++
  tests/java/javatests/DoubleHolder.java           |  17 ++
  tests/java/javatests/Issue2391AttrOrderTest.java |  20 ++
  tests/java/javatests/NumberHolder.java           |   7 +
  5 files changed, 124 insertions(+), 0 deletions(-)


diff --git a/ACKNOWLEDGMENTS b/ACKNOWLEDGMENTS
--- a/ACKNOWLEDGMENTS
+++ b/ACKNOWLEDGMENTS
@@ -172,6 +172,7 @@
     Eli Oxman
     Robert Patrick
     Kevin Edwards
+    Jaime Saiz
 
 Local Variables:
 mode: indented-text
diff --git a/src/org/python/core/PyJavaType.java b/src/org/python/core/PyJavaType.java
--- a/src/org/python/core/PyJavaType.java
+++ b/src/org/python/core/PyJavaType.java
@@ -15,8 +15,10 @@
 import java.lang.reflect.Member;
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.Comparator;
 import java.util.Enumeration;
 import java.util.EventListener;
 import java.util.HashMap;
@@ -26,6 +28,7 @@
 import java.util.Map;
 import java.util.Queue;
 import java.util.Set;
+import java.util.Stack;
 
 import org.python.core.util.StringUtil;
 import org.python.util.Generic;
@@ -297,6 +300,9 @@
             methods = allMethods.toArray(new Method[allMethods.size()]);
         }
 
+        /* make sure we "sort" all methods so they resolve in the right order. See #2391 for details */
+        Arrays.sort(methods, new MethodComparator(new ClassComparator()));
+
         boolean isInAwt = name.startsWith("java.awt.") && name.indexOf('.', 9) == -1;
         for (Method meth : methods) {
             if (!declaredOnMember(baseClass, meth) || ignore(meth)) {
@@ -996,6 +1002,79 @@
         return Collections.unmodifiableMap(postProxies);
     }
 
+    private class ClassComparator implements Comparator<Class<?>>  {
+
+        public int compare(Class<?> c1, Class<?> c2) {
+            if (c1.equals(c2)) {
+                return 0;
+            } else if (c1.isAssignableFrom(c2)) {
+                return -1;
+            } else if (c2.isAssignableFrom(c1)) {
+                return 1;
+            }
+
+            String s1 = hierarchyName(c1);
+            String s2 = hierarchyName(c2);
+            return s1.compareTo(s2);
+        }
+
+        private String hierarchyName(Class<?> c) {
+            Stack<String> nameStack = new Stack<String>();
+            StringBuilder namesBuilder = new StringBuilder();
+            do {
+                nameStack.push(c.getSimpleName());
+                c = c.getSuperclass();
+            } while (c != null);
+
+            for (String name: nameStack) {
+                namesBuilder.append(name);
+            }
+
+            return namesBuilder.toString();
+        }
+    }
+
+    private class MethodComparator implements Comparator<Method> {
+
+        private ClassComparator classComparator;
+
+        public MethodComparator(ClassComparator classComparator) {
+            this.classComparator = classComparator;
+        }
+
+        public int compare(Method m1, Method m2) {
+            int result = m1.getName().compareTo(m2.getName());
+
+            if (result != 0) {
+                return result;
+            }
+
+            Class<?>[] p1 = m1.getParameterTypes();
+            Class<?>[] p2 = m2.getParameterTypes();
+
+            int n1 = p1.length;
+            int n2 = p2.length;
+
+            result = n1 - n2;
+
+            if (result != 0) {
+                return result;
+            }
+
+            result = classComparator.compare(m1.getDeclaringClass(), m2.getDeclaringClass());
+
+            if (result != 0) {
+                return result;
+            }
+
+            if (n1 == 0) {
+                return classComparator.compare(m1.getReturnType(), m2.getReturnType());
+            } else if (n1 == 1) {
+                return classComparator.compare(p1[0], p2[0]);
+            }
+            return result;
+        }
+    }
 
     /* Traverseproc implementation */
     @Override
diff --git a/tests/java/javatests/DoubleHolder.java b/tests/java/javatests/DoubleHolder.java
new file mode 100644
--- /dev/null
+++ b/tests/java/javatests/DoubleHolder.java
@@ -0,0 +1,17 @@
+package javatests;
+
+/* Part of Issue2391 test */
+
+public class DoubleHolder implements NumberHolder {
+
+    private Double number = 0.0;
+
+    @Override
+    public Double getNumber() {
+        return number;
+    }
+
+    public void setNumber(Double number) {
+        this.number = number;
+    }
+}
diff --git a/tests/java/javatests/Issue2391AttrOrderTest.java b/tests/java/javatests/Issue2391AttrOrderTest.java
new file mode 100644
--- /dev/null
+++ b/tests/java/javatests/Issue2391AttrOrderTest.java
@@ -0,0 +1,20 @@
+package javatests;
+
+
+import org.junit.Test;
+import org.python.util.PythonInterpreter;
+
+import static org.junit.Assert.assertEquals;
+
+public class Issue2391AttrOrderTest {
+
+    @Test
+    public void testAttribute() {
+        PythonInterpreter interpreter = new PythonInterpreter();
+        interpreter.exec("from " + getClass().getPackage().getName() + " import DoubleHolder");
+        interpreter.exec("d = DoubleHolder()");
+        assertEquals("0.0", interpreter.eval("d.number").toString());
+        interpreter.exec("d.number = 3.0");
+        assertEquals("3.0", interpreter.eval("d.number").toString());
+    }
+}
diff --git a/tests/java/javatests/NumberHolder.java b/tests/java/javatests/NumberHolder.java
new file mode 100644
--- /dev/null
+++ b/tests/java/javatests/NumberHolder.java
@@ -0,0 +1,7 @@
+package javatests;
+
+/* Part of Issue2391 test */
+
+public interface NumberHolder {
+    Number getNumber();
+}

-- 
Repository URL: https://hg.python.org/jython


More information about the Jython-checkins mailing list