3434import java .util .Collection ;
3535import java .util .HashMap ;
3636import java .util .Map ;
37+ import java .util .Optional ;
3738import java .util .Set ;
39+ import java .util .function .Function ;
3840
3941import javax .script .Bindings ;
42+ import javax .script .ScriptContext ;
4043import javax .script .ScriptEngine ;
4144import javax .script .ScriptException ;
4245
4548import org .scijava .object .ObjectService ;
4649import org .scijava .plugin .Parameter ;
4750import org .scijava .script .AbstractScriptEngine ;
48- import org .scijava .ui .DialogPrompt ;
49- import org .scijava .ui .UIService ;
5051
5152/**
52- * A script engine for Python (PyImageJ).
53+ * A script engine for Python (CPython, not Jython!), backed by the
54+ * <a href="https://github.com/scijava/scyjava">scyjava</a> library.
5355 *
5456 * @author Curtis Rueden
5557 * @author Karl Duderstadt
5860public class PythonScriptEngine extends AbstractScriptEngine {
5961
6062 @ Parameter
61- ObjectService objectService ;
63+ private ObjectService objectService ;
6264
6365 @ Parameter
64- LogService logService ;
66+ private LogService logService ;
6567
66- @ Parameter
67- UIService uiService ;
68-
69- public PythonScriptEngine (Context context ) {
68+ public PythonScriptEngine (final Context context ) {
7069 context .inject (this );
7170 setLogService (logService );
7271 engineScopeBindings = new ScriptBindings ();
7372 }
7473
7574 @ Override
76- public Object eval (String script ) throws ScriptException {
77- if (objectService .getObjects (PythonScriptRunner .class ).stream ().count () > 0 )
78- return objectService .getObjects (PythonScriptRunner .class ).get (0 ).run (script , engineScopeBindings , scriptContext );
79-
80- uiService .showDialog ("The PythonScriptRunner could not be found in the ObjectService. To use the\n " +
81- "Conda Python 3 script engine Fiji must be launched from python inside a conda\n " +
82- "environment and a PythonScriptRunner must be added to the ObjectService.\n " , DialogPrompt .MessageType .ERROR_MESSAGE );
83- return null ;
75+ public Object eval (final String script ) throws ScriptException {
76+ final Optional <Function > pythonScriptRunner = //
77+ objectService .getObjects (Function .class ).stream ()//
78+ .filter (obj -> "PythonScriptRunner" .equals (objectService .getName (obj )))//
79+ .findFirst ();
80+ if (!pythonScriptRunner .isPresent ()) {
81+ throw new IllegalStateException (//
82+ "The PythonScriptRunner could not be found in the ObjectService. To use the\n " +
83+ "Python script engine, you must call scyjava.enable_scijava_scripting(context)\n " +
84+ "with this script engine's associated SciJava context before using it." );
85+ }
86+ return pythonScriptRunner .get ().apply (new Args (script , engineScopeBindings , scriptContext ));
8487 }
8588
8689 @ Override
@@ -105,10 +108,10 @@ public Bindings createBindings() {
105108 }
106109
107110 //Somehow just type casting did not work...
108- class ScriptBindings implements Bindings {
109-
110- private Map <String , Object > bindingsMap ;
111-
111+ private static class ScriptBindings implements Bindings {
112+
113+ private Map <String , Object > bindingsMap ;
114+
112115 ScriptBindings () {
113116 bindingsMap = new HashMap <String , Object >();
114117 }
@@ -173,4 +176,16 @@ public Object remove(Object key) {
173176 return bindingsMap .remove (key );
174177 }
175178 }
179+
180+ private static class Args {
181+ public final String script ;
182+ public final Map <String , Object > vars ;
183+ public final ScriptContext scriptContext ;
184+
185+ public Args (final String script , final Map <String , Object > vars , final ScriptContext scriptContext ) {
186+ this .script = script ;
187+ this .vars = vars ;
188+ this .scriptContext = scriptContext ;
189+ }
190+ }
176191}
0 commit comments