001: // Copyright (c) Corporation for National Research Initiatives
002: package org.python.util;
003:
004: import org.python.core.*;
005:
006: // Based on CPython-1.5.2's code module
007:
008: public class InteractiveInterpreter extends PythonInterpreter {
009: public InteractiveInterpreter() {
010: this (null);
011: }
012:
013: public InteractiveInterpreter(PyObject locals) {
014: this (locals, null);
015:
016: }
017:
018: public InteractiveInterpreter(PyObject locals,
019: PySystemState systemState) {
020: super (locals, systemState);
021: cflags = new CompilerFlags();
022: }
023:
024: /**
025: * Compile and run some source in the interpreter.
026: *
027: * Arguments are as for compile_command().
028: *
029: * One several things can happen:
030: *
031: * 1) The input is incorrect; compile_command() raised an exception
032: * (SyntaxError or OverflowError). A syntax traceback will be printed
033: * by calling the showsyntaxerror() method.
034: *
035: * 2) The input is incomplete, and more input is required;
036: * compile_command() returned None. Nothing happens.
037: *
038: * 3) The input is complete; compile_command() returned a code object.
039: * The code is executed by calling self.runcode() (which also handles
040: * run-time exceptions, except for SystemExit).
041: *
042: * The return value is 1 in case 2, 0 in the other cases (unless an
043: * exception is raised). The return value can be used to decide
044: * whether to use sys.ps1 or sys.ps2 to prompt the next line.
045: **/
046: public boolean runsource(String source) {
047: return runsource(source, "<input>", "single");
048: }
049:
050: public boolean runsource(String source, String filename) {
051: return runsource(source, filename, "single");
052: }
053:
054: public boolean runsource(String source, String filename,
055: String symbol) {
056: PyObject code;
057: try {
058: code = Py.compile_command_flags(source, filename, symbol,
059: cflags, true);
060: } catch (PyException exc) {
061: if (Py.matchException(exc, Py.SyntaxError)) {
062: // Case 1
063: showexception(exc);
064: return false;
065: } else if (Py.matchException(exc, Py.ValueError)
066: || Py.matchException(exc, Py.OverflowError)) {
067: // Should not print the stack trace, just the error.
068: showexception(exc);
069: return false;
070: } else {
071: throw exc;
072: }
073: }
074: // Case 2
075: if (code == Py.None)
076: return true;
077: // Case 3
078: runcode(code);
079: return false;
080: }
081:
082: /**
083: * execute a code object.
084: *
085: * When an exception occurs, self.showtraceback() is called to display
086: * a traceback. All exceptions are caught except SystemExit, which is
087: * reraised.
088: *
089: * A note about KeyboardInterrupt: this exception may occur elsewhere
090: * in this code, and may not always be caught. The caller should be
091: * prepared to deal with it.
092: **/
093:
094: // Make this run in another thread somehow????
095: public void runcode(PyObject code) {
096: try {
097: exec(code);
098: } catch (PyException exc) {
099: if (Py.matchException(exc, Py.SystemExit))
100: throw exc;
101: showexception(exc);
102: }
103: }
104:
105: public void showexception(PyException exc) {
106: // Should probably add code to handle skipping top stack frames
107: // somehow...
108: Py.printException(exc);
109: }
110:
111: public void write(String data) {
112: Py.stderr.write(data);
113: }
114:
115: public StringBuffer buffer = new StringBuffer();
116: public String filename = "<stdin>";
117:
118: public void resetbuffer() {
119: buffer.setLength(0);
120: }
121:
122: /** Pause the current code, sneak an exception raiser into
123: * sys.trace_func, and then continue the code hoping that JPython will
124: * get control to do the break;
125: **/
126: public void interrupt(ThreadState ts) {
127: TraceFunction breaker = new BreakTraceFunction();
128: TraceFunction oldTrace = ts.systemState.tracefunc;
129: ts.systemState.tracefunc = breaker;
130: if (ts.frame != null)
131: ts.frame.tracefunc = breaker;
132: ts.systemState.tracefunc = oldTrace;
133: //ts.thread.join();
134: }
135: }
136:
137: class BreakTraceFunction extends TraceFunction {
138: private void doBreak() {
139: throw new Error("Python interrupt");
140: //Thread.currentThread().interrupt();
141: }
142:
143: public TraceFunction traceCall(PyFrame frame) {
144: doBreak();
145: return null;
146: }
147:
148: public TraceFunction traceReturn(PyFrame frame, PyObject ret) {
149: doBreak();
150: return null;
151: }
152:
153: public TraceFunction traceLine(PyFrame frame, int line) {
154: doBreak();
155: return null;
156: }
157:
158: public TraceFunction traceException(PyFrame frame, PyException exc) {
159: doBreak();
160: return null;
161: }
162: }
|