From: <nr...@us...> - 2009-07-17 05:27:55
|
Revision: 6541 http://jython.svn.sourceforge.net/jython/?rev=6541&view=rev Author: nriley Date: 2009-07-17 05:27:51 +0000 (Fri, 17 Jul 2009) Log Message: ----------- JSR 223 support for compile and eval of Strings. Modified Paths: -------------- branches/jsr223/build.xml branches/jsr223/src/org/python/core/Py.java branches/jsr223/src/org/python/core/PyFinalizableInstance.java branches/jsr223/src/org/python/jsr223/PyScriptEngine.java branches/jsr223/src/org/python/util/PythonInterpreter.java Added Paths: ----------- branches/jsr223/src/META-INF/ branches/jsr223/src/META-INF/services/ branches/jsr223/src/META-INF/services/javax.script.ScriptEngineFactory branches/jsr223/tests/java/org/python/jsr223/ branches/jsr223/tests/java/org/python/jsr223/ScriptEngineTest.java Modified: branches/jsr223/build.xml =================================================================== --- branches/jsr223/build.xml 2009-07-17 04:28:55 UTC (rev 6540) +++ branches/jsr223/build.xml 2009-07-17 05:27:51 UTC (rev 6541) @@ -503,6 +503,10 @@ </copy> <!-- grammar must now be up to date --> <property name="antlr.notneeded" value="true" /> + + <copy todir="${compile.dir}/META-INF/services"> + <fileset dir="${source.dir}/META-INF/services" /> + </copy> </target> <!-- Added: branches/jsr223/src/META-INF/services/javax.script.ScriptEngineFactory =================================================================== --- branches/jsr223/src/META-INF/services/javax.script.ScriptEngineFactory (rev 0) +++ branches/jsr223/src/META-INF/services/javax.script.ScriptEngineFactory 2009-07-17 05:27:51 UTC (rev 6541) @@ -0,0 +1 @@ +org.python.jsr223.PyScriptEngineFactory Modified: branches/jsr223/src/org/python/core/Py.java =================================================================== --- branches/jsr223/src/org/python/core/Py.java 2009-07-17 04:28:55 UTC (rev 6540) +++ branches/jsr223/src/org/python/core/Py.java 2009-07-17 05:27:51 UTC (rev 6541) @@ -1021,7 +1021,7 @@ stderr.println(getStackTrace((Throwable) javaError)); } } - stderr.println(formatException(type, value, tb)); + stderr.println(formatException(type, value)); } /** @@ -1074,7 +1074,7 @@ out.print("^\n"); } - static String formatException(PyObject type, PyObject value, PyObject tb) { + public static String formatException(PyObject type, PyObject value) { StringBuilder buf = new StringBuilder(); if (PyException.isExceptionClass(type)) { @@ -1100,7 +1100,7 @@ } else { buf.append(type.__str__()); } - if (value != Py.None) { + if (value != null && value != Py.None) { // only print colon if the str() of the object is not the empty string PyObject s = value.__str__(); if (!(s instanceof PyString) || s.__len__() != 0) { Modified: branches/jsr223/src/org/python/core/PyFinalizableInstance.java =================================================================== --- branches/jsr223/src/org/python/core/PyFinalizableInstance.java 2009-07-17 04:28:55 UTC (rev 6540) +++ branches/jsr223/src/org/python/core/PyFinalizableInstance.java 2009-07-17 05:27:51 UTC (rev 6541) @@ -31,7 +31,7 @@ } catch (PyException e) { ; } Py.stderr.println("Exception " + - Py.formatException(exc.type, exc.value, exc.traceback) + + Py.formatException(exc.type, exc.value) + " in " + method + " ignored"); } Modified: branches/jsr223/src/org/python/jsr223/PyScriptEngine.java =================================================================== --- branches/jsr223/src/org/python/jsr223/PyScriptEngine.java 2009-07-17 04:28:55 UTC (rev 6540) +++ branches/jsr223/src/org/python/jsr223/PyScriptEngine.java 2009-07-17 05:27:51 UTC (rev 6541) @@ -1,5 +1,6 @@ package org.python.jsr223; +import org.python.core.*; import java.io.Reader; import javax.script.AbstractScriptEngine; import javax.script.Bindings; @@ -10,9 +11,6 @@ import javax.script.ScriptEngine; import javax.script.ScriptEngineFactory; import javax.script.ScriptException; -import org.python.core.Py; -import org.python.core.PyException; -import org.python.core.PyObject; import org.python.util.PythonInterpreter; public class PyScriptEngine extends AbstractScriptEngine implements Compilable, Invocable { @@ -26,9 +24,17 @@ } public Object eval(String script, ScriptContext context) throws ScriptException { - throw new UnsupportedOperationException("Not supported yet."); + return eval(compileScript(script, context)); } + private Object eval(PyCode code) throws ScriptException { + try { + return interp.eval(code).__tojava__(Object.class); + } catch (PyException e) { + throw scriptException(e); + } + } + // it would be nice if we supported a Reader interface in Py.compileFlags, instead of having // to create a string here public Object eval(Reader reader, ScriptContext context) throws ScriptException { @@ -43,15 +49,26 @@ return factory; } - // i assume this should simply return a PyModule object or something public CompiledScript compile(String script) throws ScriptException { - throw new UnsupportedOperationException("Not supported yet."); + return new PyCompiledScript(compileScript(script, context)); } public CompiledScript compile(Reader script) throws ScriptException { throw new UnsupportedOperationException("Not supported yet."); } + private PyCode compileScript(String script, ScriptContext context) throws ScriptException { + try { + String filename = (String) context.getAttribute(ScriptEngine.FILENAME); + if (filename == null) + return interp.compileExpressionOrModule(script); + else + return interp.compileExpressionOrModule(script, filename); + } catch (PyException e) { + throw scriptException(e); + } + } + public Object invokeMethod(Object thiz, String name, Object... args) throws ScriptException, NoSuchMethodException { try { if (thiz instanceof PyObject) { @@ -85,6 +102,48 @@ throw new UnsupportedOperationException("Not supported yet."); } + private static ScriptException scriptException(PyException e) { + ScriptException se = null; + try { + e.normalize(); + + PyObject type = e.type; + PyObject value = e.value; + PyTraceback tb = e.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 ? "<script>" : filename.toString(), + lineno == null ? 0 : lineno.asInt(), + offset == null ? 0 : offset.asInt()); + } else if (tb != null) { + String filename; + if (tb.tb_frame == null || tb.tb_frame.f_code == null) + filename = null; + else + filename = tb.tb_frame.f_code.co_filename; + + se = new ScriptException( + Py.formatException(type, value), + filename, + tb.tb_lineno); + } else { + se = new ScriptException(Py.formatException(type, value)); + } + se.initCause(e); + return se; + } catch (Exception ee) { + se = new ScriptException(e); + } + return se; + } + private static PyObject[] java2py(Object[] args) { PyObject wrapped[] = new PyObject[args.length]; for (int i = 0; i < args.length; i++) { @@ -93,18 +152,20 @@ return wrapped; } - // wraps a PyCode object - private static class PyCompiledScript extends CompiledScript { + private class PyCompiledScript extends CompiledScript { + private PyCode code; - @Override - public Object eval(ScriptContext arg0) throws ScriptException { - throw new UnsupportedOperationException("Not supported yet."); + PyCompiledScript(PyCode code) { + this.code = code; } - @Override public ScriptEngine getEngine() { - throw new UnsupportedOperationException("Not supported yet."); + return PyScriptEngine.this; } + public Object eval(ScriptContext ctx) throws ScriptException { + // can't read filename from context at this point + return PyScriptEngine.this.eval(code); + } } } Modified: branches/jsr223/src/org/python/util/PythonInterpreter.java =================================================================== --- branches/jsr223/src/org/python/util/PythonInterpreter.java 2009-07-17 04:28:55 UTC (rev 6540) +++ branches/jsr223/src/org/python/util/PythonInterpreter.java 2009-07-17 05:27:51 UTC (rev 6541) @@ -2,8 +2,10 @@ import java.util.Properties; +import org.python.antlr.base.mod; import org.python.core.CompileMode; import org.python.core.CompilerFlags; +import org.python.core.ParserFacade; import org.python.core.Py; import org.python.core.PyCode; import org.python.core.PyException; @@ -13,6 +15,7 @@ import org.python.core.PyObject; import org.python.core.PyString; import org.python.core.PyStringMap; +import org.python.core.PySyntaxError; import org.python.core.PySystemState; import org.python.core.__builtin__; @@ -130,6 +133,14 @@ } /** + * Evaluate a Python code object and return the result + */ + public PyObject eval(PyObject code) { + setState(); + return __builtin__.eval(code, locals, locals); + } + + /** * Execute a string of Python source in the local namespace */ public void exec(String s) { @@ -166,6 +177,34 @@ Py.flushLine(); } + /** + * Compile a string of Python source as either an expression (if possible) or module. + * + * Designed for use by a JSR 223 implementation: "the Scripting API does not distinguish + * between scripts which return values and those which do not, nor do they make the + * corresponding distinction between evaluating or executing objects." (SCR.4.2.1) + */ + public PyCode compileExpressionOrModule(String script) { + return compileExpressionOrModule(script, "<script>"); + } + + public PyCode compileExpressionOrModule(String script, String filename) { + mod node; + try { + // first, try parsing as an expression + node = ParserFacade.parse(script, CompileMode.eval, filename, cflags); + } catch (PySyntaxError e) { + try { + // then, try parsing as a module + node = ParserFacade.parse(script, CompileMode.exec, filename, cflags); + } catch (PySyntaxError ee) { + throw ee; + } + } + return Py.compile_flags(node, filename, CompileMode.eval, cflags); + } + + public PyObject getLocals() { return locals; } Added: branches/jsr223/tests/java/org/python/jsr223/ScriptEngineTest.java =================================================================== --- branches/jsr223/tests/java/org/python/jsr223/ScriptEngineTest.java (rev 0) +++ branches/jsr223/tests/java/org/python/jsr223/ScriptEngineTest.java 2009-07-17 05:27:51 UTC (rev 6541) @@ -0,0 +1,58 @@ +package org.python.jsr223; + +import javax.script.Compilable; +import javax.script.CompiledScript; +import javax.script.ScriptContext; +import javax.script.ScriptEngine; +import javax.script.ScriptEngineManager; +import javax.script.ScriptException; +import javax.script.SimpleScriptContext; +import junit.framework.TestCase; + +public class ScriptEngineTest extends TestCase { + + public void testEvalString() throws ScriptException { + ScriptEngineManager manager = new ScriptEngineManager(); + ScriptEngine pythonEngine = manager.getEngineByName("python"); + + assertNull(pythonEngine.eval("x = 5")); + assertEquals(Integer.valueOf(5), pythonEngine.eval("x")); + } + + public void testSyntaxError() { + ScriptEngineManager manager = new ScriptEngineManager(); + ScriptEngine pythonEngine = manager.getEngineByName("python"); + + try { + pythonEngine.eval("5q"); + } catch (ScriptException e) { + assertEquals(e.getColumnNumber(), 1); + assertEquals(e.getLineNumber(), 1); + assertTrue(e.getMessage().startsWith("SyntaxError: ")); + return; + } + assertTrue("Expected a ScriptException", false); + } + + public void testScriptFilename() { + ScriptEngineManager manager = new ScriptEngineManager(); + ScriptEngine pythonEngine = manager.getEngineByName("python"); + SimpleScriptContext scriptContext = new SimpleScriptContext(); + scriptContext.setAttribute(ScriptEngine.FILENAME, "sample.py", ScriptContext.ENGINE_SCOPE); + try { + pythonEngine.eval("foo", scriptContext); + } catch (ScriptException e) { + assertEquals("sample.py", e.getFileName()); + return; + } + assertTrue("Expected a ScriptException", false); + } + + public void testCompileEvalString() throws ScriptException { + ScriptEngineManager manager = new ScriptEngineManager(); + ScriptEngine pythonEngine = manager.getEngineByName("python"); + + CompiledScript five = ((Compilable)pythonEngine).compile("5"); + assertEquals(Integer.valueOf(5), five.eval()); + } +} This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <nr...@us...> - 2009-07-22 21:15:46
|
Revision: 6559 http://jython.svn.sourceforge.net/jython/?rev=6559&view=rev Author: nriley Date: 2009-07-22 21:15:39 +0000 (Wed, 22 Jul 2009) Log Message: ----------- JSR 223: support for compile and eval with Readers. Modified Paths: -------------- branches/jsr223/src/org/python/core/ParserFacade.java branches/jsr223/src/org/python/jsr223/PyScriptEngine.java branches/jsr223/src/org/python/util/PythonInterpreter.java branches/jsr223/tests/java/org/python/jsr223/ScriptEngineTest.java Modified: branches/jsr223/src/org/python/core/ParserFacade.java =================================================================== --- branches/jsr223/src/org/python/core/ParserFacade.java 2009-07-22 02:18:24 UTC (rev 6558) +++ branches/jsr223/src/org/python/core/ParserFacade.java 2009-07-22 21:15:39 UTC (rev 6559) @@ -10,6 +10,7 @@ import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.Reader; +import java.io.StringReader; import java.io.Writer; import java.nio.charset.CharacterCodingException; import java.nio.charset.Charset; @@ -108,6 +109,34 @@ } /** + * Parse a string of Python source as either an expression (if possible) or module. + * + * Designed for use by a JSR 223 implementation: "the Scripting API does not distinguish + * between scripts which return values and those which do not, nor do they make the + * corresponding distinction between evaluating or executing objects." (SCR.4.2.1) + */ + public static mod parseExpressionOrModule(Reader reader, + String filename, + CompilerFlags cflags) { + ExpectedEncodingBufferedReader bufReader = null; + try { + bufReader = prepBufReader(reader, cflags, filename); + // first, try parsing as an expression + return parse(bufReader, CompileMode.eval, filename, cflags ); + } catch (Throwable t) { + try { + // then, try parsing as a module + bufReader.reset(); + return parse(bufReader, CompileMode.exec, filename, cflags); + } catch (Throwable tt) { + throw fixParseError(bufReader, tt, filename); + } + } finally { + close(bufReader); + } + } + + /** * Internal parser entry point. * * Users of this method should call fixParseError on any Throwable thrown @@ -130,6 +159,21 @@ } } + public static mod parse(Reader reader, + CompileMode kind, + String filename, + CompilerFlags cflags) { + ExpectedEncodingBufferedReader bufReader = null; + try { + bufReader = prepBufReader(reader, cflags, filename); + return parse(bufReader, kind, filename, cflags ); + } catch (Throwable t) { + throw fixParseError(bufReader, t, filename); + } finally { + close(bufReader); + } + } + public static mod parse(InputStream stream, CompileMode kind, String filename, @@ -223,6 +267,13 @@ } } + private static ExpectedEncodingBufferedReader prepBufReader(Reader reader, + CompilerFlags cflags, + String filename) + throws IOException { + return new ExpectedEncodingBufferedReader(new BufferedReader(reader), null); + } + private static ExpectedEncodingBufferedReader prepBufReader(InputStream input, CompilerFlags cflags, String filename, @@ -290,20 +341,10 @@ CompilerFlags cflags, String filename) throws IOException { - byte[] stringBytes; - if (cflags.source_is_utf8) { - // Passed unicode, re-encode the String to raw bytes - // NOTE: This could be more efficient if we duplicate - // prepBufReader/adjustForBOM/readEncoding to work on Readers, instead of - // encoding - ByteArrayOutputStream out = new ByteArrayOutputStream(); - Writer w = new OutputStreamWriter(out, "utf-8"); - w.write(string); - w.close(); - stringBytes = out.toByteArray(); - } else { - stringBytes = StringUtil.toBytes(string); - } + if (cflags.source_is_utf8) + return prepBufReader(new StringReader(string), cflags, filename); + + byte[] stringBytes = StringUtil.toBytes(string); return prepBufReader(new ByteArrayInputStream(stringBytes), cflags, filename, true, false); } Modified: branches/jsr223/src/org/python/jsr223/PyScriptEngine.java =================================================================== --- branches/jsr223/src/org/python/jsr223/PyScriptEngine.java 2009-07-22 02:18:24 UTC (rev 6558) +++ branches/jsr223/src/org/python/jsr223/PyScriptEngine.java 2009-07-22 21:15:39 UTC (rev 6559) @@ -35,10 +35,8 @@ } } - // it would be nice if we supported a Reader interface in Py.compileFlags, instead of having - // to create a string here public Object eval(Reader reader, ScriptContext context) throws ScriptException { - throw new UnsupportedOperationException("Not supported yet."); + return eval(compileScript(reader, context)); } public Bindings createBindings() { @@ -53,21 +51,33 @@ return new PyCompiledScript(compileScript(script, context)); } - public CompiledScript compile(Reader script) throws ScriptException { - throw new UnsupportedOperationException("Not supported yet."); + 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.compileExpressionOrModule(script); + return interp.compile(script); else - return interp.compileExpressionOrModule(script, filename); + return interp.compile(script, filename); } catch (PyException e) { throw scriptException(e); } } + + 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 + return interp.compile(reader, filename); + } catch (PyException e) { + throw scriptException(e); + } + } public Object invokeMethod(Object thiz, String name, Object... args) throws ScriptException, NoSuchMethodException { try { Modified: branches/jsr223/src/org/python/util/PythonInterpreter.java =================================================================== --- branches/jsr223/src/org/python/util/PythonInterpreter.java 2009-07-22 02:18:24 UTC (rev 6558) +++ branches/jsr223/src/org/python/util/PythonInterpreter.java 2009-07-22 21:15:39 UTC (rev 6559) @@ -1,5 +1,9 @@ package org.python.util; +import java.io.FilterReader; +import java.io.IOException; +import java.io.Reader; +import java.io.StringReader; import java.util.Properties; import org.python.antlr.base.mod; @@ -184,23 +188,17 @@ * between scripts which return values and those which do not, nor do they make the * corresponding distinction between evaluating or executing objects." (SCR.4.2.1) */ - public PyCode compileExpressionOrModule(String script) { - return compileExpressionOrModule(script, "<script>"); + public PyCode compile(String script) { + return compile(script, "<script>"); } - - public PyCode compileExpressionOrModule(String script, String filename) { - mod node; - try { - // first, try parsing as an expression - node = ParserFacade.parse(script, CompileMode.eval, filename, cflags); - } catch (PySyntaxError e) { - try { - // then, try parsing as a module - node = ParserFacade.parse(script, CompileMode.exec, filename, cflags); - } catch (PySyntaxError ee) { - throw ee; - } - } + public PyCode compile(Reader reader) { + return compile(reader, "<script>"); + } + public PyCode compile(String script, String filename) { + return compile(new StringReader(script), filename); + } + public PyCode compile(Reader reader, String filename) { + mod node = ParserFacade.parseExpressionOrModule(reader, filename, cflags); return Py.compile_flags(node, filename, CompileMode.eval, cflags); } Modified: branches/jsr223/tests/java/org/python/jsr223/ScriptEngineTest.java =================================================================== --- branches/jsr223/tests/java/org/python/jsr223/ScriptEngineTest.java 2009-07-22 02:18:24 UTC (rev 6558) +++ branches/jsr223/tests/java/org/python/jsr223/ScriptEngineTest.java 2009-07-22 21:15:39 UTC (rev 6559) @@ -1,5 +1,6 @@ package org.python.jsr223; +import java.io.StringReader; import javax.script.Compilable; import javax.script.CompiledScript; import javax.script.ScriptContext; @@ -69,4 +70,20 @@ CompiledScript five = ((Compilable)pythonEngine).compile("5"); assertEquals(Integer.valueOf(5), five.eval()); } + + public void testEvalReader() throws ScriptException { + ScriptEngineManager manager = new ScriptEngineManager(); + ScriptEngine pythonEngine = manager.getEngineByName("python"); + + assertNull(pythonEngine.eval(new StringReader("x = 5"))); + assertEquals(Integer.valueOf(5), pythonEngine.eval(new StringReader("x"))); + } + + public void testCompileEvalReader() throws ScriptException { + ScriptEngineManager manager = new ScriptEngineManager(); + ScriptEngine pythonEngine = manager.getEngineByName("python"); + + CompiledScript five = ((Compilable)pythonEngine).compile(new StringReader("5")); + assertEquals(Integer.valueOf(5), five.eval()); + } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <nr...@us...> - 2009-07-22 23:52:22
|
Revision: 6563 http://jython.svn.sourceforge.net/jython/?rev=6563&view=rev Author: nriley Date: 2009-07-22 23:52:19 +0000 (Wed, 22 Jul 2009) Log Message: ----------- JSR 223: bindings support. Modified Paths: -------------- branches/jsr223/CoreExposed.includes branches/jsr223/src/org/python/jsr223/PyScriptEngine.java branches/jsr223/tests/java/org/python/jsr223/ScriptEngineTest.java Added Paths: ----------- branches/jsr223/src/org/python/jsr223/PyScriptEngineScope.java Modified: branches/jsr223/CoreExposed.includes =================================================================== --- branches/jsr223/CoreExposed.includes 2009-07-22 23:52:08 UTC (rev 6562) +++ branches/jsr223/CoreExposed.includes 2009-07-22 23:52:19 UTC (rev 6563) @@ -41,6 +41,7 @@ org/python/core/PyType.class org/python/core/PyUnicode.class org/python/core/PyXRange.class +org/python/jsr223/PyScriptEngineScope.class org/python/modules/_codecs$EncodingMap.class org/python/modules/_csv/PyDialect.class org/python/modules/_csv/PyReader.class Modified: branches/jsr223/src/org/python/jsr223/PyScriptEngine.java =================================================================== --- branches/jsr223/src/org/python/jsr223/PyScriptEngine.java 2009-07-22 23:52:08 UTC (rev 6562) +++ branches/jsr223/src/org/python/jsr223/PyScriptEngine.java 2009-07-22 23:52:19 UTC (rev 6563) @@ -11,6 +11,7 @@ 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 { @@ -20,7 +21,7 @@ PyScriptEngine(ScriptEngineFactory factory) { this.factory = factory; - interp = new PythonInterpreter(); + interp = new PythonInterpreter(new PyScriptEngineScope(this, context)); } public Object eval(String script, ScriptContext context) throws ScriptException { @@ -40,7 +41,7 @@ } public Bindings createBindings() { - throw new UnsupportedOperationException("Not supported yet."); + return new SimpleBindings(); } public ScriptEngineFactory getFactory() { Added: branches/jsr223/src/org/python/jsr223/PyScriptEngineScope.java =================================================================== --- branches/jsr223/src/org/python/jsr223/PyScriptEngineScope.java (rev 0) +++ branches/jsr223/src/org/python/jsr223/PyScriptEngineScope.java 2009-07-22 23:52:19 UTC (rev 6563) @@ -0,0 +1,101 @@ +package org.python.jsr223; + +import java.util.List; +import javax.script.Bindings; +import javax.script.ScriptContext; +import javax.script.ScriptEngine; +import org.python.core.Py; +import org.python.core.PyList; +import org.python.core.PyObject; +import org.python.core.PyString; +import org.python.core.PyType; +import org.python.expose.ExposedType; +import org.python.expose.ExposedGet; +import org.python.expose.ExposedMethod; + +@ExposedType(name = "scope", isBaseType = false) +public final class PyScriptEngineScope extends PyObject { + public static final PyType TYPE = PyType.fromClass(PyScriptEngineScope.class); + + private final ScriptContext context; + private final ScriptEngine engine; + + PyScriptEngineScope(ScriptEngine engine, ScriptContext context) { + this.context = context; + this.engine = engine; + } + + @ExposedGet(name = "context") + public PyObject pyGetContext() { + return Py.java2py(context); + } + + @ExposedGet(name = "engine") + public PyObject pyGetEngine() { + return Py.java2py(engine); + } + + @ExposedMethod + public PyObject scope_keys() { + PyList members = new PyList(); + synchronized (context) { + List<Integer> scopes = context.getScopes(); + for (int scope : scopes) { + Bindings bindings = context.getBindings(scope); + if (bindings == null) + continue; + for (String key : bindings.keySet()) + members.append(new PyString(key)); + } + } + members.sort(); + return members; + } + + // Not necessary for functionality; present to satisfy __builtin__.PyMapping_check + @ExposedMethod + public PyObject __getitem__(PyObject key) { + return super.__getitem__(key); + } + + public PyObject __finditem__(PyObject key) { + return __finditem__(key.asString()); + } + + public PyObject __finditem__(String key) { + synchronized (context) { + int scope = context.getAttributesScope(key); + if (scope == -1) + return null; + return Py.java2py(context.getAttribute(key, scope)); + } + } + + @ExposedMethod + public void __setitem__(PyObject key, PyObject value) { + __setitem__(key.asString(), value); + } + + public void __setitem__(String key, PyObject value) { + synchronized (context) { + int scope = context.getAttributesScope(key); + if (scope == -1) + scope = ScriptContext.ENGINE_SCOPE; + context.setAttribute(key, value.__tojava__(Object.class), scope); + } + } + + @ExposedMethod + public void __delitem__(PyObject key) { + __delitem__(key.asString()); + } + + public void __delitem__(String key) { + synchronized (context) { + int scope = context.getAttributesScope(key); + if (scope == -1) + throw Py.KeyError(key); + context.removeAttribute(key, scope); + } + } +} Modified: branches/jsr223/tests/java/org/python/jsr223/ScriptEngineTest.java =================================================================== --- branches/jsr223/tests/java/org/python/jsr223/ScriptEngineTest.java 2009-07-22 23:52:08 UTC (rev 6562) +++ branches/jsr223/tests/java/org/python/jsr223/ScriptEngineTest.java 2009-07-22 23:52:19 UTC (rev 6563) @@ -86,4 +86,16 @@ CompiledScript five = ((Compilable)pythonEngine).compile(new StringReader("5")); assertEquals(Integer.valueOf(5), five.eval()); } + + public void testBindings() throws ScriptException { + ScriptEngineManager manager = new ScriptEngineManager(); + ScriptEngine pythonEngine = manager.getEngineByName("python"); + + pythonEngine.put("a", 42); + assertEquals(Integer.valueOf(42), pythonEngine.eval("a")); + assertNull(pythonEngine.eval("x = 5")); + assertEquals(Integer.valueOf(5), pythonEngine.get("x")); + assertNull(pythonEngine.eval("del x")); + assertNull(pythonEngine.get("x")); + } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <nr...@us...> - 2009-07-23 03:12:53
|
Revision: 6565 http://jython.svn.sourceforge.net/jython/?rev=6565&view=rev Author: nriley Date: 2009-07-23 03:12:52 +0000 (Thu, 23 Jul 2009) Log Message: ----------- JSR 223: Invocable implementation. Modified Paths: -------------- branches/jsr223/src/org/python/jsr223/PyScriptEngine.java branches/jsr223/tests/java/org/python/jsr223/ScriptEngineTest.java Modified: branches/jsr223/src/org/python/jsr223/PyScriptEngine.java =================================================================== --- branches/jsr223/src/org/python/jsr223/PyScriptEngine.java 2009-07-23 03:12:10 UTC (rev 6564) +++ branches/jsr223/src/org/python/jsr223/PyScriptEngine.java 2009-07-23 03:12:52 UTC (rev 6565) @@ -21,10 +21,12 @@ private final PythonInterpreter interp; private final ScriptEngineFactory factory; + private final PyModule module; PyScriptEngine(ScriptEngineFactory factory) { this.factory = factory; interp = new PythonInterpreter(new PyScriptEngineScope(this, context)); + module = (PyModule)Py.getSystemState().modules.__finditem__("__main__"); } public Object eval(String script, ScriptContext context) throws ScriptException { @@ -85,10 +87,9 @@ public Object invokeMethod(Object thiz, String name, Object... args) throws ScriptException, NoSuchMethodException { try { - if (thiz instanceof PyObject) { - return ((PyObject) thiz).invoke(name, java2py(args)).__tojava__(Object.class); - } - throw new NoSuchMethodException(name); + if (!(thiz instanceof PyObject)) + thiz = Py.java2py(thiz); + return ((PyObject) thiz).invoke(name, java2py(args)).__tojava__(Object.class); } catch (PyException pye) { return throwInvokeException(pye, name); } @@ -96,30 +97,37 @@ public Object invokeFunction(String name, Object... args) throws ScriptException, NoSuchMethodException { try { - return interp.get(name).__call__(java2py(args)).__tojava__(Object.class); + PyObject function = interp.get(name); + if (function == null) + throw new NoSuchMethodException(name); + return function.__call__(java2py(args)).__tojava__(Object.class); } catch (PyException pye) { return throwInvokeException(pye, name); } } public <T> T getInterface(Class<T> clazz) { - return getInterface(null, clazz); + return getInterface(module, clazz); } - public <T> T getInterface(Object thiz, Class<T> clazz) { + public <T> T getInterface(Object obj, Class<T> clazz) { + if (obj == null) + throw new IllegalArgumentException("object expected"); + if (clazz == null || !clazz.isInterface()) + throw new IllegalArgumentException("interface expected"); + final Object thiz = Py.java2py(obj); return (T) Proxy.newProxyInstance( - clazz.getClassLoader(), - new Class[] { clazz }, - new InvocationHandler() { - - public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { - try { - return ((PyObject) proxy).invoke(method.getName(), java2py(args)).__tojava__(Object.class); - } catch (PyException pye) { - return throwInvokeException(pye, method.getName()); + clazz.getClassLoader(), + new Class[] { clazz }, + new InvocationHandler() { + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + try { + return ((PyObject) thiz).invoke(method.getName(), java2py(args)).__tojava__(Object.class); + } catch (PyException pye) { + return throwInvokeException(pye, method.getName()); + } } - } - }); + }); } private static Object throwInvokeException(PyException pye, String methodName) Modified: branches/jsr223/tests/java/org/python/jsr223/ScriptEngineTest.java =================================================================== --- branches/jsr223/tests/java/org/python/jsr223/ScriptEngineTest.java 2009-07-23 03:12:10 UTC (rev 6564) +++ branches/jsr223/tests/java/org/python/jsr223/ScriptEngineTest.java 2009-07-23 03:12:52 UTC (rev 6565) @@ -1,14 +1,17 @@ package org.python.jsr223; +import java.io.IOException; import java.io.StringReader; import javax.script.Compilable; import javax.script.CompiledScript; +import javax.script.Invocable; import javax.script.ScriptContext; import javax.script.ScriptEngine; import javax.script.ScriptEngineManager; import javax.script.ScriptException; import javax.script.SimpleScriptContext; import junit.framework.TestCase; +import org.python.core.PyString; public class ScriptEngineTest extends TestCase { @@ -98,4 +101,56 @@ assertNull(pythonEngine.eval("del x")); assertNull(pythonEngine.get("x")); } + + public void testInvoke() throws ScriptException, NoSuchMethodException { + ScriptEngineManager manager = new ScriptEngineManager(); + ScriptEngine pythonEngine = manager.getEngineByName("python"); + Invocable invocableEngine = (Invocable)pythonEngine; + + assertNull(pythonEngine.eval("def f(x): return abs(x)")); + assertEquals(Integer.valueOf(5), invocableEngine.invokeFunction("f", Integer.valueOf(-5))); + assertEquals("spam", invocableEngine.invokeMethod(new PyString(" spam "), "strip")); + assertEquals("spam", invocableEngine.invokeMethod(" spam ", "strip")); + } + + public void testInvokeFunctionNoSuchMethod() throws ScriptException { + ScriptEngineManager manager = new ScriptEngineManager(); + Invocable invocableEngine = (Invocable)manager.getEngineByName("python"); + + try { + invocableEngine.invokeFunction("undefined"); + } catch (NoSuchMethodException e) { + return; + } + assertTrue("Expected a NoSuchMethodException", false); + } + + public void testInvokeMethodNoSuchMethod() throws ScriptException { + ScriptEngineManager manager = new ScriptEngineManager(); + Invocable invocableEngine = (Invocable)manager.getEngineByName("python"); + + try { + invocableEngine.invokeMethod("eggs", "undefined"); + } catch (NoSuchMethodException e) { + return; + } + assertTrue("Expected a NoSuchMethodException", false); + } + + public void testGetInterface() throws ScriptException, IOException { + ScriptEngineManager manager = new ScriptEngineManager(); + ScriptEngine pythonEngine = manager.getEngineByName("python"); + Invocable invocableEngine = (Invocable)pythonEngine; + + assertNull(pythonEngine.eval("def read(cb): return 1")); + Readable readable = invocableEngine.getInterface(Readable.class); + assertEquals(1, readable.read(null)); + + assertNull(pythonEngine.eval( + "class C(object):\n" + + " def read(self, cb): return 2\n" + + "c = C()")); + readable = invocableEngine.getInterface(pythonEngine.get("c"), Readable.class); + assertEquals(2, readable.read(null)); + } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |