This release is compatible with Python 2.7, 3.3, 3.4, 3.5, 3.6, and 3.7. It is compatible with Java versions >= 1.7.
The Jep source code and test code now follow a typical layout of Maven projects. The C code is organized following CPython's layout as a guideline.
Jep.invoke() now supports keyword arguments when invoking Python functions. It continues to support varargs arguments and also supports a combination of positional arguments and keyword arguments.
It is now possible to pass a Python list or tuple to a Java method that is expecting an array. A new array is created and each object in the Python sequence is converted to a Java object and placed in the array.
Jep will try harder to find both the native Jep library and the Python library so LD_PRELOAD, LD_LIBRARY_PATH and java.library.path are not needed in many environments. There are 2 different changes that help with this:
- Jep will now try to load the Python library globally which is required by some Python modules. Previously this global loading could be forced on Unix by using LD_PRELOAD.
- If the native Jep Library is not found, then Jep will attempt to find it in the jep module. To find the jep module it looks in the locations in the PYTHONPATH environmental variable and also in the site-packages directory which is found relative to the PYTHONHOME environmental variable. If the Jep Library can be found in one of those locations then it is no longer necessary to set the LD_LIBRARY_PATH and/or java.library.path to the location of the Jep library.
PyConfig can now be used to set the "home" directory for Python. This serves the same purpose as the PYTHONHOME environmental variable. This value can be used by Jep when trying to find the Jep native library and it is also used by Python to find the standard Python libraries.
When a Python object is wrapped in a Java interface (using jproxy) it will now correctly call default methods on the Java interface that are not overridden by the Python object.
A new subclass of Jep has been created called SharedInterpreter. Instances of this class can be used the same as an ordinary Jep instance but it will not use a Python sub-interpreter. This is intended to improve compatibility with CPython extension modules. For simple use cases this can provide an alternative to using shared modules. Creating a SharedInterpreter is equivalent to sharing all modules. See the JavaDoc on SharedInterpreter for more information on the limitations and capabilities of this new mode.
Wrapped Python objects can now be retrieved through the use of the new method Jep.getValue(String, Class). Provide the class of jep.python.PyObject or jep.python.PyCallable to retrieve a Python object wrapped as a Java object. These wrapped Python objects provide the methods getAttr(String), getAttr(String, Class), setAttr(String, Object), and delAttr(String). You can creatively use and manipulate Python objects from Java by using PyObject.getAttr(String, Class) repeatedly to access fields and methods and PyCallable.call(...) to invoke retrieved methods. The methods on a PyObject can only be called from the Thread that created the PyObject. Please see the javadoc on the classes PyObject and PyCallable and their methods for more information. This feature is still considered to be in beta, it works well in isolated testing but needs more real world testing in a variety of environments to ensure it works consistently. It is possible that the API may change in future releases.
Previously the Jep constructor(s) would print a warning to System.err when a thread was reused for two active Jep instances. Jep will now throw a JepException when this state is detected to ensure stability.
Jep now extends AutoCloseable instead of Closeable. Along with this change, Jep will throw a JepException if you try to close a Jep instance from a thread other than the thread that constructed it. This helps ensure stability.
Some of the Jep constructors have been deprecated in favor of using the constructor Jep(JepConfig). JepConfig also has a new method .createJep() for an alternative method of creating Jep instances.
Using Jep.setInitParams(PyConfig) and Jep.setSharedModulesArgv(String...) have been deprecated in favor of using the same methods on the new class MainInterpreter. As before, these methods must be called before instantiating a Jep instance for them to take effect. This is only an API change, the functionality remains the same.
The Python method jep.printStack(bool) has been removed. This could be used to enable the printing of stacktraces to stdout when Java exceptions occur in Python. JepException has supported stacktraces since Jep 3.3 so the printStack(bool) function was no longer as useful as it originally was and hence it has been removed.
The classes JepScriptEngine and JepScriptEngineFactory have been deprecated since they are not being used by the community.
The Java classes PyModule and PyClass have been deprecated in favor of the new beta PyObject API. In addition to this, the old set(String, Object) methods on PyObject have been deprecated in favor of using setAttr(String, Object). Also Jep.createModule(String) has been deprecated as it will likely be replaced as the new PyObject API evolves.