[Jython-checkins] jython: Enable mixing Python and Java types in the bases of a class when

jim.baker jython-checkins at python.org
Fri Jan 10 05:08:23 CET 2014


http://hg.python.org/jython/rev/b4ae9e2893c8
changeset:   7175:b4ae9e2893c8
user:        Jim Baker <jim.baker at rackspace.com>
date:        Thu Jan 09 21:08:56 2014 -0700
summary:
  Enable mixing Python and Java types in the bases of a class when
using a metaclass.

files:
  Lib/test/test_java_subclasses.py |  46 +++++++++++++++++++-
  src/org/python/core/PyType.java  |  12 +++++
  2 files changed, 57 insertions(+), 1 deletions(-)


diff --git a/Lib/test/test_java_subclasses.py b/Lib/test/test_java_subclasses.py
--- a/Lib/test/test_java_subclasses.py
+++ b/Lib/test/test_java_subclasses.py
@@ -8,6 +8,7 @@
 from java.lang import (Boolean, Class, ClassLoader, Comparable,Integer, Object, Runnable, String,
         Thread, ThreadGroup)
 from java.util import Date, Hashtable, Vector
+from java.util.concurrent import Callable, Executors
 
 from java.awt import Color, Component, Dimension, Rectangle
 from javax.swing import ComboBoxModel, ListModel
@@ -331,13 +332,56 @@
         self.assertEquals(len(called), 1)
 
 
+class MetaClass(type):
+    def __new__(meta, name, bases, d):
+
+        # Insert the method to be called from Java
+        def call(self):
+            return self.x
+
+        d["call"] = call
+        d["foo"] = 99
+        return super(MetaClass, meta).__new__(meta, name, bases, d)
+
+
+class MetaBase(object):
+    __metaclass__ = MetaClass
+
+
+class MetaClassTest(unittest.TestCase):
+
+    def test_java_with_metaclass_base(self):
+        """Java classes can be mixed with Python bases using metaclasses"""
+        
+        # Permute mixin order
+        class Bar(MetaBase, Callable):
+            def __init__(self, x):
+                self.x = x
+
+        class Baz(Callable, MetaBase):
+            def __init__(self, x):
+                self.x = x
+
+        # Go through {bar|baz}.call indirectly through a Java path,
+        # just to ensure this mixin provided by the metaclass is available
+        pool = Executors.newSingleThreadExecutor()
+        bar = Bar(42)
+        self.assertEqual(bar.foo, 99)
+        self.assertEqual(42, pool.submit(bar).get())
+        baz = Baz(47)
+        self.assertEqual(baz.foo, 99)
+        self.assertEqual(47, pool.submit(baz).get())
+        pool.shutdown()
+
+
 def test_main():
     test_support.run_unittest(InterfaceTest,
             TableModelTest,
             AutoSuperTest,
             PythonSubclassesTest,
             AbstractOnSyspathTest,
-            ContextClassloaderTest)
+            ContextClassloaderTest,
+            MetaClassTest)
 
 
 if __name__ == '__main__':
diff --git a/src/org/python/core/PyType.java b/src/org/python/core/PyType.java
--- a/src/org/python/core/PyType.java
+++ b/src/org/python/core/PyType.java
@@ -1119,6 +1119,10 @@
         return best;
     }
 
+    private static boolean isJavaRootClass(PyType type) {
+        return type instanceof PyJavaType && type.fastGetName().equals("java.lang.Class");
+    }
+
     /**
      * Finds the most derived subtype of initialMetatype in the types
      * of bases, or initialMetatype if it is already the most derived.
@@ -1130,11 +1134,19 @@
      */
     private static PyType findMostDerivedMetatype(PyObject[] bases_list, PyType initialMetatype) {
         PyType winner = initialMetatype;
+        if (isJavaRootClass(winner)) {  // consider this root class to be equivalent to type
+            winner = PyType.TYPE;
+        }
+
         for (PyObject base : bases_list) {
             if (base instanceof PyClass) {
                 continue;
             }
             PyType curtype = base.getType();
+            if (isJavaRootClass(curtype)) {
+                curtype = PyType.TYPE;
+            }
+
             if (winner.isSubType(curtype)) {
                 continue;
             }

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


More information about the Jython-checkins mailing list