From michaelklein4685 at outlook.com Tue Jun 11 13:59:25 2013 From: michaelklein4685 at outlook.com (Michael Klein) Date: Tue, 11 Jun 2013 16:29:25 +0430 Subject: ADAMASTOR JOĆO CARLOS MOREIRA DE CARVALHO AVILA Message-ID: <1370967673416e8d4b487eed8d4800641ce675585b@outlook.com> GUEDES LARISSA DE MORAIS VIANA, ELIANE VIRG?NIO DE SIQUEIRA NASCIMENTO, JO?O CARLOS MOREIRA DE CARVALHO, RUTH KELLY RIPARDO, ISAIAS JESUS DE ALMEIDA, NEDIA ALVES PARRIAO, VIRGINIA GADELHA DOS SANTOS, FERNANDO DA SILVA GUEDELHA. RACHEL CABRAL MOTA. AM?S COSME, ?LIO LILGEN, LILGEN CUST?DIO, COSME ADAMASTOR LILGEN. ?LIO GUEDES, TI?O D'?VILA, IVAN MENDES, MILTON GON?ALVES, CLEMENTINO KEL?, RAUL CORTEZ, FELIPE PINHEIRO, LUCAS COTRIM, ARMANDO B?GUS, RONY C?CEGAS, GUILHERME DE P?DUA, MARCELO V?RZEA, CARLOS AUGUSTO STRAZZER, PAOLETTI, EDUARDO DUSEK, JOS? DUMONT, ALEXANDRE LIPPIANI BALTAZAR, ADAMASTOR. CACHOEIRO DE ITAPEMIRIM, ITACAMBIRA, JANDA?RA IPIA?U. AM?S BALTAZAR, ADAMASTOR. CACHOEIRO DE ITAPEMIRIM, ITACAMBIRA, JANDA?RA JO?O CARLOS MOREIRA DE CARVALHO PASSA QUATRO RACHEL CABRAL MOTA BARCINO GUEDES, COSME LILGEN. From jython-checkins at python.org Fri Jun 14 21:46:13 2013 From: jython-checkins at python.org (jim.baker) Date: Fri, 14 Jun 2013 21:46:13 +0200 (CEST) Subject: [Jython-checkins] =?utf-8?q?jython=3A_Fixes_bug_1878_by_resolving?= =?utf-8?q?_complex_diamond_inheritance_of_java=2Elang=2EIterable=2C?= Message-ID: <3bXC454qssz7LjQ@mail.python.org> http://hg.python.org/jython/rev/28a66ba03862 changeset: 7110:28a66ba03862 user: Jim Baker date: Fri Jun 14 13:46:00 2013 -0600 summary: Fixes bug 1878 by resolving complex diamond inheritance of java.lang.Iterable, java.util.Map. Enables interoperation of Jython with Clojure types, including systems that build on Clojure like Storm. files: .idea/compiler.xml | 6 +- .idea/libraries/extlibs.xml | 2 +- .idea/libraries/extlibs2.xml | 2 +- Lib/test/pounce.py | 9 + Lib/test/test_java_integration.py | 77 +++++++ src/org/python/core/PyJavaType.java | 15 +- tests/java/javatests/DiamondIterableMapMRO.java | 108 ++++++++++ tests/java/javatests/ProxyDeserialization.java | 20 + 8 files changed, 234 insertions(+), 5 deletions(-) diff --git a/.idea/compiler.xml b/.idea/compiler.xml --- a/.idea/compiler.xml +++ b/.idea/compiler.xml @@ -15,7 +15,11 @@ - + + + + + diff --git a/.idea/libraries/extlibs.xml b/.idea/libraries/extlibs.xml --- a/.idea/libraries/extlibs.xml +++ b/.idea/libraries/extlibs.xml @@ -44,4 +44,4 @@ - + \ No newline at end of file diff --git a/.idea/libraries/extlibs2.xml b/.idea/libraries/extlibs2.xml --- a/.idea/libraries/extlibs2.xml +++ b/.idea/libraries/extlibs2.xml @@ -44,4 +44,4 @@ - + \ No newline at end of file diff --git a/Lib/test/pounce.py b/Lib/test/pounce.py new file mode 100644 --- /dev/null +++ b/Lib/test/pounce.py @@ -0,0 +1,9 @@ +from java.io import Serializable +from java.util.concurrent import Callable + +class Cat(Callable, Serializable): + def whoami(self): + return "Socks" + def call(self): + print "meow" # force use of PySystemState + diff --git a/Lib/test/test_java_integration.py b/Lib/test/test_java_integration.py --- a/Lib/test/test_java_integration.py +++ b/Lib/test/test_java_integration.py @@ -1,9 +1,13 @@ import copy +import glob import operator import os +import os.path import unittest +import shutil import subprocess import sys +import tempfile import re from collections import deque @@ -25,6 +29,9 @@ from org.python.tests import (BeanImplementation, Child, Child2, CustomizableMapHolder, Listenable, ToUnicode) from org.python.tests.mro import (ConfusedOnGetitemAdd, FirstPredefinedGetitem, GetitemAdder) +from org.python.util import PythonInterpreter +import org.python.core.Options + from javatests import Issue1833 from javatests.ProxyTests import NullToString, Person @@ -483,6 +490,25 @@ self.assertEqual(str(nts), '') self.assertEqual(unicode(nts), '') + def test_diamond_inheritance_of_iterable_and_map(self): + """Test deeply nested diamond inheritance of Iterable and Map, as see in some Clojure classes""" + # http://bugs.jython.org/issue1878 + from javatests import DiamondIterableMapMRO # this will raise a TypeError re MRO conflict without the fix + # Verify the correct MRO is generated - order is of course *important*; + # the following used types are implemented as empty interfaces/abstract classes, but match the inheritance graph + # and naming of Clojure/Storm. + # + # Also instead of directly importing, which would cause annoying bloat in javatests by making lots of little files, + # just match using str - this will still be stable/robust. + self.assertEqual( + str(DiamondIterableMapMRO.__mro__), + "(, , , , , , , , , , , , , , )") + # And usable with __iter__ and map functionality + m = DiamondIterableMapMRO() + m["abc"] = 42 + m["xyz"] = 47 + self.assertEqual(set(m), set(["abc", "xyz"])) + self.assertEqual(m["abc"], 42) def roundtrip_serialization(obj): """Returns a deep copy of an object, via serializing it @@ -521,6 +547,20 @@ return self.output.classQueue.popleft() +def find_jython_jars(): + # Uses the same classpath resolution as bin/jython + jython_jar_path = os.path.normpath(os.path.join(sys.executable, "../../jython.jar")) + jython_jar_dev_path = os.path.normpath(os.path.join(sys.executable, "../../jython-dev.jar")) + if os.path.exists(jython_jar_dev_path): + jars = [jython_jar_dev_path] + jars.extend(glob.glob(os.path.normpath(os.path.join(jython_jar_dev_path, "../javalib/*.jar")))) + elif os.path.exists(jython_jar_path): + jars = [jython_jar_path] + else: + raise Exception("Cannot find jython jar") + return jars + + class SerializationTest(unittest.TestCase): def test_java_serialization(self): @@ -540,6 +580,43 @@ names = [x for x in dir(__builtin__)] self.assertEqual(names, roundtrip_serialization(names)) + def test_proxy_serialization(self): + """Proxies can be deserializable in a fresh JVM, including being able to "findPython" to get a PySystemState""" + tempdir = tempfile.mkdtemp() + old_proxy_debug_dir = org.python.core.Options.proxyDebugDirectory + try: + # Generate a proxy for Cat class; + org.python.core.Options.proxyDebugDirectory = tempdir + from pounce import Cat + cat = Cat() + self.assertEqual(cat.whoami(), "Socks") + + # Create a jar file containing the Cat proxy; could use Java to do this; do it the easy way for now + proxies_jar_path = os.path.join(tempdir, "proxies.jar") + subprocess.check_call(["jar", "cf", proxies_jar_path, "-C", tempdir, "org/"]) + + # Serialize our cat + output = ByteArrayOutputStream() + serializer = CloneOutput(output) + serializer.writeObject(cat) + serializer.close() + cat_path = os.path.join(tempdir, "serialized-cat") + with open(cat_path, "wb") as f: + f.write(output.toByteArray()) + + # Then in a completely different JVM running + # ProxyDeserialization, verify we get "meow" printed to + # stdout, which in turn ensures that PySystemState (and + # Jython runtime) is initialized for the proxy + jars = find_jython_jars() + jars.append(proxies_jar_path) + classpath = ":".join(jars) + cmd = [os.path.join(System.getProperty("java.home"), "bin/java"), + "-classpath", classpath, "ProxyDeserialization", cat_path] + self.assertEqual(subprocess.check_output(cmd), "meow\n") + finally: + org.python.core.Options.proxyDebugDirectory = old_proxy_debug_dir + shutil.rmtree(tempdir) class CopyTest(unittest.TestCase): 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 @@ -172,15 +172,25 @@ continue; } for (String method : type.modified) { - if (!allModified.add(method)) { // Another type in conflict has this method, fail + if (!allModified.add(method)) { // Another type in conflict has this method, possibly fail PyList types = new PyList(); + Set proxySet = Generic.set(); for (PyJavaType othertype : conflictedAttributes) { if (othertype.modified != null && othertype.modified.contains(method)) { types.add(othertype); + proxySet.add(othertype.getProxyType()); } } + // Need to special case collections that implement both Iterable and Map. Ignore the conflict + // in having duplicate __iter__ added (see getCollectionProxies), while still allowing each + // path on the inheritance hierarchy to get an __iter__. Annoying but necessary logic. + // See http://bugs.jython.org/issue1878 + if (method.equals("__iter__") && proxySet.equals(Generic.set(Iterable.class, Map.class))) { + continue; + } throw Py.TypeError(String.format("Supertypes that share a modified attribute " - + " have an MRO conflict[attribute=%s, types=%s]", method, types)); + + "have an MRO conflict[attribute=%s, supertypes=%s, type=%s]", + method, types, this.getName())); } } } @@ -996,6 +1006,7 @@ } }; collectionProxies.put(Map.class, new PyBuiltinMethod[] {mapLenProxy, + // map IterProxy can conflict with Iterable.class; fix after the fact in handleMroError mapIterProxy, mapContainsProxy, mapGetProxy, diff --git a/tests/java/javatests/DiamondIterableMapMRO.java b/tests/java/javatests/DiamondIterableMapMRO.java new file mode 100644 --- /dev/null +++ b/tests/java/javatests/DiamondIterableMapMRO.java @@ -0,0 +1,108 @@ +// example from Storm and its use of Clojure + +package javatests; + +import java.io.Serializable; +import java.util.AbstractMap; +import java.util.Collection; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.Callable; +import org.python.util.Generic; + +// The following tag interfaces duplicate the interface/abstract class supertypes of +// Storm's IndifferentAccessMap, including Clojure types + +interface Seqable {} +interface IPersistentCollection extends Seqable {} +interface ILookup {} +interface Associative extends IPersistentCollection, ILookup {} +interface Counted {} +interface IPersistentMap extends Iterable, Associative, Counted {} +abstract class AFn implements IFn {} +interface IFn extends Callable, Runnable {} + +public class DiamondIterableMapMRO extends AFn implements ILookup, IPersistentMap, Map { + private final Map backing; + + public DiamondIterableMapMRO() { + backing = Generic.map(); + } + + public Object call() { return null; } + + public void run() {} + + public Iterator iterator() { + return backing.keySet().iterator(); + } + + public Set entrySet() { + return backing.entrySet(); + } + + @Override + public boolean equals(Object o) { + return backing.equals(o); + } + + @Override + public int hashCode() { + return backing.hashCode(); + } + + @Override + public int size() { + return backing.size(); + } + + @Override + public boolean isEmpty() { + return backing.isEmpty(); + } + + @Override + public boolean containsKey(Object key) { + return backing.containsKey(key); + } + + @Override + public boolean containsValue(Object value) { + return backing.containsValue(value); + } + + @Override + public Object get(Object key) { + return backing.get(key); + } + + public Object put(Object key, Object value) { + return backing.put(key, value); + } + + @Override + public Object remove(Object key) { + return backing.remove(key); + } + + public void putAll(Map m) { + backing.putAll(m); + } + + @Override + public void clear() { + backing.clear(); + } + + @Override + public Set keySet() { + return backing.keySet(); + } + + @Override + public Collection values() { + return backing.values(); + } +} + diff --git a/tests/java/javatests/ProxyDeserialization.java b/tests/java/javatests/ProxyDeserialization.java new file mode 100644 --- /dev/null +++ b/tests/java/javatests/ProxyDeserialization.java @@ -0,0 +1,20 @@ +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.concurrent.Callable; +import java.io.FileInputStream; +import java.io.ObjectInputStream; + + +public class ProxyDeserialization { + + public static void main(String[] args) { + try { + ObjectInputStream ois = new ObjectInputStream(new FileInputStream(args[0])); + Callable cat = (Callable) ois.readObject(); // abuse! obviously not concurrent + cat.call(); + } + catch(Exception e) { + System.err.println(e); + } + } +} -- Repository URL: http://hg.python.org/jython From jython-checkins at python.org Wed Jun 26 02:26:31 2013 From: jython-checkins at python.org (jim.baker) Date: Wed, 26 Jun 2013 02:26:31 +0200 (CEST) Subject: [Jython-checkins] =?utf-8?q?jython=3A_=5Btrivial=5D_Made_org=2Epy?= =?utf-8?q?thon=2Ecompiler=2ECode=23return=5F_public_like_all_other?= Message-ID: <3bg4mR1krSz7LjN@mail.python.org> http://hg.python.org/jython/rev/7eb5574d023d changeset: 7111:7eb5574d023d user: Jim Baker date: Tue Jun 25 18:26:38 2013 -0600 summary: [trivial] Made org.python.compiler.Code#return_ public like all other instruction-emitting methods in this class. Enables outside classes (including those written in Python) to use Jython to write Java bytecode. files: src/org/python/compiler/Code.java | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/src/org/python/compiler/Code.java b/src/org/python/compiler/Code.java --- a/src/org/python/compiler/Code.java +++ b/src/org/python/compiler/Code.java @@ -572,7 +572,7 @@ mv.visitVarInsn(RET, index); } - void return_() { + public void return_() { mv.visitInsn(RETURN); } -- Repository URL: http://hg.python.org/jython