Browse Source

Added support for importing Python modules from paths other than Java Classpath.

Abhinav Sarkar 11 years ago
parent
commit
906e5222f3

+ 1
- 0
.classpath View File

@@ -1,6 +1,7 @@
1 1
 <?xml version="1.0" encoding="UTF-8"?>
2 2
 <classpath>
3 3
 	<classpathentry kind="src" path="src/main/java"/>
4
+	<classpathentry excluding="src/example/java/|src/main/java/" including="Lib/" kind="src" path=""/>
4 5
 	<classpathentry kind="src" path="src/example/java"/>
5 6
 	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
6 7
 	<classpathentry kind="var" path="JYTHON_HOME/jython.jar" sourcepath="/JYTHON_HOME/src"/>

+ 4
- 1
.pydevproject View File

@@ -2,6 +2,9 @@
2 2
 <?eclipse-pydev version="1.0"?>
3 3
 
4 4
 <pydev_project>
5
-<pydev_property name="org.python.pydev.PYTHON_PROJECT_VERSION">python 2.6</pydev_property>
5
+<pydev_property name="org.python.pydev.PYTHON_PROJECT_VERSION">jython 2.5</pydev_property>
6 6
 <pydev_property name="org.python.pydev.PYTHON_PROJECT_INTERPRETER">Default</pydev_property>
7
+<pydev_pathproperty name="org.python.pydev.PROJECT_SOURCE_PATH">
8
+<path>/jywrapper/Lib</path>
9
+</pydev_pathproperty>
7 10
 </pydev_project>

src/example/java/person.py → Lib/person.py View File


+ 12
- 0
src/example/java/net/abhinavsarkar/jywrapper/example/DependentTest.java View File

@@ -8,6 +8,18 @@ import org.junit.Test;
8 8
 
