/* * Copyright (c) 2012 European Synchrotron Radiation Facility, * Diamond Light Source Ltd. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html */ package fable.python.views; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStreamReader; import java.io.UnsupportedEncodingException; import jep.Jep; import jep.JepException; import org.dawb.fabio.FableJep; import org.eclipse.swt.widgets.Display; import org.eclipse.ui.IWorkbenchPage; import org.eclipse.ui.PartInitException; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.console.ConsolePlugin; import org.eclipse.ui.console.IConsole; import fable.framework.views.FableIOConsole; /** * a Python console for starting a Python interpreter from Java using Jep * * @author goetz * */ public class PythonConsole { static FableIOConsole pythonConsole; RunConsoleThread runConsoleThread = new RunConsoleThread(); Jep jep = null; boolean consoleError = false; public PythonConsole() { pythonConsole = new FableIOConsole("Python Console"); ConsolePlugin.getDefault().getConsoleManager().addConsoles( new IConsole[] { pythonConsole }); } public void run() { new Thread(runConsoleThread).start(); } class RunConsoleThread implements Runnable { final Runtime runtime = Runtime.getRuntime(); String outputMessage; public void run() { try { jep = FableJep.getFableJep().getJep(); // this seems to be necessary in order to capture the sys.stdout jep.setInteractive(true); jep.eval("import sys\n"); // a simple class which can be used to redirect sys.stdout to a // variable // called stdouttext, the text is appended until a call to clear // is made jep.eval("class mystdout:\n" + " def write(self, text):\n" + " self.stdouttext += text\n" + " def clear(self):\n" + " self.stdouttext = \"\"\n"); jep.eval("mystdout=mystdout()\n"); // redirect sys.stdout to mystdout so we can pick up the output // in interactive mode jep.eval("sys.stdout=mystdout"); jep.eval(null); } catch (Throwable e) { // TODO Auto-generated catch block e.printStackTrace(); } pythonConsole.getInputStream(); BufferedReader in = null; try { in = new BufferedReader(new InputStreamReader(pythonConsole .getInputStream(), "UTF-8")); } catch (UnsupportedEncodingException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } String scriptFile = null; File file = null; FileInputStream fileStream = null; BufferedReader bufferedStream = null; boolean scriptInput = false, scriptCommand = false; while (true && !consoleError) { try { String str, command; str = ""; command = ""; int indent = 0; scriptCommand = false; if (!scriptInput) { pythonConsole.displayOut(">>> "); str = in.readLine(); } else { str = bufferedStream.readLine(); if (str == null) { str = ""; scriptInput = false; } pythonConsole.displayOut(scriptFile + ":>>> " + str + "\n"); } if (str != null && str.length() > 10) { if (str.substring(0, 10).equals("script.run")) { scriptFile = str.substring(str.indexOf('(') + 1, str.indexOf(')')); file = new File(scriptFile); if (file.exists()) { fileStream = new FileInputStream(file); bufferedStream = new BufferedReader( new InputStreamReader(fileStream)); if (fileStream.available() > 0) { scriptInput = true; scriptCommand = true; } } } } if (!scriptCommand) { command = str + "\n"; /* does this command require indentation ? */ if (str != null && str.length() > 1) if (str.charAt(str.length() - 1) == ':') indent++; while (indent != 0) { int noSpaces = 0; if (!scriptInput) { pythonConsole.displayOut("... "); str = in.readLine(); } else { str = bufferedStream.readLine(); if (str == null) { str = ""; scriptInput = false; } pythonConsole.displayOut(scriptFile + ":... " + str + "\n"); } command = command + str + "\n"; for (int i = 0; i < str.length(); i++) { if (str.charAt(i) != ' ') break; noSpaces++; } indent = noSpaces / 4; } evaluateCommand(command); } } catch (IOException e) { consoleError = true; // e.printStackTrace(); } } } } /** * evaluate a command by sending it to the Python interpreter * * @param command * - python command e.g. a=1 */ void evaluateCommand(String command) { if (jep == null) { pythonConsole .displayOut("There is no Jep Python object, please fix the problem and then try again !"); } else { boolean plotCommand = false; /* treat plot as a special keyword */ if (command.length() > 7) { if (command.substring(0, 7).equalsIgnoreCase("plot.1d")) { String arrayToPlot; arrayToPlot = command.substring(command.indexOf('(') + 1, command.indexOf(')')); plotArray(arrayToPlot); plotCommand = true; } } if (!plotCommand) { try { jep.eval("mystdout.clear()"); jep.eval(command); jep.eval("res=mystdout.stdouttext"); jep.eval(null); String commandOut = (String) jep.getValue("res"); pythonConsole.displayOut(commandOut); } catch (JepException e) { pythonConsole.displayError(e.getMessage().substring( e.getMessage().indexOf('>') + 3) + "\n"); } } } } /* * get the array from python, activate the python plot and plot the data */ private void plotArray(String _arrayName) { final String arrayName = _arrayName; final float arrayData[]; try { jep .eval("res = " + arrayName + ".astype(numpy.float32).tostring()"); arrayData = (float[]) jep.getValue_floatarray("res"); if (!Display.getDefault().isDisposed()) { Display.getDefault().syncExec(new Runnable() { public void run() { try { PythonPlotView pythonPlot = (PythonPlotView) (PlatformUI .getWorkbench().getActiveWorkbenchWindow() .getActivePage().showView( PythonPlotView.ID, "0", IWorkbenchPage.VIEW_ACTIVATE)); if (pythonPlot != null) pythonPlot.plotArray(arrayName, arrayData); } catch (PartInitException e2) { e2.printStackTrace(); } } }); } } catch (JepException e) { pythonConsole.displayError(e.getMessage().substring( e.getMessage().indexOf('>') + 3) + "\n"); } } }