Skip to content

Commit cb3ec00

Browse files
committed
Make PythonScriptRunner logic less tightly coupled
Now, if there is any java.util.function.Function named PythonScriptRunner in the ObjectService, we try to use its apply function, rather than requiring the runner to be of a special type. In this way, the scyjava library can gain a new function enable_python_scripting(context) that injects such a function (implemented on the Python side via @JImplements, of course, in the same way that the PythonScriptRunner was with the previous design iteration), without needing to guard against the possibility that scripting-python is unavailable at runtime when the @JImplements decorator executes; the only class needed (Function) is part of the Java standard library. Python scripts wanting to launch a Java capable of making use of this PythonScriptEngine should now perform the following steps: 1. Put scripting-python on the classpath, either via the org.scijava:scripting-python Maven coordinate string in an endpoint, or locally via scyjava.config.add_classpath; 2. Construct a SciJava context; and 3. Invoke the scyjava.enable_scijava_scripting(context) function. After which point, using the context's ScriptService to execute Python scripts should start working! \^_^/
1 parent a7550c9 commit cb3ec00

File tree

2 files changed

+36
-67
lines changed

2 files changed

+36
-67
lines changed

src/main/java/org/scijava/plugins/scripting/python/PythonScriptEngine.java

Lines changed: 36 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,12 @@
3434
import java.util.Collection;
3535
import java.util.HashMap;
3636
import java.util.Map;
37+
import java.util.Optional;
3738
import java.util.Set;
39+
import java.util.function.Function;
3840

3941
import javax.script.Bindings;
42+
import javax.script.ScriptContext;
4043
import javax.script.ScriptEngine;
4144
import javax.script.ScriptException;
4245

@@ -45,11 +48,10 @@
4548
import org.scijava.object.ObjectService;
4649
import org.scijava.plugin.Parameter;
4750
import 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
@@ -58,29 +60,30 @@
5860
public 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
}

src/main/java/org/scijava/plugins/scripting/python/PythonScriptRunner.java

Lines changed: 0 additions & 46 deletions
This file was deleted.

0 commit comments

Comments
 (0)