9 9
 public class DependentTest {
10 10
 
11
+	private static final String PYLIB_DIR_NAME = "Lib";
12
+
13
+	static {
14
+		try {
15
+			JyWrapper.addToPythonPath(
16
+					DependentTest.class.getClassLoader()
17
+						.getResource(PYLIB_DIR_NAME).toURI());
18
+		} catch (final Exception e) {
19
+			throw new RuntimeException(e);
20
+		}
21
+	}
22
+
11 23
 	private final Employee Employee_ = JyWrapper.wrap(Employee.class, "person.Employee");
12 24
 
13 25
 	private final Dependent Dependent_ = JyWrapper.wrap(Dependent.class, "person.Dependent");

+ 13
- 0
src/example/java/net/abhinavsarkar/jywrapper/example/EmployeeTest.java View File

@@ -3,12 +3,25 @@ package net.abhinavsarkar.jywrapper.example;
3 3
 import static org.junit.Assert.assertEquals;
4 4
 import static org.junit.Assert.assertFalse;
5 5
 import static org.junit.Assert.assertTrue;
6
+
6 7
 import net.abhinavsarkar.jywrapper.JyWrapper;
7 8
 
8 9
 import org.junit.Test;
9 10
 
10 11
 public class EmployeeTest {
11 12
 
13
+	private static final String PYLIB_DIR_NAME = "Lib";
14
+
15
+	static {
16
+		try {
17
+			JyWrapper.addToPythonPath(
18
+					DependentTest.class.getClassLoader()
19
+						.getResource(PYLIB_DIR_NAME).toURI());
20
+		} catch (final Exception e) {
21
+			throw new RuntimeException(e);
22
+		}
23
+	}
24
+
12 25
 	private final Employee Employee_ = JyWrapper.wrap(Employee.class, "person.Employee");
13 26
 
14 27
 	private final Dependent Dependent_ = JyWrapper.wrap(Dependent.class, "person.Dependent");

+ 36
- 16
src/main/java/net/abhinavsarkar/jywrapper/JyWrapper.java View File

@@ -2,14 +2,17 @@ package net.abhinavsarkar.jywrapper;
2 2
 
3 3
 import static net.abhinavsarkar.jywrapper.Messages._;
4 4
 
5
-
5
+import java.net.URI;
6 6
 import net.abhinavsarkar.jywrapper.annotation.Wraps;
7 7
 import net.abhinavsarkar.jywrapper.exception.PythonImportNotFoundException;
8 8
 
9
+import org.python.core.Py;
9 10
 import org.python.core.PyClass;
10 11
 import org.python.core.PyFunction;
11 12
 import org.python.core.PyModule;
12 13
 import org.python.core.PyObject;
14
+import org.python.core.PyString;
15
+import org.python.core.PySystemState;
13 16
 import org.python.core.PyType;
14 17
 
15 18
 /**
@@ -18,7 +21,7 @@ import org.python.core.PyType;
18 21
  * @param <T>	The type of the java class to wrap the Python class/module with.
19 22
  */
20 23
 public final class JyWrapper {
21
-	
24
+
22 25
 	private JyWrapper() {
23 26
 	}
24 27
 
@@ -27,20 +30,20 @@ public final class JyWrapper {
27 30
 		if (annotation == null) {
28 31
 			throw new PythonImportNotFoundException(_("JyWrapper.7", javaClass));  //$NON-NLS-1$
29 32
 		}
30
-		
33
+
31 34
 		return wrap(javaClass, annotation.value());
32 35
 	}
33 36
 
34 37
 	/**
35 38
 	 * @param pyImportName	The full import name of the Python class/module
36 39
 	 * 		to wrap.
37
-	 * @return	An instance of {@link UninitedPyObjectWrapper}, ready to be 
40
+	 * @return	An instance of {@link UninitedPyObjectWrapper}, ready to be
38 41
 	 * 		initialized.
39 42
 	 * @throws	IllegalStateException Thrown if the java Class to be used to
40
-	 * 		wrap the Python module/class, has not been supplied by earlier 
43
+	 * 		wrap the Python module/class, has not been supplied by earlier
41 44
 	 * 		calling {@link JyWrapper#with(Class)}.
42 45
 	 * @throws IllegalArgumentException Thrown if the pyImportName parameter
43
-	 * 		is null.	
46
+	 * 		is null.
44 47
 	 */
45 48
 	public static <T> T wrap(final Class<T> javaClass, final String pyImportName) {
46 49
 		if (javaClass == null) {
@@ -49,24 +52,24 @@ public final class JyWrapper {
49 52
 		if (pyImportName == null) {
50 53
 			throw new IllegalArgumentException(_("JyWrapper.6", "pyImportName"));   //$NON-NLS-1$ //$NON-NLS-2$
51 54
 		}
52
-		
55
+
53 56
 		final PyObject pyImport = PyImportLoader.loadPyImport(pyImportName);
54
-		if (!(pyImport instanceof PyType 
55
-				|| pyImport instanceof PyModule 
57
+		if (!(pyImport instanceof PyType
58
+				|| pyImport instanceof PyModule
56 59
 				|| pyImport instanceof PyClass)) {
57 60
 			throw new IllegalArgumentException(_("JyWrapper.5", pyImportName));  //$NON-NLS-1$
58 61
 		}
59 62
 		return Util.py2Java(pyImport, javaClass);
60 63
 	}
61
-	
64
+
62 65
 	/**
63
-	 * @param <T>			The return type of the {@link PyCallable} instance. 
66
+	 * @param <T>			The return type of the {@link PyCallable} instance.
64 67
 	 * @param pyImportName	The full import name of the Python function to wrap.
65 68
 	 * @param returnType	The class of the return type.
66 69
 	 * @return				An instance of {@link PyCallable} which wraps the
67 70
 	 * 		Python function given in parameter.
68
-	 * @throws	IllegalArgumentException Thrown if the any of the parameters 
69
-	 * 		supplied are null or if the pyImportName parameter supplied does not 
71
+	 * @throws	IllegalArgumentException Thrown if the any of the parameters
72
+	 * 		supplied are null or if the pyImportName parameter supplied does not
70 73
 	 * 		correspond to a Python function.
71 74
 	 */
72 75
 	public static <T> PyCallable<T> wrapPyFunction(
@@ -77,16 +80,33 @@ public final class JyWrapper {
77 80
 		if (returnType == null) {
78 81
 			throw new IllegalArgumentException(_("JyWrapper.6", "returnType"));   //$NON-NLS-1$ //$NON-NLS-2$
79 82
 		}
80
-		
83
+
81 84
 		final PyObject pyImport = PyImportLoader.loadPyImport(pyImportName);
82 85
 		if (!(pyImport instanceof PyFunction)) {
83 86
 			throw new IllegalArgumentException(_("JyWrapper.0", pyImportName));  //$NON-NLS-1$
84 87
 		}
85
-		
88
+
86 89
 		@SuppressWarnings("unchecked")
87 90
 		final PyCallable<T> newInstance = PyObjectProxy.newInstance(
88 91
 				pyImport, PyCallable.class);
89 92
 		return newInstance;
90 93
 	}
91
-	
94
+
95
+	public static void addToPythonPath(final URI path) {
96
+		final PySystemState pySystemState = Py.getSystemState();
97
+		final PyString resolvedPath = Util.resolvePath(path);
98
+		if (resolvedPath != null && !pySystemState.path.contains(resolvedPath)) {
99
+			pySystemState.path.append(resolvedPath);
100
+		}
101
+	}
102
+
103
+
104
+	public static void removeFromPythonPath(final URI path) {
105
+		final PySystemState pySystemState = Py.getSystemState();
106
+		final PyString resolvedPath = Util.resolvePath(path);
107
+		if (resolvedPath != null && pySystemState.path.contains(resolvedPath)) {
108
+			pySystemState.path.remove(resolvedPath);
109
+		}
110
+	}
111
+
92 112
 }

+ 4
- 4
src/main/java/net/abhinavsarkar/jywrapper/PyImportLoader.java View File

@@ -9,7 +9,6 @@ import net.abhinavsarkar.jywrapper.exception.PythonImportNotFoundException;
9 9
 import org.python.core.Py;
10 10
 import org.python.core.PyException;
11 11
 import org.python.core.PyObject;
12
-import org.python.core.PySystemState;
13 12
 
14 13
 /**
15 14
  * @author AbhinavSarkar
@@ -17,8 +16,8 @@ import org.python.core.PySystemState;
17 16
  */
18 17
 public final class PyImportLoader {
19 18
 
20
-	private static final PyObject importer = new PySystemState().getBuiltins()
21
-		.__getitem__(Py.newString("__import__")); //$NON-NLS-1$
19
+	private static final PyObject importer =
20
+		Py.getSystemState().getBuiltins().__getitem__(Py.newString("__import__"));
22 21
 
23 22
 	private static final ConcurrentHashMap<String, PyObject> loadedPyImports =
24 23
 		new ConcurrentHashMap<String, PyObject>();
@@ -35,7 +34,7 @@ public final class PyImportLoader {
35 34
 			throws PythonImportNotFoundException {
36 35
 		if (!loadedPyImports.containsKey(fullImportName)) {
37 36
 			final int i = fullImportName.lastIndexOf('.');
38
-			final String errorMsg = _("PyImportLoader.1", fullImportName); //$NON-NLS-1$
37
+			final String errorMsg = _("PyImportLoader.1", fullImportName, Py.getSystemState().path); //$NON-NLS-1$
39 38
 			PyObject pyImport;
40 39
 			if (i == -1) {
41 40
 				final String pyModuleName = fullImportName;
@@ -59,4 +58,5 @@ public final class PyImportLoader {
59 58
 		}
60 59
 		return loadedPyImports.get(fullImportName);
61 60
 	}
61
+
62 62
 }

+ 32
- 0
src/main/java/net/abhinavsarkar/jywrapper/Util.java View File

@@ -2,6 +2,10 @@ package net.abhinavsarkar.jywrapper;
2 2
 
3 3
 import static net.abhinavsarkar.jywrapper.Messages._;
4 4
 
5
+import java.io.File;
6
+import java.io.IOException;
7
+import java.net.URI;
8
+
5 9
 import org.python.core.Py;
6 10
 import org.python.core.PyClass;
7 11
 import org.python.core.PyFunction;
@@ -83,4 +87,32 @@ final class Util {
83 87
 		return word.replaceAll("([A-Z])", "_$1").toLowerCase();   //$NON-NLS-1$ //$NON-NLS-2$
84 88
 	}
85 89
 
90
+	static PyString resolvePath(final URI pythonPath) {
91
+		PyString resolvedPath = null;
92
+		if (pythonPath.getScheme().equals("jar")) {
93
+			final String schemeSpecificPart = pythonPath.getSchemeSpecificPart();
94
+			final int lastIndexOf = schemeSpecificPart.lastIndexOf("!");
95
+			final String jarPath = schemeSpecificPart.substring(5, lastIndexOf);
96
+			final File file = new File(jarPath);
97
+			if (file.exists()) {
98
+				try {
99
+					resolvedPath = Py.newString(file.getCanonicalPath()
100
+						+ schemeSpecificPart.substring(lastIndexOf + 1));
101
+				} catch (final IOException e) {
102
+					throw new RuntimeException(e);
103
+				}
104
+			}
105
+		} else if (pythonPath.getScheme().equals("file")) {
106
+			final File file = new File(pythonPath);
107
+			if (file.exists()) {
108
+				try {
109
+					resolvedPath = Py.newString(file.getCanonicalPath());
110
+				} catch (final IOException e) {
111
+					throw new RuntimeException(e);
112
+				}
113
+			}
114
+		}
115
+		return resolvedPath;
116
+	}
117
+
86 118
 }

+ 1
- 1
src/main/java/net/abhinavsarkar/jywrapper/messages.properties View File

@@ -14,4 +14,4 @@ JyWrapper.12=Trying to get instance attribute "{0}" from a Python Type
14 14
 JyWrapper.13=Can''t set attribute: {0}
15 15
 JyWrapper.14=Trying to set instance attribute "{0}" in a python class
16 16
 JyWrapper.15=No {0} named "{1}" in the backing Python Type {2}
17
-PyImportLoader.1=Python Import "{0}" not found in pythonpath
17
+PyImportLoader.1=Python Import "{0}" not found in pythonpath {1}

Loading…
Cancel
Save