Implement flush in fake streams to fix
MODIFY
runtime/src/jycessing/DevNullPrinter.java
runtime/src/jycessing/DevNullPrinter.java
@@ -8,4 +8,9 @@ public class DevNullPrinter implements Printer {
public void print(final Object o) {
// no-op
}
+
+ @Override
+ public void flush() {
+ // no-op
+ }
}

MODIFY
runtime/src/jycessing/Printer.java
runtime/src/jycessing/Printer.java
@@ -2,4 +2,6 @@ package jycessing;
public interface Printer {
void print(Object o);
+
+ void flush();
}

MODIFY
runtime/src/jycessing/StreamPrinter.java
runtime/src/jycessing/StreamPrinter.java
@@ -15,4 +15,9 @@ public class StreamPrinter implements Printer {
stream.print(String.valueOf(o));
stream.flush();
}
+
+ @Override
+ public void flush() {
+ stream.flush();
+ }
}

MODIFY
runtime/src/jycessing/core.py
runtime/src/jycessing/core.py
@@ -616,11 +616,15 @@ __builtin__.open = __open__
class FakeStdOut():
def write(self, s):
__stdout__.print(s)
+ def flush(self):
+ __stdout__.flush()
sys.stdout = FakeStdOut()
class FakeStdErr():
def write(self, s):
__stderr__.print(s)
+ def flush(self):
+ __stderr__.flush()
sys.stderr = FakeStdErr()
del FakeStdOut, FakeStdErr

