From b2136a7d4be932e3b8070e98a5a750077de78686 Mon Sep 17 00:00:00 2001 From: Dr-Irv Date: Fri, 22 Jun 2018 09:40:26 -0400 Subject: [PATCH 1/3] Docs for setPythonHome --- doc/install.rst | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/doc/install.rst b/doc/install.rst index e89f476195..d84382c589 100644 --- a/doc/install.rst +++ b/doc/install.rst @@ -90,6 +90,13 @@ All the parameters can be passed directly to the JVM either as Java system prope Such property file is also written for each build and is found in ``build/lib--/jpyconfig.properties``. +Setting PYTHONHOME +------------------ + +If the environment variable ``PYTHONHOME`` is not set when you call Python from Java, you may get an error about +file system encodings not being found. It is possible to set the location of Python from your +Java program. Use ``PyLib.setPythonHome(pathToPythonHome)`` to do that, where ``pathToPythonHome`` is a ``String`` that +contains the location of the Python installation. ======================== Build for Linux / Darwin From 7e1efd8993fa55a92c76842437cf8bfbb00c71db Mon Sep 17 00:00:00 2001 From: Dr-Irv Date: Fri, 22 Jun 2018 15:43:42 -0400 Subject: [PATCH 2/3] Support hashCode, equals, str --- src/main/java/org/jpy/PyProxyHandler.java | 100 +++++++++++++++++++++- src/test/java/org/jpy/PyObjectTest.java | 28 ++++++ src/test/python/fixtures/hasheqstr.py | 29 +++++++ 3 files changed, 154 insertions(+), 3 deletions(-) create mode 100644 src/test/python/fixtures/hasheqstr.py diff --git a/src/main/java/org/jpy/PyProxyHandler.java b/src/main/java/org/jpy/PyProxyHandler.java index 862abb49dc..2dd1ec23f5 100644 --- a/src/main/java/org/jpy/PyProxyHandler.java +++ b/src/main/java/org/jpy/PyProxyHandler.java @@ -17,9 +17,11 @@ package org.jpy; import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Proxy; import java.lang.reflect.Method; import java.util.Arrays; + import static org.jpy.PyLib.assertPythonRuns; /** @@ -30,7 +32,23 @@ * @since 0.7 */ class PyProxyHandler implements InvocationHandler { - private final PyObject pyObject; + // preloaded Method objects for the methods in java.lang.Object + private static Method hashCodeMethod; + private static Method equalsMethod; + private static Method toStringMethod; + static { + try { + hashCodeMethod = Object.class.getMethod("hashCode"); + equalsMethod = + Object.class.getMethod("equals", new Class[] { Object.class }); + toStringMethod = Object.class.getMethod("toString"); + } catch (NoSuchMethodException e) { + throw new NoSuchMethodError(e.getMessage()); + } + } + + + private final PyObject pyObject; private final PyLib.CallableKind callableKind; public PyProxyHandler(PyObject pyObject, PyLib.CallableKind callableKind) { @@ -52,13 +70,89 @@ public Object invoke(Object proxyObject, Method method, Object[] args) throws Th Long.toHexString(this.pyObject.getPointer()), Thread.currentThread()); } + String methodName = method.getName(); + Class returnType = method.getReturnType(); + if (method.equals(hashCodeMethod)) { + return callPythonHash(); + } else if (method.equals(equalsMethod)) { + if (isProxyEqualsEligible(proxyObject, args[0])) { + PyObject otherPyObject = proxyGetOtherPyObject(proxyObject, args[0]); + if (this.pyObject == otherPyObject) { + return true; + } + else { + args[0] = otherPyObject; + if (this.pyObject.hasAttribute("__eq__")) { + PyObject eqMethPtr = this.pyObject.getAttribute("__eq__"); + if (!eqMethPtr.hasAttribute("__func__")) { // Must not be implemented + return false; + } + } + else { + return false; + } + } + } + else { + return false; + } + // It's proxy eligible, but not same object, and __eq__ was implemented + // so defer to the Python __eq__ + methodName = "__eq__"; + } else if (method.equals(toStringMethod)) { + methodName = "__str__"; + } return PyLib.callAndReturnValue(this.pyObject.getPointer(), callableKind == PyLib.CallableKind.METHOD, - method.getName(), + methodName, args != null ? args.length : 0, args, method.getParameterTypes(), - method.getReturnType()); + returnType); + } + /** + * Determines if the two proxy objects implement the same interfaces + * @param proxyObject + * @param otherObject + * @return + */ + private boolean isProxyEqualsEligible(Object proxyObject, Object otherObject) { + boolean result = ((proxyObject.getClass() == otherObject.getClass()) && + (Arrays.deepEquals(proxyObject.getClass().getInterfaces(), + otherObject.getClass().getInterfaces()))); + + return result; + } + /** + * Determines the corresponding Python object for the other object passed + * @param proxyObject + * @param otherObject + * @return + */ + private PyObject proxyGetOtherPyObject(Object proxyObject, Object otherObject) { + PyObject result = null; + InvocationHandler otherProxyHandler = Proxy.getInvocationHandler(otherObject); + if (otherProxyHandler.getClass() == this.getClass()) { + PyProxyHandler otherPyProxyHandler = (PyProxyHandler) otherProxyHandler; + result = otherPyProxyHandler.pyObject; + } + + return result; + } + /** + * Calls the Python __hash__ function on the Python object, and returns the + * last 32 bits of it, since Python hash codes are 64 bits on 64 bit machines. + * @return + */ + private int callPythonHash() { + long pythonHash = PyLib.callAndReturnValue(this.pyObject.getPointer(), + true, + "__hash__", + 0, + null, + new Class[0], + Long.class); + return (int) pythonHash; } } diff --git a/src/test/java/org/jpy/PyObjectTest.java b/src/test/java/org/jpy/PyObjectTest.java index 8d2d530756..bdd0cd33d0 100644 --- a/src/test/java/org/jpy/PyObjectTest.java +++ b/src/test/java/org/jpy/PyObjectTest.java @@ -357,4 +357,32 @@ public String call() throws Exception { return processor.computeTile(x, y, new float[100 * 100]); } } + + private static interface ISimple { + public int getValue(); + } + + private static ISimple newTestObj(PyModule pyModule, String pythonClass, int value) { + PyObject procObj = pyModule.call(pythonClass, value); + ISimple simple = procObj.createProxy(ISimple.class); + return simple; + } + @Test + public void testHashEqStr() { + PyModule pyModule = PyModule.importModule("hasheqstr"); + testOneClass(pyModule, "Simple", false); + testOneClass(pyModule, "HashSimple", true); + } + private static void testOneClass(PyModule pyModule, String pythonClass, boolean eqResExpected) { + ISimple simple = newTestObj(pyModule, pythonClass, 1234); + int value = simple.getValue(); + assertEquals(value, 1234); + String rep = simple.toString(); + assertEquals(rep, pythonClass + ": 1234"); + ISimple simple2 = newTestObj(pyModule, pythonClass, 1234); + boolean eqRes = simple.equals(simple2); + assertEquals(eqRes, eqResExpected); + assertEquals(simple.hashCode()==simple2.hashCode(), eqResExpected); + assertEquals(simple.equals(simple), true); + } } diff --git a/src/test/python/fixtures/hasheqstr.py b/src/test/python/fixtures/hasheqstr.py new file mode 100644 index 0000000000..59ef87da25 --- /dev/null +++ b/src/test/python/fixtures/hasheqstr.py @@ -0,0 +1,29 @@ +class Simple(object): + def __init__(self, v): + self._v = v + + def __str__(self): + return "Simple: " + str(self._v) + + def getValue(self): + return self._v + +class HashSimple(object): + def __init__(self, v): + self._v = v + + def __str__(self): + return "HashSimple: " + str(self._v) + + def getValue(self): + return self._v + + def __hash__(self): + return hash(self._v) + + def __eq__(self, other): + if isinstance(other, self.__class__): + return self._v == other._v + else: + return False # Java can't support NotImplemented + From b58cf1dd1124abec3b8d423987afad583ec6a828 Mon Sep 17 00:00:00 2001 From: Dr-Irv Date: Mon, 25 Jun 2018 10:49:28 -0400 Subject: [PATCH 3/3] formatting code --- src/main/java/org/jpy/PyProxyHandler.java | 146 ++++++++++---------- src/test/java/org/jpy/PyObjectTest.java | 159 ++++++++++------------ 2 files changed, 145 insertions(+), 160 deletions(-) diff --git a/src/main/java/org/jpy/PyProxyHandler.java b/src/main/java/org/jpy/PyProxyHandler.java index 2dd1ec23f5..37ee54579e 100644 --- a/src/main/java/org/jpy/PyProxyHandler.java +++ b/src/main/java/org/jpy/PyProxyHandler.java @@ -1,17 +1,17 @@ /* * Copyright 2015 Brockmann Consult GmbH * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. */ package org.jpy; @@ -21,12 +21,12 @@ import java.lang.reflect.Method; import java.util.Arrays; - import static org.jpy.PyLib.assertPythonRuns; /** * The {@code InvocationHandler} for used by the proxy instances created by the - * {@link PyObject#createProxy(Class)} and {@link PyModule#createProxy(Class)} methods. + * {@link PyObject#createProxy(Class)} and {@link PyModule#createProxy(Class)} + * methods. * * @author Norman Fomferra * @since 0.7 @@ -34,23 +34,24 @@ class PyProxyHandler implements InvocationHandler { // preloaded Method objects for the methods in java.lang.Object private static Method hashCodeMethod; + private static Method equalsMethod; + private static Method toStringMethod; static { try { hashCodeMethod = Object.class.getMethod("hashCode"); - equalsMethod = - Object.class.getMethod("equals", new Class[] { Object.class }); + equalsMethod = Object.class.getMethod("equals", new Class[] { Object.class }); toStringMethod = Object.class.getMethod("toString"); } catch (NoSuchMethodException e) { throw new NoSuchMethodError(e.getMessage()); } } - - - private final PyObject pyObject; + + private final PyObject pyObject; + private final PyLib.CallableKind callableKind; - + public PyProxyHandler(PyObject pyObject, PyLib.CallableKind callableKind) { if (pyObject == null) { throw new NullPointerException("pyObject"); @@ -58,101 +59,94 @@ public PyProxyHandler(PyObject pyObject, PyLib.CallableKind callableKind) { this.pyObject = pyObject; this.callableKind = callableKind; } - + @Override public Object invoke(Object proxyObject, Method method, Object[] args) throws Throwable { assertPythonRuns(); - + if ((PyLib.Diag.getFlags() & PyLib.Diag.F_METH) != 0) { - System.out.printf("org.jpy.PyProxyHandler: invoke: %s(%s) on pyObject=%s in thread %s\n", - method.getName(), - Arrays.toString(args), - Long.toHexString(this.pyObject.getPointer()), - Thread.currentThread()); + System.out.printf("org.jpy.PyProxyHandler: invoke: %s(%s) on pyObject=%s in thread %s\n", method.getName(), + Arrays.toString(args), Long.toHexString(this.pyObject.getPointer()), Thread.currentThread()); } String methodName = method.getName(); Class returnType = method.getReturnType(); if (method.equals(hashCodeMethod)) { return callPythonHash(); } else if (method.equals(equalsMethod)) { - if (isProxyEqualsEligible(proxyObject, args[0])) { - PyObject otherPyObject = proxyGetOtherPyObject(proxyObject, args[0]); - if (this.pyObject == otherPyObject) { - return true; - } - else { - args[0] = otherPyObject; - if (this.pyObject.hasAttribute("__eq__")) { - PyObject eqMethPtr = this.pyObject.getAttribute("__eq__"); - if (!eqMethPtr.hasAttribute("__func__")) { // Must not be implemented - return false; - } - } - else { - return false; - } - } - } - else { - return false; - } - // It's proxy eligible, but not same object, and __eq__ was implemented - // so defer to the Python __eq__ + if (isProxyEqualsEligible(proxyObject, args[0])) { + PyObject otherPyObject = proxyGetOtherPyObject(proxyObject, args[0]); + if (this.pyObject == otherPyObject) { + return true; + } else { + args[0] = otherPyObject; + if (this.pyObject.hasAttribute("__eq__")) { + PyObject eqMethPtr = this.pyObject.getAttribute("__eq__"); + if (!eqMethPtr.hasAttribute("__func__")) { // Must not + // be + // implemented + return false; + } + } else { + return false; + } + } + } else { + return false; + } + // It's proxy eligible, but not same object, and __eq__ was + // implemented + // so defer to the Python __eq__ methodName = "__eq__"; } else if (method.equals(toStringMethod)) { methodName = "__str__"; } - - return PyLib.callAndReturnValue(this.pyObject.getPointer(), - callableKind == PyLib.CallableKind.METHOD, - methodName, - args != null ? args.length : 0, - args, - method.getParameterTypes(), - returnType); + + return PyLib.callAndReturnValue(this.pyObject.getPointer(), callableKind == PyLib.CallableKind.METHOD, + methodName, args != null ? args.length : 0, args, method.getParameterTypes(), returnType); } + /** * Determines if the two proxy objects implement the same interfaces + * * @param proxyObject * @param otherObject * @return */ private boolean isProxyEqualsEligible(Object proxyObject, Object otherObject) { - boolean result = ((proxyObject.getClass() == otherObject.getClass()) && - (Arrays.deepEquals(proxyObject.getClass().getInterfaces(), - otherObject.getClass().getInterfaces()))); - - return result; + boolean result = ((proxyObject.getClass() == otherObject.getClass()) + && (Arrays.deepEquals(proxyObject.getClass().getInterfaces(), otherObject.getClass().getInterfaces()))); + + return result; } + /** * Determines the corresponding Python object for the other object passed + * * @param proxyObject * @param otherObject * @return */ private PyObject proxyGetOtherPyObject(Object proxyObject, Object otherObject) { - PyObject result = null; - InvocationHandler otherProxyHandler = Proxy.getInvocationHandler(otherObject); - if (otherProxyHandler.getClass() == this.getClass()) { - PyProxyHandler otherPyProxyHandler = (PyProxyHandler) otherProxyHandler; - result = otherPyProxyHandler.pyObject; - } - - return result; + PyObject result = null; + InvocationHandler otherProxyHandler = Proxy.getInvocationHandler(otherObject); + if (otherProxyHandler.getClass() == this.getClass()) { + PyProxyHandler otherPyProxyHandler = (PyProxyHandler) otherProxyHandler; + result = otherPyProxyHandler.pyObject; + } + + return result; } + /** * Calls the Python __hash__ function on the Python object, and returns the - * last 32 bits of it, since Python hash codes are 64 bits on 64 bit machines. + * last 32 bits of it, since Python hash codes are 64 bits on 64 bit + * machines. + * * @return */ private int callPythonHash() { - long pythonHash = PyLib.callAndReturnValue(this.pyObject.getPointer(), - true, - "__hash__", - 0, - null, - new Class[0], - Long.class); - return (int) pythonHash; + long pythonHash = PyLib.callAndReturnValue(this.pyObject.getPointer(), true, "__hash__", 0, null, + new Class[0], Long.class); + return (int) pythonHash; } } diff --git a/src/test/java/org/jpy/PyObjectTest.java b/src/test/java/org/jpy/PyObjectTest.java index bdd0cd33d0..fac8db41fa 100644 --- a/src/test/java/org/jpy/PyObjectTest.java +++ b/src/test/java/org/jpy/PyObjectTest.java @@ -1,17 +1,17 @@ /* * Copyright 2015 Brockmann Consult GmbH * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. * * This file was modified by Illumon. * @@ -36,43 +36,44 @@ * @author Norman Fomferra */ public class PyObjectTest { - + @Before public void setUp() throws Exception { - //System.out.println("PyModuleTest: Current thread: " + Thread.currentThread()); + // System.out.println("PyModuleTest: Current thread: " + + // Thread.currentThread()); String importPath = new File("src/test/python/fixtures").getCanonicalPath(); - + PyLib.startPython(importPath); assertEquals(true, PyLib.isPythonRunning()); - + PyLib.Diag.setFlags(PyLib.Diag.F_ALL); } - + @After public void tearDown() throws Exception { PyLib.Diag.setFlags(PyLib.Diag.F_OFF); PyLib.stopPython(); } - + @Test(expected = IllegalArgumentException.class) public void testNullPointer() throws Exception { new PyObject(0); } - + @Test public void testPointer() throws Exception { long pointer = PyLib.importModule("sys"); PyObject pyObject = new PyObject(pointer); assertEquals(pointer, pyObject.getPointer()); } - + @Test public void testToString() throws Exception { long pointer = PyLib.importModule("sys"); PyObject pyObject = new PyObject(pointer); assertEquals("", pyObject.toString()); } - + @Test public void testEqualsAndHashCode() throws Exception { long pointer1 = PyLib.importModule("sys"); @@ -90,83 +91,76 @@ public void testEqualsAndHashCode() throws Exception { assertEquals(pyObject1.hashCode(), new PyObject(pointer1).hashCode()); assertTrue(pyObject1.hashCode() != pyObject2.hashCode()); } - + @Test public void testExecuteCode_Stmt() throws Exception { PyObject pyObject = PyObject.executeCode("pass", PyInputMode.STATEMENT); assertNotNull(pyObject); assertNull(pyObject.getObjectValue()); } - + @Test public void testExecuteCode_IntExpr() throws Exception { PyObject pyObject = PyObject.executeCode("7465", PyInputMode.EXPRESSION); assertNotNull(pyObject); assertEquals(7465, pyObject.getIntValue()); } - + @Test public void testExecuteCode_DoubleExpr() throws Exception { PyObject pyObject = PyObject.executeCode("3.14", PyInputMode.EXPRESSION); assertNotNull(pyObject); assertEquals(3.14, pyObject.getDoubleValue(), 1e-10); } - + @Test public void testExecuteCode_StringExpr() throws Exception { PyObject pyObject = PyObject.executeCode("'Hello from Python'", PyInputMode.EXPRESSION); assertNotNull(pyObject); assertEquals("Hello from Python", pyObject.getStringValue()); } - + @Test public void testExecuteCode_Script() throws Exception { HashMap localMap = new HashMap<>(); - PyObject pyVoid = PyObject.executeCode("" + - "import jpy\n" + - "File = jpy.get_type('java.io.File')\n" + - "f = File('test.txt')", - PyInputMode.SCRIPT, - null, - localMap); + PyObject pyVoid = PyObject.executeCode( + "" + "import jpy\n" + "File = jpy.get_type('java.io.File')\n" + "f = File('test.txt')", + PyInputMode.SCRIPT, null, localMap); assertNotNull(pyVoid); assertEquals(null, pyVoid.getObjectValue()); - + assertNotNull(localMap.get("jpy")); assertNotNull(localMap.get("File")); assertNotNull(localMap.get("f")); assertEquals(PyObject.class, localMap.get("jpy").getClass()); assertEquals(Class.class, localMap.get("File").getClass()); assertEquals(File.class, localMap.get("f").getClass()); - + assertEquals(new File("test.txt"), localMap.get("f")); } - + @Test public void testLocals() throws Exception { HashMap localMap = new HashMap<>(); localMap.put("x", 7); localMap.put("y", 6); - PyObject pyVoid = PyObject.executeCode("z = x + y", - PyInputMode.STATEMENT, - null, - localMap); + PyObject pyVoid = PyObject.executeCode("z = x + y", PyInputMode.STATEMENT, null, localMap); assertEquals(null, pyVoid.getObjectValue()); - + System.out.println("LocalMap size = " + localMap.size()); for (Map.Entry entry : localMap.entrySet()) { System.out.println("LocalMap[" + entry.getKey() + "]: " + entry.getValue()); } - + assertNotNull(localMap.get("x")); assertNotNull(localMap.get("y")); assertNotNull(localMap.get("z")); - + assertEquals(7, localMap.get("x")); assertEquals(6, localMap.get("y")); assertEquals(13, localMap.get("z")); } - + @Test public void testExecuteScript_ErrorExpr() throws Exception { try { @@ -176,7 +170,7 @@ public void testExecuteScript_ErrorExpr() throws Exception { assertTrue(e.getMessage().contains("SyntaxError")); } } - + @Test public void testCall() throws Exception { // Python equivalent: @@ -187,16 +181,16 @@ public void testCall() throws Exception { // PyModule builtins; try { - //Python 3.3 + // Python 3.3 builtins = PyModule.importModule("builtins"); } catch (Exception e) { - //Python 2.7 + // Python 2.7 builtins = PyModule.importModule("__builtin__"); } PyObject value = builtins.call("max", "A", "Z"); Assert.assertEquals("Z", value.getStringValue()); } - + @Test public void testGetSetAttributes() throws Exception { // Python equivalent: @@ -215,7 +209,7 @@ public void testGetSetAttributes() throws Exception { PyObject a = myobj.getAttribute("a"); Assert.assertEquals("Tut tut!", a.getStringValue()); } - + private boolean hasKey(Map dict, String key) { for (Map.Entry entry : dict.entrySet()) { if (entry.getKey().isString()) { @@ -226,48 +220,47 @@ private boolean hasKey(Map dict, String key) { } return false; } - + @Test public void testDictCopy() throws Exception { PyObject globals = PyLib.getMainGlobals(); PyDictWrapper dict = globals.asDict(); PyDictWrapper dictCopy = dict.copy(); - + PyObject.executeCode("x = 42", PyInputMode.STATEMENT, globals, dictCopy.unwrap()); - + boolean copyHasX = hasKey(dictCopy, "x"); boolean origHasX = hasKey(dict, "x"); - + assertTrue(copyHasX); assertFalse(origHasX); } - + @Test public void testCreateProxyAndCallSingleThreaded() throws Exception { - //addTestDirToPythonSysPath(); + // addTestDirToPythonSysPath(); PyModule procModule = PyModule.importModule("proc_class"); PyObject procObj = procModule.call("Processor"); testCallProxySingleThreaded(procObj); } - + // see https://github.com/bcdev/jpy/issues/26 @Test public void testCreateProxyAndCallMultiThreaded() throws Exception { - //addTestDirToPythonSysPath(); - //PyLib.Diag.setFlags(PyLib.Diag.F_ALL); + // addTestDirToPythonSysPath(); + // PyLib.Diag.setFlags(PyLib.Diag.F_ALL); PyModule procModule = PyModule.importModule("proc_class"); PyObject procObj = procModule.call("Processor"); PyLib.Diag.setFlags(PyLib.Diag.F_ALL); testCallProxyMultiThreaded(procObj); - //PyLib.Diag.setFlags(PyLib.Diag.F_OFF); + // PyLib.Diag.setFlags(PyLib.Diag.F_OFF); } - - + static void testCallProxySingleThreaded(PyObject procObject) { // Cast the Python object to a Java object of type 'Processor' Processor processor = procObject.createProxy(Processor.class); assertNotNull(processor); - + String result; result = processor.initialize(); assertEquals("initialize", result); @@ -286,39 +279,35 @@ static void testCallProxySingleThreaded(PyObject procObject) { result = processor.dispose(); assertEquals("dispose", result); } - + static void testCallProxyMultiThreaded(PyObject procObject) { testCallProxyMultiThreaded(procObject, Executors.newFixedThreadPool(4)); } - + private static void testCallProxyMultiThreaded(PyObject procObject, ExecutorService executorService) { // Cast the Python object to a Java object of type 'Processor' final Processor processor = procObject.createProxy(Processor.class); assertNotNull(processor); - + String result; result = processor.initialize(); assertEquals("initialize", result); - + List> futures; try { - futures = executorService.invokeAll(Arrays.asList(new ProcessorTask(processor, 100, 100), - new ProcessorTask(processor, 200, 100), - new ProcessorTask(processor, 100, 200), - new ProcessorTask(processor, 200, 200)), 10, TimeUnit.SECONDS); - + futures = executorService.invokeAll( + Arrays.asList(new ProcessorTask(processor, 100, 100), new ProcessorTask(processor, 200, 100), + new ProcessorTask(processor, 100, 200), new ProcessorTask(processor, 200, 200)), + 10, TimeUnit.SECONDS); + result = processor.dispose(); assertEquals("dispose", result); - - String[] results = new String[]{ - futures.get(0).get(), - futures.get(1).get(), - futures.get(2).get(), - futures.get(3).get(), - }; - + + String[] results = new String[] { futures.get(0).get(), futures.get(1).get(), futures.get(2).get(), + futures.get(3).get(), }; + Arrays.sort(results); - + result = results[0]; assertEquals("computeTile-100,100", result); result = results[1]; @@ -327,31 +316,31 @@ private static void testCallProxyMultiThreaded(PyObject procObject, ExecutorServ assertEquals("computeTile-200,100", result); result = results[3]; assertEquals("computeTile-200,200", result); - + } catch (InterruptedException | ExecutionException e) { e.printStackTrace(); fail(e.getMessage()); } } - + static void addTestDirToPythonSysPath() throws IOException { // Add module dir to sys.path in order to import file 'proc_class.py' String importPath = new File("src/test/python/fixtures").getCanonicalPath(); - //System.out.println("importPath = " + importPath); + // System.out.println("importPath = " + importPath); PyLib.execScript(String.format("import sys; sys.path.append('%s')", importPath.replace("\\", "\\\\"))); } - + private static class ProcessorTask implements Callable { final Processor processor; int x; int y; - + public ProcessorTask(Processor processor, int x, int y) { this.processor = processor; this.x = x; this.y = y; } - + @Override public String call() throws Exception { return processor.computeTile(x, y, new float[100 * 100]); @@ -359,7 +348,7 @@ public String call() throws Exception { } private static interface ISimple { - public int getValue(); + public int getValue(); } private static ISimple newTestObj(PyModule pyModule, String pythonClass, int value) { @@ -367,12 +356,14 @@ private static ISimple newTestObj(PyModule pyModule, String pythonClass, int val ISimple simple = procObj.createProxy(ISimple.class); return simple; } + @Test public void testHashEqStr() { PyModule pyModule = PyModule.importModule("hasheqstr"); testOneClass(pyModule, "Simple", false); testOneClass(pyModule, "HashSimple", true); } + private static void testOneClass(PyModule pyModule, String pythonClass, boolean eqResExpected) { ISimple simple = newTestObj(pyModule, pythonClass, 1234); int value = simple.getValue(); @@ -382,7 +373,7 @@ private static void testOneClass(PyModule pyModule, String pythonClass, boolean ISimple simple2 = newTestObj(pyModule, pythonClass, 1234); boolean eqRes = simple.equals(simple2); assertEquals(eqRes, eqResExpected); - assertEquals(simple.hashCode()==simple2.hashCode(), eqResExpected); + assertEquals(simple.hashCode() == simple2.hashCode(), eqResExpected); assertEquals(simple.equals(simple), true); } }