diff --git a/.classpath b/.classpath
index c7ecb244..419d8915 100644
--- a/.classpath
+++ b/.classpath
@@ -9,5 +9,10 @@
+
+
+
+
+
diff --git a/Base - Launch Mode in Eclipse.launch b/Base - Launch Mode in Eclipse.launch
index d1cafdd9..6300d573 100644
--- a/Base - Launch Mode in Eclipse.launch
+++ b/Base - Launch Mode in Eclipse.launch
@@ -11,17 +11,17 @@
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
diff --git a/build.xml b/build.xml
index f540bd49..6704468e 100644
--- a/build.xml
+++ b/build.xml
@@ -38,6 +38,7 @@
+
@@ -93,6 +94,9 @@
+
+
+
@@ -131,6 +135,10 @@
+
+
+
+
diff --git a/buildtime/lib/jyni/JyNI-2.7-alpha.5-bin-all-platforms-64/JyNI.dll/python27.dll b/buildtime/lib/jyni/JyNI-2.7-alpha.5-bin-all-platforms-64/JyNI.dll/python27.dll
new file mode 100755
index 00000000..73682764
Binary files /dev/null and b/buildtime/lib/jyni/JyNI-2.7-alpha.5-bin-all-platforms-64/JyNI.dll/python27.dll differ
diff --git a/buildtime/lib/jyni/JyNI-2.7-alpha.5-bin-all-platforms-64/libJyNI-Loader.dylib b/buildtime/lib/jyni/JyNI-2.7-alpha.5-bin-all-platforms-64/libJyNI-Loader.dylib
new file mode 100755
index 00000000..6d9b2954
Binary files /dev/null and b/buildtime/lib/jyni/JyNI-2.7-alpha.5-bin-all-platforms-64/libJyNI-Loader.dylib differ
diff --git a/buildtime/lib/jyni/JyNI-2.7-alpha.5-bin-all-platforms-64/libJyNI-Loader.so b/buildtime/lib/jyni/JyNI-2.7-alpha.5-bin-all-platforms-64/libJyNI-Loader.so
new file mode 100755
index 00000000..81618507
Binary files /dev/null and b/buildtime/lib/jyni/JyNI-2.7-alpha.5-bin-all-platforms-64/libJyNI-Loader.so differ
diff --git a/buildtime/lib/jyni/JyNI-2.7-alpha.5-bin-all-platforms-64/libJyNI.dylib b/buildtime/lib/jyni/JyNI-2.7-alpha.5-bin-all-platforms-64/libJyNI.dylib
new file mode 100755
index 00000000..27460ff9
Binary files /dev/null and b/buildtime/lib/jyni/JyNI-2.7-alpha.5-bin-all-platforms-64/libJyNI.dylib differ
diff --git a/buildtime/lib/jyni/JyNI-2.7-alpha.5-bin-all-platforms-64/libJyNI.so b/buildtime/lib/jyni/JyNI-2.7-alpha.5-bin-all-platforms-64/libJyNI.so
new file mode 100755
index 00000000..1ee3becc
Binary files /dev/null and b/buildtime/lib/jyni/JyNI-2.7-alpha.5-bin-all-platforms-64/libJyNI.so differ
diff --git a/buildtime/lib/jyni/JyNI-2.7-alpha.5.zip b/buildtime/lib/jyni/JyNI-2.7-alpha.5.zip
new file mode 100644
index 00000000..58099a5c
Binary files /dev/null and b/buildtime/lib/jyni/JyNI-2.7-alpha.5.zip differ
diff --git a/buildtime/lib/jyni/JyNI.jar b/buildtime/lib/jyni/JyNI.jar
new file mode 100644
index 00000000..7cec7808
Binary files /dev/null and b/buildtime/lib/jyni/JyNI.jar differ
diff --git a/runtime/src/jycessing/LibraryImporter.java b/runtime/src/jycessing/LibraryImporter.java
index 004f2299..a4480398 100644
--- a/runtime/src/jycessing/LibraryImporter.java
+++ b/runtime/src/jycessing/LibraryImporter.java
@@ -28,7 +28,7 @@
import org.python.core.PyStringMap;
import org.python.core.PySystemState;
import org.python.google.common.base.Joiner;
-import org.python.util.InteractiveConsole;
+import org.python.util.PythonInterpreter;
import processing.core.PApplet;
@@ -68,9 +68,9 @@ private static void log(final String msg) {
/*
* The interpreter into which we inject import statements.
*/
- private final InteractiveConsole interp;
+ private final PythonInterpreter interp;
- public LibraryImporter(final List libdirs, final InteractiveConsole interp) {
+ public LibraryImporter(final List libdirs, final PythonInterpreter interp) {
this.libSearchPath = libdirs;
this.interp = interp;
diff --git a/runtime/src/jycessing/PAppletJythonDriver.java b/runtime/src/jycessing/PAppletJythonDriver.java
index dd7824f0..ae8b1668 100644
--- a/runtime/src/jycessing/PAppletJythonDriver.java
+++ b/runtime/src/jycessing/PAppletJythonDriver.java
@@ -58,7 +58,7 @@
import org.python.core.PyTuple;
import org.python.core.PyType;
import org.python.core.PyUnicode;
-import org.python.util.InteractiveConsole;
+import org.python.util.PythonInterpreter;
import com.google.common.base.Charsets;
import com.google.common.io.Files;
@@ -103,7 +103,7 @@ public class PAppletJythonDriver extends PApplet {
private PythonSketchError terminalException = null;
protected final PyStringMap builtins;
- protected final InteractiveConsole interp;
+ protected final PythonInterpreter interp;
private final Path pySketchPath;
private final String programText;
private final WrappedPrintStream wrappedStdout;
@@ -253,6 +253,7 @@ private static PythonSketchError toSketchException(Throwable t) {
}
if (t instanceof PyException) {
final PyException e = (PyException) t;
+ System.err.println(t);
final Pattern tbParse =
Pattern.compile("^\\s*File \"([^\"]+)\", line (\\d+)", Pattern.MULTILINE);
final Matcher m = tbParse.matcher(e.toString());
@@ -272,7 +273,7 @@ private static PythonSketchError toSketchException(Throwable t) {
line = Integer.parseInt(m.group(2)) - 1;
}
if (((PyType) e.type).getName().equals("ImportError")) {
- final Pattern importStar = Pattern.compile("import\\s+\\*");
+ final Pattern importStar = Pattern.compile("import +\\* *$");
if (importStar.matcher(e.toString()).find()) {
return new PythonSketchError("import * does not work in this environment.", file, line);
}
@@ -376,7 +377,7 @@ public void frameMoved(final int x, final int y) {
}
public PAppletJythonDriver(
- final InteractiveConsole interp,
+ final PythonInterpreter interp,
final String pySketchPath,
final String programText,
final Printer stdout)
diff --git a/runtime/src/jycessing/Runner.java b/runtime/src/jycessing/Runner.java
index a8d35477..e6936249 100644
--- a/runtime/src/jycessing/Runner.java
+++ b/runtime/src/jycessing/Runner.java
@@ -36,7 +36,6 @@
import org.python.core.PyObject;
import org.python.core.PyStringMap;
import org.python.core.PySystemState;
-import org.python.util.InteractiveConsole;
import org.python.util.PythonInterpreter;
import jycessing.launcher.LaunchHelper;
@@ -291,8 +290,7 @@ public static synchronized void runSketchBlocking(
// Suppress sys-package-manager output.
props.setProperty("python.verbose", "error");
// Prevent "Failed to install '': java.nio.charset.UnsupportedCharsetException: cp0."
- props.put("python.console.encoding", "UTF-8");
- props.put("python.import.site", "false");
+ props.put("python.console.encoding", "UTF-8");
// Can be handy for class loading issues and the like.
// props.setProperty("python.verbose", "debug");
@@ -318,7 +316,7 @@ public static synchronized void runSketchBlocking(
final PyStringMap builtins = (PyStringMap) sys.getBuiltins();
final PyStringMap originalBuiltins = builtins.copy();
try {
- final InteractiveConsole interp = new InteractiveConsole();
+ final PythonInterpreter interp = new PythonInterpreter();
// For moar useful error messages.
interp.set("__file__", sketch.getMainFile().getAbsolutePath());
@@ -355,6 +353,9 @@ public static synchronized void runSketchBlocking(
for (final String lib : userLibs) {
sys.path.insert(0, Py.newString(lib));
}
+ for (final String lib : SystemPython.getSysPath()) {
+ sys.path.add(Py.newString(lib));
+ }
// Make fake "launcher" module available to sketches - will only work with standalone sketches
interp.exec(LAUNCHER_TEXT);
diff --git a/runtime/src/jycessing/SystemPython.java b/runtime/src/jycessing/SystemPython.java
new file mode 100644
index 00000000..89aa8502
--- /dev/null
+++ b/runtime/src/jycessing/SystemPython.java
@@ -0,0 +1,54 @@
+package jycessing;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.List;
+
+/** Utilities for querying the existence and properties of the system Python, if any. */
+public class SystemPython {
+
+ public static File getSystemPython() {
+ return new File("/Users/feinberg/numpy/bin/python").getAbsoluteFile();
+ }
+
+ public static boolean nativePythonAvailable() {
+ try {
+ return Runtime.getRuntime().exec(getSystemPython().getAbsolutePath() + " --version").waitFor()
+ == 0;
+ } catch (final Exception e) {
+ return false;
+ }
+ }
+
+ public static List getSysPath() {
+ final List result = new ArrayList<>();
+ try {
+ final Process p =
+ new ProcessBuilder(
+ getSystemPython().getAbsolutePath(),
+ "-c",
+ "import sys\nfor p in sys.path:print p")
+ .start();
+ final BufferedReader in =
+ new BufferedReader(new InputStreamReader(p.getInputStream(), StandardCharsets.UTF_8));
+ final BufferedReader err =
+ new BufferedReader(new InputStreamReader(p.getErrorStream(), StandardCharsets.UTF_8));
+ String pathElement = null;
+ while ((pathElement = in.readLine()) != null) {
+ result.add(pathElement);
+ }
+ String s;
+ while ((s = err.readLine()) != null) {
+ System.err.println(s);
+ }
+ p.waitFor();
+ } catch (InterruptedException | IOException e) {
+ System.err.println(e);
+ }
+ return result;
+ }
+}
diff --git a/runtime/src/jycessing/mode/FormatServer.java b/runtime/src/jycessing/mode/FormatServer.java
index e508de57..27fb6752 100644
--- a/runtime/src/jycessing/mode/FormatServer.java
+++ b/runtime/src/jycessing/mode/FormatServer.java
@@ -6,6 +6,7 @@
import java.io.IOException;
import java.net.Socket;
+import jycessing.SystemPython;
import processing.app.Formatter;
import processing.app.Platform;
import processing.app.exec.StreamPump;
@@ -31,14 +32,6 @@ public FormatServer(final File modeHome) {
this.modeHome = modeHome;
}
- private static boolean nativePythonAvailable() {
- try {
- return Runtime.getRuntime().exec("python --version").waitFor() == 0;
- } catch (final Exception e) {
- return false;
- }
- }
-
/**
* If a python exectuable is available on this machine, use it to run the formatting server.
* Otherwise, use the same Java that ran the PDE to interpret the formatting server with Jython,
@@ -48,9 +41,9 @@ private static boolean nativePythonAvailable() {
* @return a ProcessBuilder that, when started, will run the formatting server.
*/
private ProcessBuilder getPythonProcess(final String formatServerPath) {
- if (nativePythonAvailable()) {
+ if (SystemPython.nativePythonAvailable()) {
log("Native python available for formatting.");
- return new ProcessBuilder("python", formatServerPath);
+ return new ProcessBuilder(SystemPython.getSystemPython().getAbsolutePath(), formatServerPath);
}
log("Native python not available for formatting.");
final String jython = new File(modeHome, "mode/jython.jar").getAbsolutePath();
diff --git a/runtime/src/jycessing/mode/run/RMIUtils.java b/runtime/src/jycessing/mode/run/RMIUtils.java
index 0b0d7295..0d388c3d 100644
--- a/runtime/src/jycessing/mode/run/RMIUtils.java
+++ b/runtime/src/jycessing/mode/run/RMIUtils.java
@@ -4,6 +4,7 @@
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
+import java.rmi.AlreadyBoundException;
import java.rmi.Remote;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
@@ -89,7 +90,13 @@ public static void bind(final Remote remote, final Class extends Remote> remot
+ remote.getClass().getName()
+ " to registry as "
+ registryKey);
- registry().bind(registryKey, stub);
+ try {
+ registry().bind(registryKey, stub);
+ } catch (final AlreadyBoundException e) {
+ System.err.println(registryKey + " already bound. Trying to unbind.");
+ registry().unbind(registryKey);
+ registry().bind(registryKey, stub);
+ }
log("Bound.");
Runtime.getRuntime()
.addShutdownHook(
diff --git a/runtime/src/jycessing/mode/run/SketchServiceProcess.java b/runtime/src/jycessing/mode/run/SketchServiceProcess.java
index b3eb4d22..d9d7fad0 100644
--- a/runtime/src/jycessing/mode/run/SketchServiceProcess.java
+++ b/runtime/src/jycessing/mode/run/SketchServiceProcess.java
@@ -14,10 +14,13 @@
import java.rmi.RemoteException;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.HashSet;
import java.util.List;
+import java.util.Set;
import java.util.regex.Pattern;
import com.google.common.base.Joiner;
+import com.google.common.base.Splitter;
import jycessing.mode.PyEditor;
import jycessing.mode.PythonMode;
@@ -130,7 +133,16 @@ private ProcessBuilder createServerCommand() {
command.add("-Dverbose=true");
}
- command.add("-Djava.library.path=" + System.getProperty("java.library.path"));
+ final Set libraryPath =
+ new HashSet<>(
+ Splitter.on(File.pathSeparatorChar)
+ .splitToList(System.getProperty("java.library.path")));
+ libraryPath.add(
+ new File(
+ mode.getContentFile("mode").getAbsolutePath(),
+ "JyNI-2.7-alpha.5-bin-all-platforms-64")
+ .getAbsolutePath());
+ command.add("-Djava.library.path=" + Joiner.on(File.pathSeparatorChar).join(libraryPath));
final List cp = new ArrayList<>();
cp.addAll(