Skip to content

Commit e048a59

Browse files
committed
got running in a separate process functional!
1 parent ce96269 commit e048a59

File tree

7 files changed

+108
-40
lines changed

7 files changed

+108
-40
lines changed

README.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,16 @@ Future work:
2424
As I don't have the preprocessor done, code isn't very pretty right now, but it works!
2525
A working sketch (copy and paste into the PDE to try it out!):
2626

27-
import info.sansgills.mode.python.PythonPApplet as PApplet
27+
import info.sansgills.mode.python.wrapper.PythonPApplet as PApplet
2828

2929
class Placeholder(PApplet):
3030
def setup(self):
3131
self.size(200, 200)
3232
self.background(0)
3333
self.noStroke()
3434
self.ellipseMode(PApplet.CENTER)
35-
35+
3636
def draw(self):
37-
self.ellipse(self.mouseX, self.mouseY, 5, 5)
37+
self.ellipse(self.mouseX, self.mouseY, 5, 5)
38+
39+
applet = Placeholder()

build.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@
6060

6161
<mkdir dir="${build}" />
6262

63-
<javac srcdir="${src}" destdir="${build}" source="${java.target.version}" target="${java.target.version}" bootclasspath="${java.target.bootclasspath}" includeantruntime="false">
63+
<javac srcdir="${src}" destdir="${build}" source="${java.target.version}" target="${java.target.version}" bootclasspath="${java.target.bootclasspath}" includeantruntime="false" debug="true">
6464
<classpath>
6565
<path refid="library-classpath"/>
6666
</classpath>

release/PythonMode.zip

5.78 KB
Binary file not shown.

src/info/sansgills/mode/python/PythonBuild.java

Lines changed: 37 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import java.io.PrintWriter;
55

66
import processing.app.Base;
7+
import processing.app.Library;
78
import processing.app.Sketch;
89
import processing.app.SketchCode;
910

@@ -44,7 +45,7 @@ public void build() throws Exception{
4445
//a start
4546
resultProgram = "";
4647

47-
SketchCode[] parts = sketch.getCode(); //TODO this function doesn't work properly, it returns old code for some reason
48+
SketchCode[] parts = sketch.getCode(); //fix'd
4849

4950
//concatenate code strings
5051
for(int i = parts.length-1; i >= 0; i--){ //iterate backwards... it seemed like a good idea at the time
@@ -59,11 +60,14 @@ public void build() throws Exception{
5960
binFolder = sketch.makeTempFolder();
6061

6162
outFile = new File(binFolder.getAbsolutePath()
63+
+ File.separator
6264
+ sketch.getName().toLowerCase()
6365
+ ".py");
6466
outFile.createNewFile();
67+
68+
6569
PrintWriter writer = new PrintWriter(outFile);
66-
writer.write(resultProgram+"\n");
70+
writer.print(resultProgram+"\n");
6771
writer.close();
6872
}
6973

@@ -97,22 +101,40 @@ public int getBuildNumber(){
97101

98102
/*
99103
* Classes used to run the build.
104+
*
105+
* TODO build during preprocess
100106
*/
101-
public String getClassPath(){
102-
String cp = "";
103-
String sep = System.getProperty("file.separator");
104-
String modeRoot = Base.getSketchbookModesFolder().getAbsolutePath()
105-
+sep
106-
+"PythonMode"
107-
+sep
108-
+"mode"
109-
+sep;
110-
cp += modeRoot+"ProcessingJythonWrapper.jar;";
111-
cp += modeRoot+"jython-standalone-2.7-b1.jar;";
107+
public String getClassPath() {
108+
//the Processing classpath
109+
String cp = mode.getCoreLibrary().getClassPath();
110+
111+
// From JavaMode.java:
112+
// Finally, add the regular Java CLASSPATH. This contains everything
113+
// imported by the PDE itself (core.jar, pde.jar, quaqua.jar) which may
114+
// in fact be more of a problem.
115+
String javaClassPath = System.getProperty("java.class.path");
116+
// Remove quotes if any.. A messy (and frequent) Windows problem
117+
if (javaClassPath.startsWith("\"") && javaClassPath.endsWith("\"")) {
118+
javaClassPath = javaClassPath.substring(1,
119+
javaClassPath.length() - 1);
120+
}
121+
cp += File.pathSeparator + javaClassPath;
122+
123+
//The .jars for this mode; Jython and wrapper, primarily
124+
String jythonModeLib = Base.getSketchbookModesFolder().getAbsolutePath()
125+
+ File.separator
126+
+ "PythonMode"
127+
+ File.separator
128+
+ "mode";
129+
System.out.println(jythonModeLib);
130+
cp += Base.contentsToClassPath(new File(jythonModeLib));
112131

113-
cp += mode.getCoreLibrary().getClassPath();
114132

115-
return cp; //TODO libraries?
133+
return cp; // TODO libraries?
134+
}
135+
136+
public String getJavaLibraryPath(){
137+
return "";
116138
}
117139

118140
/*

src/info/sansgills/mode/python/PythonEditor.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -136,13 +136,13 @@ public void handleRun() {
136136
new Thread(new Runnable(){
137137
public void run(){
138138
toolbar.activate(PythonToolbar.RUN); //pretty lights
139+
prepareRun();
139140
PythonBuild build = new PythonBuild(sketch, pyMode); //create build
140141
try {
141142
build.build(); //run build
142143
} catch (Exception e){
143144
statusError(e); //do something pretty?
144145
}
145-
prepareRun();
146146
runner = new PythonRunner(build, self); //create runtime (can't use 'this', this is a runnable)
147147
runner.launch(false); //launch runtime; present = false
148148
}
@@ -154,13 +154,13 @@ public void handlePresent() {
154154
new Thread(new Runnable() {
155155
public void run() {
156156
toolbar.activate(PythonToolbar.RUN);
157+
prepareRun();
157158
PythonBuild build = new PythonBuild(sketch, pyMode);
158159
try {
159160
build.build();
160161
} catch (Exception e){
161162
statusError(e);
162163
}
163-
prepareRun();
164164
runner = new PythonRunner(build, self);
165165
runner.launch(true); //present = true
166166
}

src/info/sansgills/mode/python/PythonRunner.java

Lines changed: 48 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
package info.sansgills.mode.python;
22

3+
import java.io.InputStream;
34
import java.util.ArrayList;
45

56
import processing.app.Base;
7+
import processing.app.exec.StreamRedirectThread;
68
import processing.core.PApplet;
79

810
/**
@@ -17,10 +19,13 @@
1719

1820
public class PythonRunner {
1921
PythonBuild build; // the python source we're working with
20-
PythonEditor editor;
21-
22-
Process sketchProcess;
22+
PythonEditor editor; // our editor (TODO command line?)
2323

24+
Process sketchProcess; // the process we create
25+
26+
// Threads to redirect output / error streams from process to us
27+
Thread errThread = null;
28+
Thread outThread = null;
2429

2530
public PythonRunner(PythonBuild build, PythonEditor editor) {
2631
this.build = build;
@@ -36,31 +41,69 @@ public void launch(boolean present) {
3641

3742
/*
3843
* Construct the command-line command to start the sketch with
44+
*
45+
* TODO add proper machine detection & whatnot from Java Mode
3946
*/
4047
private String[] buildArgs(boolean present){
4148
ArrayList<String> args = new ArrayList<String>();
4249

4350
args.add("java");
44-
args.add("");
51+
args.add("-cp");
52+
args.add(build.getClassPath());
53+
54+
args.add("info.sansgills.mode.python.wrapper.ProcessingJythonWrapper"); //main class
55+
56+
args.add(build.getResultFile()); //path to script
57+
args.add("Placeholder"); //sketch name
4558

4659
String[] out = args.toArray(new String[0]);
47-
System.out.println("command: "+out);
60+
61+
{//debugging
62+
String cmd = "";
63+
for (String c : out) {
64+
cmd += c + " ";
65+
}
66+
System.out.println("command: " + cmd);
67+
}
68+
4869
return out;
4970
}
5071

72+
/*
73+
* Start the process & a thread to track it
74+
*/
5175
private void exec(final String[] args){
5276
new Thread(new Runnable(){
5377
public void run(){
5478
sketchProcess = PApplet.exec(args);
79+
attach(); //TODO dirty hack
5580
try{
5681
int result = sketchProcess.waitFor();
82+
System.out.println("result: "+result);
5783
}catch(InterruptedException e){
84+
System.out.println("error:");
5885
e.printStackTrace();
5986
}
6087
}
6188
}).start();
6289
}
6390

91+
/*
92+
* Create redirect threads for stdout, stderr, etc.
93+
*
94+
* TODO connect vm & error threads
95+
*/
96+
private void attach(){
97+
// piggybacking off of Java Mode's redirect for now
98+
outThread = new StreamRedirectThread("JVM stdout Reader",
99+
sketchProcess.getInputStream(), System.out);
100+
errThread = new StreamRedirectThread("JVM stderr Reader",
101+
sketchProcess.getErrorStream(), System.err);
102+
103+
outThread.start();
104+
errThread.start();
105+
}
106+
64107
/*
65108
* Kill the code.
66109
*/

src/info/sansgills/mode/python/wrapper/ProcessingJythonWrapper.java

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -36,50 +36,51 @@ public class ProcessingJythonWrapper {
3636
static PySystemState sys; // for modifying python classpath, as yet
3737
static PythonPApplet constructedApplet; // Applet we pull from the interpreter
3838

39-
static String scriptPath;
40-
static String objname = "applet";
41-
42-
static String[] params;
39+
static final String objname = "applet";
4340

4441
/**
4542
*
4643
* First argument is the path to the script; the rest are things to pass to PApplet.
4744
*
4845
*/
4946
public static void main(String[] args) {
50-
scriptPath = args[0];
51-
params = Arrays.copyOfRange(args, 1, args.length);
52-
run();
47+
String scriptPath = args[0];
48+
String[] params = Arrays.copyOfRange(args, 1, args.length);
49+
run(scriptPath, params);
5350
}
5451

5552
/*
5653
* Run.
5754
*/
58-
public static void run(){
55+
public static void run(String scriptPath, String[] params){
5956
interp = new InteractiveConsole(); // create jython environment
6057
sys = Py.getSystemState(); // python 'sys' variable
6158

6259
//path to the archive of this wrapper, for Jython to import PythonPApplet from
63-
String jarPath = getJarLocation(); //TODO
64-
60+
String jarPath = getJarLocation();
61+
6562
sys.path.append(new PyString(jarPath));
6663

67-
6864
try {
6965
//run the script we were given; should define a PythonPApplet subclass and create an instance
7066
interp.execfile(scriptPath);
7167

7268
//get the applet we constructed
7369
PyObject pythonApplet = interp.get(objname);
7470

75-
//aaaand convert to an applet through jython magic
76-
constructedApplet = (PythonPApplet) pythonApplet.__tojava__(PythonPApplet.class);
71+
if (pythonApplet != null) {
72+
// aaaand convert to an applet through jython magic
73+
constructedApplet = (PythonPApplet) pythonApplet.__tojava__(PythonPApplet.class);
74+
} else {
75+
throw new Exception("Couldn't construct applet.");
76+
}
7777

7878
//run the sketch!
7979
PythonPApplet.runSketch(params, constructedApplet);
8080

8181
} catch (Exception e){
82-
System.err.println("Error running sketch: "+e.getMessage()); //TODO
82+
System.err.println("Error running sketch: " + e.getMessage()); //TODO
83+
e.printStackTrace();
8384
System.exit(1);
8485
}
8586
}

0 commit comments

Comments
 (0)