org.python.jsr223.PyScriptEngine Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jython-slim Show documentation
Show all versions of jython-slim Show documentation
Jython is an implementation of the high-level, dynamic, object-oriented
language Python written in 100% Pure Java, and seamlessly integrated with
the Java platform. It thus allows you to run Python on any Java platform.
package org.python.jsr223;
import java.lang.reflect.Method;
import org.python.core.*;
import java.io.Reader;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import javax.script.AbstractScriptEngine;
import javax.script.Bindings;
import javax.script.Compilable;
import javax.script.CompiledScript;
import javax.script.Invocable;
import javax.script.ScriptContext;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineFactory;
import javax.script.ScriptException;
import javax.script.SimpleBindings;
import org.python.util.PythonInterpreter;
public class PyScriptEngine extends AbstractScriptEngine implements Compilable, Invocable, AutoCloseable {
private final PythonInterpreter interp;
private final ScriptEngineFactory factory;
PyScriptEngine(ScriptEngineFactory factory) {
this.factory = factory;
interp = PythonInterpreter.threadLocalStateInterpreter(new PyScriptEngineScope(this, context));
}
public Object eval(String script, ScriptContext context) throws ScriptException {
return eval(compileScript(script, context), context);
}
private Object eval(PyCode code, ScriptContext context) throws ScriptException {
try {
interp.setIn(context.getReader());
interp.setOut(context.getWriter());
interp.setErr(context.getErrorWriter());
interp.setLocals(new PyScriptEngineScope(this, context));
// set sys.argv if FILENAME, ARGV attributes are defined
String filename = (String) context.getAttribute(ScriptEngine.FILENAME);
String[] argv = (String[]) context.getAttribute(ScriptEngine.ARGV);
if (argv != null || filename != null) {
PyList pyargv = new PyList();
if (filename != null) {
pyargv.append(Py.java2py(filename));
}
if (argv != null) {
for (int i = 0; i < argv.length; i++) {
pyargv.append(Py.java2py(argv[i]));
}
}
interp.getSystemState().argv = pyargv;
}
return interp.eval(code).__tojava__(Object.class);
} catch (PyException pye) {
throw scriptException(pye);
}
}
public Object eval(Reader reader, ScriptContext context) throws ScriptException {
return eval(compileScript(reader, context), context);
}
public Bindings createBindings() {
return new SimpleBindings();
}
public ScriptEngineFactory getFactory() {
return factory;
}
public CompiledScript compile(String script) throws ScriptException {
return new PyCompiledScript(compileScript(script, context));
}
public CompiledScript compile(Reader reader) throws ScriptException {
return new PyCompiledScript(compileScript(reader, context));
}
private PyCode compileScript(String script, ScriptContext context) throws ScriptException {
try {
String filename = (String) context.getAttribute(ScriptEngine.FILENAME);
if (filename == null) {
return interp.compile(script);
} else {
interp.getLocals().__setitem__(Py.newString("__file__"), Py.newString(filename));
return interp.compile(script, filename);
}
} catch (PyException pye) {
throw scriptException(pye);
}
}
private PyCode compileScript(Reader reader, ScriptContext context) throws ScriptException {
try {
String filename = (String) context.getAttribute(ScriptEngine.FILENAME);
if (filename == null) {
return interp.compile(reader);
} else {
interp.getLocals().__setitem__(Py.newString("__file__"), Py.newString(filename));
return interp.compile(reader, filename);
}
} catch (PyException pye) {
throw scriptException(pye);
}
}
public Object invokeMethod(Object thiz, String name, Object... args) throws ScriptException,
NoSuchMethodException {
try {
interp.setLocals(new PyScriptEngineScope(this, context));
if (!(thiz instanceof PyObject)) {
thiz = Py.java2py(thiz);
}
PyObject method = ((PyObject) thiz).__findattr__(name);
if (method == null) {
throw new NoSuchMethodException(name);
}
//return method.__call__(Py.javas2pys(args)).__tojava__(Object.class);
PyObject result;
if(args != null) {
result = method.__call__(Py.javas2pys(args));
} else {
result = method.__call__();
}
return result.__tojava__(Object.class);
} catch (PyException pye) {
throw scriptException(pye);
}
}
public Object invokeFunction(String name, Object... args) throws ScriptException,
NoSuchMethodException {
try {
interp.setLocals(new PyScriptEngineScope(this, context));
PyObject function = interp.get(name);
if (function == null) {
throw new NoSuchMethodException(name);
}
PyObject result;
if(args != null) {
result = function.__call__(Py.javas2pys(args));
} else {
result = function.__call__();
}
return result.__tojava__(Object.class);
} catch (PyException pye) {
throw scriptException(pye);
}
}
public T getInterface(Class clazz) {
return getInterface(new PyModule("__jsr223__", interp.getLocals()), clazz);
}
public T getInterface(Object obj, Class clazz) {
if (obj == null) {
throw new IllegalArgumentException("object expected");
}
if (clazz == null || !clazz.isInterface()) {
throw new IllegalArgumentException("interface expected");
}
interp.setLocals(new PyScriptEngineScope(this, context));
final PyObject thiz = Py.java2py(obj);
@SuppressWarnings("unchecked")
T proxy = (T) Proxy.newProxyInstance(
clazz.getClassLoader(),
new Class[] { clazz },
new InvocationHandler() {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
try {
interp.setLocals(new PyScriptEngineScope(PyScriptEngine.this, context));
PyObject pyMethod = thiz.__findattr__(method.getName());
if (pyMethod == null)
throw new NoSuchMethodException(method.getName());
PyObject result;
if(args != null) {
result = pyMethod.__call__(Py.javas2pys(args));
} else {
result = pyMethod.__call__();
}
return result.__tojava__(Object.class);
} catch (PyException pye) {
throw scriptException(pye);
}
}
});
return proxy;
}
private static ScriptException scriptException(PyException pye) {
ScriptException se = null;
try {
pye.normalize();
PyObject type = pye.type;
PyObject value = pye.value;
PyTraceback tb = pye.traceback;
if (__builtin__.isinstance(value, Py.SyntaxError)) {
PyObject filename = value.__findattr__("filename");
PyObject lineno = value.__findattr__("lineno");
PyObject offset = value.__findattr__("offset");
value = value.__findattr__("msg");
se = new ScriptException(
Py.formatException(type, value),
filename == null ? "