Added support for importing Python modules from paths other than Java Classpath.
This commit is contained in:
parent
6ef5078412
commit
906e5222f3
|
@ -1,6 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="src" path="src/main/java"/>
|
||||
<classpathentry excluding="src/example/java/|src/main/java/" including="Lib/" kind="src" path=""/>
|
||||
<classpathentry kind="src" path="src/example/java"/>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
|
||||
<classpathentry kind="var" path="JYTHON_HOME/jython.jar" sourcepath="/JYTHON_HOME/src"/>
|
||||
|
|
|
@ -2,6 +2,9 @@
|
|||
<?eclipse-pydev version="1.0"?>
|
||||
|
||||
<pydev_project>
|
||||
<pydev_property name="org.python.pydev.PYTHON_PROJECT_VERSION">python 2.6</pydev_property>
|
||||
<pydev_property name="org.python.pydev.PYTHON_PROJECT_VERSION">jython 2.5</pydev_property>
|
||||
<pydev_property name="org.python.pydev.PYTHON_PROJECT_INTERPRETER">Default</pydev_property>
|
||||
<pydev_pathproperty name="org.python.pydev.PROJECT_SOURCE_PATH">
|
||||
<path>/jywrapper/Lib</path>
|
||||
</pydev_pathproperty>
|
||||
</pydev_project>
|
||||
|
|
|
@ -8,6 +8,18 @@ import org.junit.Test;
|
|||
|
||||
public class DependentTest {
|
||||
|
||||
private static final String PYLIB_DIR_NAME = "Lib";
|
||||
|
||||
static {
|
||||
try {
|
||||
JyWrapper.addToPythonPath(
|
||||
DependentTest.class.getClassLoader()
|
||||
.getResource(PYLIB_DIR_NAME).toURI());
|
||||
} catch (final Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private final Employee Employee_ = JyWrapper.wrap(Employee.class, "person.Employee");
|
||||
|
||||
private final Dependent Dependent_ = JyWrapper.wrap(Dependent.class, "person.Dependent");
|
||||
|
|
|
@ -3,12 +3,25 @@ package net.abhinavsarkar.jywrapper.example;
|
|||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import net.abhinavsarkar.jywrapper.JyWrapper;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
public class EmployeeTest {
|
||||
|
||||
private static final String PYLIB_DIR_NAME = "Lib";
|
||||
|
||||
static {
|
||||
try {
|
||||
JyWrapper.addToPythonPath(
|
||||
DependentTest.class.getClassLoader()
|
||||
.getResource(PYLIB_DIR_NAME).toURI());
|
||||
} catch (final Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private final Employee Employee_ = JyWrapper.wrap(Employee.class, "person.Employee");
|
||||
|
||||
private final Dependent Dependent_ = JyWrapper.wrap(Dependent.class, "person.Dependent");
|
||||
|
|
|
@ -2,14 +2,17 @@ package net.abhinavsarkar.jywrapper;
|
|||
|
||||
import static net.abhinavsarkar.jywrapper.Messages._;
|
||||
|
||||
|
||||
import java.net.URI;
|
||||
import net.abhinavsarkar.jywrapper.annotation.Wraps;
|
||||
import net.abhinavsarkar.jywrapper.exception.PythonImportNotFoundException;
|
||||
|
||||
import org.python.core.Py;
|
||||
import org.python.core.PyClass;
|
||||
import org.python.core.PyFunction;
|
||||
import org.python.core.PyModule;
|
||||
import org.python.core.PyObject;
|
||||
import org.python.core.PyString;
|
||||
import org.python.core.PySystemState;
|
||||
import org.python.core.PyType;
|
||||
|
||||
/**
|
||||
|
@ -18,7 +21,7 @@ import org.python.core.PyType;
|
|||
* @param <T> The type of the java class to wrap the Python class/module with.
|
||||
*/
|
||||
public final class JyWrapper {
|
||||
|
||||
|
||||
private JyWrapper() {
|
||||
}
|
||||
|
||||
|
@ -27,20 +30,20 @@ public final class JyWrapper {
|
|||
if (annotation == null) {
|
||||
throw new PythonImportNotFoundException(_("JyWrapper.7", javaClass)); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
|
||||
return wrap(javaClass, annotation.value());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param pyImportName The full import name of the Python class/module
|
||||
* to wrap.
|
||||
* @return An instance of {@link UninitedPyObjectWrapper}, ready to be
|
||||
* @return An instance of {@link UninitedPyObjectWrapper}, ready to be
|
||||
* initialized.
|
||||
* @throws IllegalStateException Thrown if the java Class to be used to
|
||||
* wrap the Python module/class, has not been supplied by earlier
|
||||
* wrap the Python module/class, has not been supplied by earlier
|
||||
* calling {@link JyWrapper#with(Class)}.
|
||||
* @throws IllegalArgumentException Thrown if the pyImportName parameter
|
||||
* is null.
|
||||
* is null.
|
||||
*/
|
||||
public static <T> T wrap(final Class<T> javaClass, final String pyImportName) {
|
||||
if (javaClass == null) {
|
||||
|
@ -49,24 +52,24 @@ public final class JyWrapper {
|
|||
if (pyImportName == null) {
|
||||
throw new IllegalArgumentException(_("JyWrapper.6", "pyImportName")); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
}
|
||||
|
||||
|
||||
final PyObject pyImport = PyImportLoader.loadPyImport(pyImportName);
|
||||
if (!(pyImport instanceof PyType
|
||||
|| pyImport instanceof PyModule
|
||||
if (!(pyImport instanceof PyType
|
||||
|| pyImport instanceof PyModule
|
||||
|| pyImport instanceof PyClass)) {
|
||||
throw new IllegalArgumentException(_("JyWrapper.5", pyImportName)); //$NON-NLS-1$
|
||||
}
|
||||
return Util.py2Java(pyImport, javaClass);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param <T> The return type of the {@link PyCallable} instance.
|
||||
* @param <T> The return type of the {@link PyCallable} instance.
|
||||
* @param pyImportName The full import name of the Python function to wrap.
|
||||
* @param returnType The class of the return type.
|
||||
* @return An instance of {@link PyCallable} which wraps the
|
||||
* Python function given in parameter.
|
||||
* @throws IllegalArgumentException Thrown if the any of the parameters
|
||||
* supplied are null or if the pyImportName parameter supplied does not
|
||||
* @throws IllegalArgumentException Thrown if the any of the parameters
|
||||
* supplied are null or if the pyImportName parameter supplied does not
|
||||
* correspond to a Python function.
|
||||
*/
|
||||
public static <T> PyCallable<T> wrapPyFunction(
|
||||
|
@ -77,16 +80,33 @@ public final class JyWrapper {
|
|||
if (returnType == null) {
|
||||
throw new IllegalArgumentException(_("JyWrapper.6", "returnType")); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
}
|
||||
|
||||
|
||||
final PyObject pyImport = PyImportLoader.loadPyImport(pyImportName);
|
||||
if (!(pyImport instanceof PyFunction)) {
|
||||
throw new IllegalArgumentException(_("JyWrapper.0", pyImportName)); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
final PyCallable<T> newInstance = PyObjectProxy.newInstance(
|
||||
pyImport, PyCallable.class);
|
||||
return newInstance;
|
||||
}
|
||||
|
||||
|
||||
public static void addToPythonPath(final URI path) {
|
||||
final PySystemState pySystemState = Py.getSystemState();
|
||||
final PyString resolvedPath = Util.resolvePath(path);
|
||||
if (resolvedPath != null && !pySystemState.path.contains(resolvedPath)) {
|
||||
pySystemState.path.append(resolvedPath);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void removeFromPythonPath(final URI path) {
|
||||
final PySystemState pySystemState = Py.getSystemState();
|
||||
final PyString resolvedPath = Util.resolvePath(path);
|
||||
if (resolvedPath != null && pySystemState.path.contains(resolvedPath)) {
|
||||
pySystemState.path.remove(resolvedPath);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -9,7 +9,6 @@ import net.abhinavsarkar.jywrapper.exception.PythonImportNotFoundException;
|
|||
import org.python.core.Py;
|
||||
import org.python.core.PyException;
|
||||
import org.python.core.PyObject;
|
||||
import org.python.core.PySystemState;
|
||||
|
||||
/**
|
||||
* @author AbhinavSarkar
|
||||
|
@ -17,8 +16,8 @@ import org.python.core.PySystemState;
|
|||
*/
|
||||
public final class PyImportLoader {
|
||||
|
||||
private static final PyObject importer = new PySystemState().getBuiltins()
|
||||
.__getitem__(Py.newString("__import__")); //$NON-NLS-1$
|
||||
private static final PyObject importer =
|
||||
Py.getSystemState().getBuiltins().__getitem__(Py.newString("__import__"));
|
||||
|
||||
private static final ConcurrentHashMap<String, PyObject> loadedPyImports =
|
||||
new ConcurrentHashMap<String, PyObject>();
|
||||
|
@ -35,7 +34,7 @@ public final class PyImportLoader {
|
|||
throws PythonImportNotFoundException {
|
||||
if (!loadedPyImports.containsKey(fullImportName)) {
|
||||
final int i = fullImportName.lastIndexOf('.');
|
||||
final String errorMsg = _("PyImportLoader.1", fullImportName); //$NON-NLS-1$
|
||||
final String errorMsg = _("PyImportLoader.1", fullImportName, Py.getSystemState().path); //$NON-NLS-1$
|
||||
PyObject pyImport;
|
||||
if (i == -1) {
|
||||
final String pyModuleName = fullImportName;
|
||||
|
@ -59,4 +58,5 @@ public final class PyImportLoader {
|
|||
}
|
||||
return loadedPyImports.get(fullImportName);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -2,6 +2,10 @@ package net.abhinavsarkar.jywrapper;
|
|||
|
||||
import static net.abhinavsarkar.jywrapper.Messages._;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
|
||||
import org.python.core.Py;
|
||||
import org.python.core.PyClass;
|
||||
import org.python.core.PyFunction;
|
||||
|
@ -83,4 +87,32 @@ final class Util {
|
|||
return word.replaceAll("([A-Z])", "_$1").toLowerCase(); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
}
|
||||
|
||||
static PyString resolvePath(final URI pythonPath) {
|
||||
PyString resolvedPath = null;
|
||||
if (pythonPath.getScheme().equals("jar")) {
|
||||
final String schemeSpecificPart = pythonPath.getSchemeSpecificPart();
|
||||
final int lastIndexOf = schemeSpecificPart.lastIndexOf("!");
|
||||
final String jarPath = schemeSpecificPart.substring(5, lastIndexOf);
|
||||
final File file = new File(jarPath);
|
||||
if (file.exists()) {
|
||||
try {
|
||||
resolvedPath = Py.newString(file.getCanonicalPath()
|
||||
+ schemeSpecificPart.substring(lastIndexOf + 1));
|
||||
} catch (final IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
} else if (pythonPath.getScheme().equals("file")) {
|
||||
final File file = new File(pythonPath);
|
||||
if (file.exists()) {
|
||||
try {
|
||||
resolvedPath = Py.newString(file.getCanonicalPath());
|
||||
} catch (final IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
return resolvedPath;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -14,4 +14,4 @@ JyWrapper.12=Trying to get instance attribute "{0}" from a Python Type
|
|||
JyWrapper.13=Can''t set attribute: {0}
|
||||
JyWrapper.14=Trying to set instance attribute "{0}" in a python class
|
||||
JyWrapper.15=No {0} named "{1}" in the backing Python Type {2}
|
||||
PyImportLoader.1=Python Import "{0}" not found in pythonpath
|
||||
PyImportLoader.1=Python Import "{0}" not found in pythonpath {1}
|
||||
|
|
Loading…
Reference in New Issue