From 2ef974b9f7ba714e793bd938df15a746e1d5739c Mon Sep 17 00:00:00 2001 From: Karl Nelson Date: Wed, 22 Jul 2020 07:06:16 -0700 Subject: [PATCH 1/3] Add alternatives. --- doc/userguide.rst | 64 ++++++++++++++++++++++++++++++++--------------- 1 file changed, 44 insertions(+), 20 deletions(-) diff --git a/doc/userguide.rst b/doc/userguide.rst index 8fdac244e..6bb0e5211 100644 --- a/doc/userguide.rst +++ b/doc/userguide.rst @@ -7,7 +7,7 @@ JPype User Guide JPype Introduction ****************** -JPype is a Python module to provide full access to Java from within Python. +JPype is a Python module to provide full access to Java from within Python. Unlike Jython, JPype does not achive this by re-implementing Python, but instead by interfacing both virtual machines at the native level. This shared memory based approach achieves good computing performance, while @@ -176,7 +176,7 @@ example and watch what happens. plt.plot(d) plt.show() -A graph appears on the screen. Meaning that NumPy has not issue dealing with +A graph appears on the screen. Meaning that NumPy has not issue dealing with Java arrays. It looks like ever 4th element in the array is zero. It must be the PR the new guy put in. And off you go back to the wonderful world of Java back to the safety of curly braces and semicolons. @@ -369,7 +369,7 @@ for our project test bench, I evaluated a number of alternatives Python bridge codes. I selected JPype primarily because it presented the most integrated API and documentation which would be suitable for getting physicists up to speed quickly. Thus your criteria may yield a different -selection. Its underlying technology was underwhelming and thus I have had +selection. JPype's underlying technology was underwhelming so I have had the pleasure of many hours reworking stuff under the hood. For more details on what you can't do with JPype, please see Limitations_. @@ -439,6 +439,30 @@ is still active as the most recent release is dated 2014. The integration level with Python is fairly low currently though what they do provide is a similar API to JPype. +`JCC `_ +------------------------------------------------ +JCC is a C++ code generator that produces a C++ object interface wrapping a Java +library via Java's Native Interface (JNI). JCC also generates C++ wrappers that +conform to Python's C type system making the instances of Java classes directly +available to a Python interpreter. This may be handy if your goal is not +to make use of all of Java but rather have a specific library exposed to Python. + +`VOC _` +---------------------------------------------------------- +A transpiler that converts Python bytecode into Java bytecode part of the +BeeWare project. This may be useful if getting a smallish piece of +Python code hooked into Java. It currently list itself as early development. +This is more in the reverse direction as its goals are making Python code +available in Java rather providing interaction between the two. + +`p2j `_ +---------------------------------------------- + +This lists itself as "A (restricted) python to java source translator". +Appears to try to convert Python code into Java. Has not been actively +maintained since 2013. Like VOC this is primilarly for code translation rather +that bridging. + About this guide ================ @@ -629,9 +653,9 @@ The following Python words will trigger name mangling of a Java name: =========== =========== ============= =========== ========== -``False`` ``None`` ``True`` ``and`` ``as`` -``async`` ``await`` ``def`` ``del`` ``elif`` -``except`` ``exec`` ``from`` ``global`` ``in`` +``False`` ``None`` ``True`` ``and`` ``as`` +``async`` ``await`` ``def`` ``del`` ``elif`` +``except`` ``exec`` ``from`` ``global`` ``in`` ``is`` ``lambda`` ``nonlocal`` ``not`` ``or`` ``pass`` ``print`` ``raise`` ``with`` ``yield`` =========== =========== ============= =========== ========== @@ -1308,12 +1332,12 @@ Hash Contains Java strings implement the concept of ``in`` when using the Java method ``contains``. The Java implementation is sufficiently similar that it will - work fairly well on strings. + work fairly well on strings. For example, ``"I" in java.lang.String("team")`` would be equal to False. Testing other types using the ``in`` operator will likely raise a ``TypeError`` if Java is unable to convert the other item - into something that can be compared with a string. + into something that can be compared with a string. Concatenation Java strings can be appended to create a new string which contains the @@ -1330,7 +1354,7 @@ For each characters, use the Python construct ``for c in str:``. Unfortunately, Java strings do not yet implement the complete list of -requirements to act as Python sequences for the purposes of +requirements to act as Python sequences for the purposes of ``collections.abc.Sequence``. .. _JString: @@ -1359,7 +1383,7 @@ Exception Classes Both Python and Java treat exception classes differently from other objects. Only these types may be caught as part of a try block. Therefore, the exceptions have a special wrapper. Most of the mechanics of exceptions happen -under the surface. The one difference between Python and Java is the behavior +under the surface. The one difference between Python and Java is the behavior when the argument is queried. Java arguments can either be the string value, the exception itself, or the internal construction key depending on how the exception came into existence. Therefore, the arguments to a Java exception should never be @@ -1472,7 +1496,7 @@ mechanic for importing classes. The first argument can be a string or a Java class instance. There are two keyword arguments ``loader`` and ``initialize``. The loader can point to an alternative ClassLoader which is handy when loading custom classes through mechanisms such as over the -web. A False ``initialize`` argument loads a class without +web. A False ``initialize`` argument loads a class without loading dependencies nor populating static fields. This option is likely not useful for ordinary users. It was provided when calling forName was problematic due to `caller sensitive`_ issues. @@ -1496,7 +1520,7 @@ types. These levels are: See the previous section on `Java Conversions`_ for details. -There are special conversion rules for ``java.lang.Object`` and ``java.lang.Number``. +There are special conversion rules for ``java.lang.Object`` and ``java.lang.Number``. (`Object Class`_ and `Number Class`_) ============== ========== ========= =========== ========= ========== ========== =========== ========= ========== =========== ========= ================== ================= @@ -2027,7 +2051,7 @@ Map A Java classes that implement ``java.util.Map`` inherit the Python collections.abc.Mapping interface. As such they can be iterated, support -the indexing operator for value lookups, item deletion, length, and +the indexing operator for value lookups, item deletion, length, and support contains. Here is a summary of their capabilities: @@ -2132,7 +2156,7 @@ bulk transfer. To do so JPype supports a ``memoryview`` on rectangular arrays. Whenever a memoryview is called on a multidimensional array of primitives, JPype verifies that it is rectangular and creates a buffer. If it is jagged, a ``BufferError`` is raised. When a Java array is used as an argument to -initialize a NumPy array, it creates a ``memoryview`` so that all of the memory +initialize a NumPy array, it creates a ``memoryview`` so that all of the memory can be transferred in bulk. @@ -2253,9 +2277,9 @@ interface. Any missing method will result in JPype raising an exception. High-level proxies have one other important behavior. When a proxy created using the high-level API returns from Java it unpacks back to the original Python object complete with all of its attributes. This occurs whether the -proxy is the ``self`` argument for a method or +proxy is the ``self`` argument for a method or proxy is returned from a Java container such as a list. This is accomplished -because the actually proxy is a temporary Java object with no substance, +because the actually proxy is a temporary Java object with no substance, thus rather than returning a useless object, JPype unpacks the proxy to its original Python object. @@ -2445,7 +2469,7 @@ AWT/Swing ********* Java GUI elements can be used from Python. To use Swing -elements the event loop in Java must be started from a user thread. +elements the event loop in Java must be started from a user thread. This will prevent the JVM from shutting down until the user thread is completed. @@ -2935,7 +2959,7 @@ been recorded. Getting additional diagnostics ============================== -For the most part JPype does what its told, but that does not mean that +For the most part JPype does what its told, but that does not mean that there are no bugs. With some many different interactions between Python and Java there is always some untested edge-cases. @@ -3018,7 +3042,7 @@ the other hand, if a fault was triggered by some external source, Java constructs a JVM fault report and then transfers control back to the usual segmentation fault handler. Java will often corrupt the stack frame. Any debugger attempting to unpack the corrupted core file will instead get random -function addresses. +function addresses. The alternative is for the user to start JPype with an interactive debugger and execute to the fault point. But this option also presents challenges. The @@ -3043,7 +3067,7 @@ safer and more restricted access. To perform this task, the JVM seaches the call stack to obtain the calling methods module. This presents a difficulty for method invoked from JNI. A method called from -JNI lacks any call stack to unravel. Rather than relegating the call +JNI lacks any call stack to unravel. Rather than relegating the call to a safer level of access, the security model would outright deny access to certain JPype calls. This resulted in a number of strange behaviors over the years that were forced to be worked around. This issue was From 6068ce3e13d7477e33df938ba787af8487cdcc1e Mon Sep 17 00:00:00 2001 From: Karl Nelson Date: Thu, 23 Jul 2020 19:21:02 -0700 Subject: [PATCH 2/3] Fix return type hint --- native/common/jp_chartype.cpp | 2 +- test/jpypetest/test_hints.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/native/common/jp_chartype.cpp b/native/common/jp_chartype.cpp index 6b3900b74..3f53edefc 100644 --- a/native/common/jp_chartype.cpp +++ b/native/common/jp_chartype.cpp @@ -141,7 +141,7 @@ void JPCharType::getConversionInfo(JPConversionInfo &info) JPJavaFrame frame = JPJavaFrame::outer(m_Context); asJCharConversion.getInfo(this, info); asCharConversion.getInfo(this, info); - PyList_Append(info.ret, (PyObject*) & PyUnicode_Type); + PyList_Append(info.ret, (PyObject*) m_Context->_char->getHost()); } jarray JPCharType::newArrayInstance(JPJavaFrame& frame, jsize sz) diff --git a/test/jpypetest/test_hints.py b/test/jpypetest/test_hints.py index f39e90a58..4dcdb3c1c 100644 --- a/test/jpypetest/test_hints.py +++ b/test/jpypetest/test_hints.py @@ -115,7 +115,7 @@ def testJBoolean(self): def testJChar(self): cls = JChar hints = cls._hints - self.assertTrue(str in hints.returns) + self.assertTrue(cls in hints.returns) self.assertTrue(cls in hints.exact) self.assertTrue(JClass("java.lang.Character") in hints.implicit) self.assertTrue(str in hints.implicit) From a940be0547134f431ed7278998daae660e02d34d Mon Sep 17 00:00:00 2001 From: Karl Nelson Date: Fri, 24 Jul 2020 07:35:00 -0700 Subject: [PATCH 3/3] Propogate interrupt --- doc/CHANGELOG.rst | 1 + native/common/jp_context.cpp | 13 +++++++++++++ native/java/org/jpype/JPypeSignal.java | 5 ++++- 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/doc/CHANGELOG.rst b/doc/CHANGELOG.rst index 8dfb2286b..020e9ac8b 100644 --- a/doc/CHANGELOG.rst +++ b/doc/CHANGELOG.rst @@ -6,6 +6,7 @@ This changelog *only* contains changes from the *first* pypi release (0.5.4.3) o Latest Changes: - **1.0.2_dev0 - 2020-07-16** + - ^C propogates to a KeyboardInterrupt properly. - Added cache to the method dispatch to bypass resolution of overloads. This reduces the cost of method resolution significantly especially if diff --git a/native/common/jp_context.cpp b/native/common/jp_context.cpp index 2506ba12f..790bc99e8 100644 --- a/native/common/jp_context.cpp +++ b/native/common/jp_context.cpp @@ -165,6 +165,11 @@ void JPContext::loadEntryPoints(const string& path) JP_TRACE_OUT; } +static void interruptPy() +{ + PyErr_SetInterrupt(); +} + void JPContext::startJVM(const string& vmPath, const StringVector& args, bool ignoreUnrecognized, bool convertStrings) { @@ -345,6 +350,14 @@ void JPContext::startJVM(const string& vmPath, const StringVector& args, m_CompareToID = frame.GetMethodID(comparableClass, "compareTo", "(Ljava/lang/Object;)I"); + jclass signalClass = getClassLoader()->findClass(frame, "org.jpype.JPypeSignal"); + + method[0].name = (char*) "interruptPy"; + method[0].signature = (char*) "()V"; + method[0].fnPtr = (void*) interruptPy; + frame.GetMethodID(signalClass, "", "()V"); + frame.RegisterNatives(signalClass, method, 1); + jclass proxyClass = getClassLoader()->findClass(frame, "org.jpype.proxy.JPypeProxy"); method[0].name = (char*) "hostInvoke"; diff --git a/native/java/org/jpype/JPypeSignal.java b/native/java/org/jpype/JPypeSignal.java index 7dfd352cc..69629620d 100644 --- a/native/java/org/jpype/JPypeSignal.java +++ b/native/java/org/jpype/JPypeSignal.java @@ -10,7 +10,7 @@ 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. - + See NOTICE file for details. **************************************************************************** */ package org.jpype; @@ -49,6 +49,7 @@ static void installHandlers() public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { main.interrupt(); + interruptPy(); return null; } }); @@ -59,4 +60,6 @@ public Object invoke(Object proxy, Method method, Object[] args) throws Throwabl throw new RuntimeException(ex); } } + + native static void interruptPy(); }