MODIFY
runtime/src/jycessing/mode/run/SketchRunner.java
runtime/src/jycessing/mode/run/SketchRunner.java
package jycessing.mode.run;
-import java.awt.Point;
import java.rmi.RemoteException;
import jycessing.Printer;
@@ -36,24 +35,20 @@ public class SketchRunner implements SketchService {
System.err.println(e.getMessage());
}
}
- new Thread(new Runnable() {
- @Override
- public void run() {
- Runner.warmup();
- }
- }, "SketchRunner Warmup Thread").start();
+ new Thread(() -> Runner.warmup(), "SketchRunner Warmup Thread").start();
}
/**
- * On Mac, even though this app has no menu, there's still a
- * built-in cmd-Q handler that, by default, quits the app.
- * Because starting up the {@link SketchRunner} is expensive,
- * we'd prefer to leave the app running.
- * <p>This function responds to a user cmd-Q by stopping the
- * currently running sketch, and rejecting the attempt to quit.
- * <p>But if we've received a shutdown request from the
- * {@link SketchServiceProcess} on the PDE VM, then we permit
- * the quit to proceed.
+ * On Mac, even though this app has no menu, there's still a built-in cmd-Q handler that, by
+ * default, quits the app. Because starting up the {@link SketchRunner} is expensive, we'd prefer
+ * to leave the app running.
+ *
+ * <p>This function responds to a user cmd-Q by stopping the currently running sketch, and
+ * rejecting the attempt to quit.
+ *
+ * <p>But if we've received a shutdown request from the {@link SketchServiceProcess} on the PDE
+ * VM, then we permit the quit to proceed.
+ *
* @return true iff the SketchRunner should quit.
*/
public boolean preventUserQuit() {
@@ -62,12 +57,7 @@ public class SketchRunner implements SketchService {
return true;
}
log("Cancelling quit, but stopping sketch.");
- new Thread(new Runnable() {
- @Override
- public void run() {
- stopSketch();
- }
- }).start();
+ new Thread(() -> stopSketch()).start();
return false;
}
@@ -80,12 +70,13 @@ public class SketchRunner implements SketchService {
@Override
public void startSketch(final PdeSketch sketch) {
- runner = new Thread(new Runnable() {
- @Override
- public void run() {
+ runner =
+ new Thread(
+ () -> {
try {
try {
- final Printer stdout = new Printer() {
+ final Printer stdout =
+ new Printer() {
@Override
public void print(final Object o) {
try {
@@ -94,8 +85,14 @@ public class SketchRunner implements SketchService {
System.err.println(e);
}
}
+
+ @Override
+ public void flush() {
+ // no-op
+ }
};
- final Printer stderr = new Printer() {
+ final Printer stderr =
+ new Printer() {
@Override
public void print(final Object o) {
try {
@@ -104,40 +101,45 @@ public class SketchRunner implements SketchService {
System.err.println(e);
}
}
- };
- final SketchPositionListener sketchPositionListener = new SketchPositionListener() {
+
@Override
- public void sketchMoved(final Point leftTop) {
+ public void flush() {
+ // no-op
+ }
+ };
+ final SketchPositionListener sketchPositionListener =
+ leftTop -> {
try {
modeService.handleSketchMoved(id, leftTop);
} catch (final RemoteException e) {
System.err.println(e);
}
- }
};
Runner.runSketchBlocking(sketch, stdout, stderr, sketchPositionListener);
- } catch (final PythonSketchError e) {
- log("Sketch runner caught " + e);
- modeService
- .handleSketchException(id, convertPythonSketchError(e, sketch.codeFileNames));
- } catch (final Exception e) {
- if (e.getCause() != null && e.getCause() instanceof PythonSketchError) {
- modeService.handleSketchException(id, convertPythonSketchError((PythonSketchError)e
- .getCause(), sketch.codeFileNames));
+ } catch (final PythonSketchError e1) {
+ log("Sketch runner caught " + e1);
+ modeService.handleSketchException(
+ id, convertPythonSketchError(e1, sketch.codeFileNames));
+ } catch (final Exception e2) {
+ if (e2.getCause() != null && e2.getCause() instanceof PythonSketchError) {
+ modeService.handleSketchException(
+ id,
+ convertPythonSketchError(
+ (PythonSketchError) e2.getCause(), sketch.codeFileNames));
} else {
- modeService.handleSketchException(id, e);
+ modeService.handleSketchException(id, e2);
}
} finally {
log("Handling sketch stoppage...");
modeService.handleSketchStopped(id);
}
- } catch (final RemoteException e) {
- log(e.toString());
+ } catch (final RemoteException e3) {
+ log(e3.toString());
}
// Exiting; no need to interrupt and join it later.
runner = null;
- }
- }, "processing.py mode runner");
+ },
+ "processing.py mode runner");
runner.start();
}
@@ -172,12 +174,10 @@ public class SketchRunner implements SketchService {
private static class ModeWaiterImpl implements ModeWaiter {
final String id;
-
public ModeWaiterImpl(final String id) {
this.id = id;
}
-
@Override
public void modeReady(final ModeService modeService) {
try {
@@ -205,27 +205,27 @@ public class SketchRunner implements SketchService {
}
}
- private static void launch(final String id, final ModeService modeService) throws RMIProblem,
- RemoteException {
+ private static void launch(final String id, final ModeService modeService)
+ throws RMIProblem, RemoteException {
final SketchRunner sketchRunner = new SketchRunner(id, modeService);
final SketchService stub = (SketchService) RMIUtils.export(sketchRunner);
log("Calling mode's handleReady().");
modeService.handleReady(id, stub);
- Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
- @Override
- public void run() {
+ Runtime.getRuntime()
+ .addShutdownHook(
+ new Thread(
+ () -> {
log("Exiting; telling modeService.");
try {
modeService.handleSketchStopped(id);
} catch (final RemoteException e) {
// nothing we can do about it now.
}
- }
}));
}
- private SketchException convertPythonSketchError(final PythonSketchError e,
- final String[] fileNames) {
+ private SketchException convertPythonSketchError(
+ final PythonSketchError e, final String[] fileNames) {
if (e.fileName == null) {
return new SketchException(e.getMessage());
}
@@ -247,5 +247,4 @@ public class SketchRunner implements SketchService {
}
return new SketchException(e.getMessage(), fileIndex, e.line, e.column);
}
-
}

MODIFY
testing/src/test/jycessing/JycessingTests.java
testing/src/test/jycessing/JycessingTests.java
@@ -12,6 +12,8 @@ import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
+import org.junit.Test;
+
import jycessing.MixedModeError;
import jycessing.PAppletJythonDriver;
import jycessing.Printer;
@@ -19,8 +21,6 @@ import jycessing.PythonSketchError;
import jycessing.Runner;
import jycessing.StreamPrinter;
-import org.junit.Test;
-
public class JycessingTests {
private static class CapturingPrinter implements Printer {
@@ -32,17 +32,22 @@ public class JycessingTests {
out.print(String.valueOf(o));
}
+ @Override
+ public void flush() {
+ out.flush();
+ }
+
public String getText() {
try {
- return new String(baos.toByteArray(), "utf-8").replaceAll("\r\n", "\n").replaceAll("\r",
- "\n");
+ return new String(baos.toByteArray(), "utf-8")
+ .replaceAll("\r\n", "\n")
+ .replaceAll("\r", "\n");
} catch (final UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
}
}
-
private static String run(final String testResource) throws Exception {
System.err.println("Running " + testResource + " test.");
final Path source = Paths.get("testing/resources/test_" + testResource + ".py");
@@ -62,7 +67,9 @@ public class JycessingTests {
final Path src = Paths.get(tmp.toString(), "test_import_" + module + ".pyde");
try {
final String testText = "import " + module + "\nprint 'OK'\nexit()";
- Files.copy(new ByteArrayInputStream(testText.getBytes("utf-8")), src,
+ Files.copy(
+ new ByteArrayInputStream(testText.getBytes("utf-8")),
+ src,
StandardCopyOption.REPLACE_EXISTING);
final CapturingPrinter out = new CapturingPrinter();
System.err.println("Running import " + module + " test.");
@@ -79,7 +86,6 @@ public class JycessingTests {
assertEquals("OK\n", run(testName));
}
-
@Test
public void inherit_str() throws Exception {
assertEquals("cosmic\n12\n[12, 13]\n", run("inherit_str"));
@@ -288,8 +294,16 @@ public class JycessingTests {
public void matrix3d_print() throws Exception {
final String actual = run("pmatrixprint");
final String expected =
- " 1.0000 0.0000 0.0000 0.0000\n" + " 0.0000 1.0000 0.0000 0.0000\n"
- + " 0.0000 0.0000 1.0000 0.0000\n" + " 0.0000 0.0000 0.0000 1.0000\n\n";
+ " 1.0000 0.0000 0.0000 0.0000\n"
+ + " 0.0000 1.0000 0.0000 0.0000\n"
+ + " 0.0000 0.0000 1.0000 0.0000\n"
+ + " 0.0000 0.0000 0.0000 1.0000\n\n";
assertEquals(expected, actual);
}
+
+ // https://github.com/jdf/processing.py/issues/264
+ @Test
+ public void unittest() throws Exception {
+ expectOK("unittest");
+ }
}

Implement flush in fake streams to fix #264.