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 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(