Skip to content

Commit

Permalink
PVector static vs. instance methods now work as expected. Improved de…
Browse files Browse the repository at this point in the history
…tection of end-of-sketch.
  • Loading branch information
Jonathan Feinberg committed Sep 16, 2010
1 parent bcecffc commit 60d3bdd
Show file tree
Hide file tree
Showing 9 changed files with 106 additions and 51 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Expand Up @@ -14,4 +14,6 @@ processing-py.jar
libraries/peasycam
dist
zamples
libraries/GSVideo
test.py

2 changes: 1 addition & 1 deletion buildtime/py/processing_parser.py
Expand Up @@ -23,7 +23,7 @@
|(get|set|remove)Cache|update|destroy|main|flush|addListeners|dataFile
|die|setup|mouseE(ntered|xited)|paint|sketch[A-Z].*|stop|save(File|Path)
|displayable|method|runSketch|start|focus(Lost|Gained)|(data|create)Path
|round|abs|max|min|open|append|splice|expand|contract|set
|round|abs|max|min|open|append|splice|expand|contract|set|exit
)$
''', re.X)

Expand Down
49 changes: 37 additions & 12 deletions runtime/src/jycessing/PAppletJythonDriver.java
@@ -1,12 +1,12 @@
/*
* Copyright 2010 Jonathan Feinberg
*
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
Expand All @@ -15,12 +15,17 @@
*/
package jycessing;

import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.HashSet;
import java.util.concurrent.CountDownLatch;
import java.util.regex.Pattern;

import javax.swing.SwingUtilities;

import org.python.core.CompileMode;
import org.python.core.CompilerFlags;
import org.python.core.Py;
Expand All @@ -39,9 +44,9 @@
import processing.core.PVector;

/**
*
*
* @author Jonathan Feinberg <jdf@pobox.com>
*
*
*/
@SuppressWarnings("serial")
abstract public class PAppletJythonDriver extends PApplet {
Expand All @@ -55,6 +60,8 @@ abstract public class PAppletJythonDriver extends PApplet {
private final String pySketchPath;
private final String programText;

private final CountDownLatch finishedLatch = new CountDownLatch(1);

// A static-mode sketch must be interpreted from with the setup() method.
// All others are interpreted during construction in order to harvest method
// definitions, which we then invoke during the run loop.
Expand All @@ -77,9 +84,10 @@ abstract public class PAppletJythonDriver extends PApplet {
private void interpretSketch() {
try {
Py.setSystemState(interp.getSystemState());
Py.exec(Py.compile_flags(programText, pySketchPath,
CompileMode.exec, new CompilerFlags()), interp.getLocals(),
null);
Py.exec(
Py.compile_flags(programText, pySketchPath,
CompileMode.exec, new CompilerFlags()),
interp.getLocals(), null);
Py.flushLine();
} catch (Throwable t) {
checkForRendererChangeException(t);
Expand All @@ -103,6 +111,13 @@ public PAppletJythonDriver(final InteractiveConsole interp,
populateBuiltins();
setFields();
builtins.__setitem__("this", Py.java2py(this));
builtins.__setitem__("exit", new PyObject() {
public PyObject __call__(
final PyObject[] args, final String[] kws) {
finishedLatch.countDown();
return Py.None;
}
});

if (!isStaticMode) {
// Executing the sketch will bind method names ("draw") to PyCode
Expand All @@ -122,8 +137,18 @@ public PAppletJythonDriver(final InteractiveConsole interp,
keyReleasedMeth = interp.get("keyReleased");
keyTypedMeth = interp.get("keyTyped");
stopMeth = interp.get("stop");
addComponentListener(new ComponentAdapter() {
@Override
public void componentHidden(ComponentEvent e) {
finishedLatch.countDown();
}
});
}

public void blockUntilFinished() throws InterruptedException {
finishedLatch.await();
}

/**
* Permit the punning use of set() by mucking with the builtin "set" Type.
* If you call it with 3 arguments, it acts like the Processing set(x, y,
Expand Down Expand Up @@ -157,10 +182,9 @@ public PyObject __call__(PyObject[] args, String[] kws) {
} else if (tx == PyInteger.TYPE && ty == PyInteger.TYPE
&& tc.getProxyType() != null
&& tc.getProxyType() == PImage.class) {
set(x.asInt(),
y.asInt(),
(processing.core.PImage) c
.__tojava__(processing.core.PImage.class));
set(x.asInt(), y.asInt(),
(processing.core.PImage) c.__tojava__(
processing.core.PImage.class));
return Py.None;
} else {
return super.__call__(args, kws);
Expand Down Expand Up @@ -232,6 +256,7 @@ public void setup() {
public void draw() {
if (drawMeth == null) {
super.draw();
finishedLatch.countDown();
} else {
// Put all of PApplet's globals into the Python context
setFields();
Expand Down
14 changes: 14 additions & 0 deletions runtime/src/jycessing/Runner.java
Expand Up @@ -22,6 +22,8 @@

import processing.core.PApplet;

import java.awt.Component;
import java.awt.Window;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileFilter;
Expand All @@ -40,6 +42,8 @@
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.swing.SwingUtilities;

public class Runner {
static boolean VERBOSE = false;

Expand Down Expand Up @@ -259,9 +263,19 @@ public static void runSketch(final String[] args, final String sketchPath,

try {
PApplet.runSketch(args, applet);
applet.blockUntilFinished();
if (VERBOSE) {
System.err.println("Applet is finished. Disposing window.");
}
Window w = (Window) SwingUtilities.getRoot(applet);
w.setVisible(false);
w.dispose();
} catch (Throwable t) {
Py.printException(t);
} finally {
if (VERBOSE) {
System.err.println("Cleaning up interpreter.");
}
interp.cleanup();
}

Expand Down
7 changes: 1 addition & 6 deletions runtime/src/jycessing/core.py
Expand Up @@ -63,11 +63,6 @@ def dot(cls, a, b):
def angleBetween(cls, a, b):
return RealPVector.angleBetween(a, b)

# Because PVector isn't serializable, we have to add __deepcopy__
@monkeypatch_method(RealPVector)
def __deepcopy__(self, memo):
return PVector(self.x, self.y, self.z)

@monkeypatch_method(RealPVector)
def __sub__(a, b):
return PVector(a.x - b.x, a.y - b.y, a.z - b.z)
Expand All @@ -79,5 +74,5 @@ def __add__(a, b):
@monkeypatch_method(RealPVector)
def __mul__(a, b):
if isinstance(b, RealPVector):
return PVector(a.x + b.x, a.y + b.y, a.z + b.z)
raise TypeError("The * operator can only be used to multiply a PVector by a scalar")
return PVector(a.x * b, a.y * b, a.z * b)
3 changes: 2 additions & 1 deletion testing/test_resources/test_inherit_str.py
Expand Up @@ -8,4 +8,5 @@ def __repr__(self):
foo = Foo('cosmic')
print foo
print str(12)
print str([12,13])
print str([12,13])
noLoop()
4 changes: 1 addition & 3 deletions testing/test_resources/test_load_in_initializer.py
Expand Up @@ -8,6 +8,4 @@
def setup():
size(10, 10, P3D)
noLoop();

def draw():
print "OK"
print 'OK'
50 changes: 35 additions & 15 deletions testing/test_resources/test_pvector.py
@@ -1,23 +1,43 @@
a = PVector(5, 7, 11)
b = PVector(13, 17, 23)
assert a - b == PVector(-8.0, -10.0, -12.0)
print b - a
print b + a
print a + b

print PVector.add(a, b)
print PVector.add(a, b)
assert b - a == PVector(8, 10, 12)
c = PVector(18, 24, 34)
assert b + a == c
assert a + b == c
assert PVector.add(a, b) == c
assert PVector.add(a, b) == c
a.add(b)
print a
assert a == c
a.add(b)
print a
assert a == PVector(31.0, 41.0, 57.0)

try:
print a * b
raise AssertionError("That shouldn't have happened.")
except TypeError:
pass

print a * b
print a * 10
print a * 10
c = PVector(310.0, 410.0, 570.0)
assert a * 10 == c
assert a * 10 == c
assert PVector.mult(a, 10) == c
assert PVector.mult(a, 10) == c
a.mult(10)
print a
assert a == c

assert int(1000 * PVector.dist(a, b)) == 736116
assert PVector.cross(a, b) == PVector(-260.0, 280.0, -60.0)
assert a.cross(b) == PVector(-260.0, 280.0, -60.0)
assert PVector.dot(a, b) == 24110.0

import copy
x = [a, b]
y = copy.deepcopy(x)

assert x == y
x[0].sub(PVector(100, 100, 100))
assert x != y

print 'OK'

print PVector.dist(a, b)
print PVector.cross(a, b)
print PVector.dot(a, b)
26 changes: 13 additions & 13 deletions testing/tests/test/jycessing/JycessingTests.java
Expand Up @@ -17,11 +17,12 @@ private static String run(final String testResource) throws Exception {
final PrintStream saved = System.out;
try {
System.setOut(new PrintStream(baos, true));
Runner.main(new String[] { "testing/test_resources/test_"
+ testResource + ".py" });
Runner.main(
new String[] { "testing/test_resources/test_" + testResource
+ ".py" });
Thread.sleep(500);
return new String(baos.toByteArray()).replaceAll("\r\n", "\n")
.replaceAll("\r", "\n");
return new String(baos.toByteArray())
.replaceAll("\r\n", "\n").replaceAll("\r", "\n");
} finally {
System.setOut(saved);
}
Expand All @@ -35,11 +36,10 @@ private static void testImport(final String module) throws Exception {
final String testClass = module + "_test";
final String bogusFileName = "<test " + module + ">";
final String testText = "import " + module + "\nprint 'OK'";
Runner.runSketch(new String[] { testClass }, bogusFileName,
testText);
assertEquals("OK\n",
new String(baos.toByteArray()).replaceAll("\r\n", "\n")
.replaceAll("\r", "\n"));
Runner.runSketch(
new String[] { testClass }, bogusFileName, testText);
assertEquals("OK\n", new String(baos.toByteArray())
.replaceAll("\r\n", "\n").replaceAll("\r", "\n"));
} finally {
System.setOut(saved);
}
Expand Down Expand Up @@ -102,10 +102,10 @@ public void processing_core() throws Exception {
run("pcore"));
}

// @Test
// public void pvector() throws Exception {
// assertEquals("[ 8.0, 10.0, 12.0 ]\n", run("pvector"));
// }
@Test
public void pvector() throws Exception {
assertEquals("OK\n", run("pvector"));
}

public static void main(final String[] args) {
JUnitCore.runClasses(JycessingTests.class);
Expand Down

0 comments on commit 60d3bdd

Please sign in to comment.