From 528d02765a26edaa4a9353e3a47f416f928895f7 Mon Sep 17 00:00:00 2001 From: Jeff Allen Date: Thu, 30 Jan 2020 08:02:32 +0000 Subject: [PATCH] Create a __main__ module and set __name__ in JSR-223 (fixes #2846). This change causes the default engine context in a PyScriptEngine to be created as a module __main__, and __name__ to be defined, comparable to the environment found when executing a Python program. The thread-local name space concept is otherwise undisturbed. org.python.jsr223.ScriptEngineTest cases are modified correspondingly, and testThreadLocalBindings is fixed to test isolation within a thread. --HG-- extra : amend_source : 936c178b0add1449e2d1d83a4d2161cd5bcd0ce0 --- NEWS | 1 + src/org/python/util/PythonInterpreter.java | 6 +- .../org/python/jsr223/ScriptEngineTest.java | 63 ++++++++++++++----- 3 files changed, 51 insertions(+), 19 deletions(-) diff --git a/NEWS b/NEWS index 77ac4891d..b2ca4c848 100644 --- a/NEWS +++ b/NEWS @@ -8,6 +8,7 @@ https://github.com/jythontools/jython Jython 2.7.2b3 Bugs fixed + - [ 2846 ] Main module __name __ is not "__main__" under Java Scripting API - [ 2828 ] Update netty JARs to 4.1.45 - [ 2044 ] CVE-2013-2027 Current umask sets privileges of class files and cache - [ 2834 ] Import of Java classes is not thread safe diff --git a/src/org/python/util/PythonInterpreter.java b/src/org/python/util/PythonInterpreter.java index 83b52d8b2..2971ee58d 100644 --- a/src/org/python/util/PythonInterpreter.java +++ b/src/org/python/util/PythonInterpreter.java @@ -101,10 +101,8 @@ protected PythonInterpreter(PyObject dict, PySystemState systemState, setSystemState(); this.useThreadLocalState = useThreadLocalState; - if (!useThreadLocalState) { - PyModule module = new PyModule("__main__", globals); - this.systemState.modules.__setitem__("__main__", module); - } + PyModule module = new PyModule("__main__", globals); + this.systemState.modules.__setitem__("__main__", module); if (Options.Qnew) { cflags.setFlag(CodeFlag.CO_FUTURE_DIVISION); diff --git a/tests/java/org/python/jsr223/ScriptEngineTest.java b/tests/java/org/python/jsr223/ScriptEngineTest.java index 2ed873308..eb97ecaba 100644 --- a/tests/java/org/python/jsr223/ScriptEngineTest.java +++ b/tests/java/org/python/jsr223/ScriptEngineTest.java @@ -15,12 +15,13 @@ import javax.script.ScriptException; import javax.script.SimpleScriptContext; -import junit.framework.TestCase; - import org.junit.Assert; import org.python.core.Options; +import org.python.core.PyList; import org.python.core.PyString; +import junit.framework.TestCase; + public class ScriptEngineTest extends TestCase { public void testEvalString() throws ScriptException { @@ -160,25 +161,37 @@ public void testBindings() throws ScriptException { assertNull(pythonEngine.get("x")); } - class ThreadLocalBindingsTest implements Runnable { + static class ThreadLocalBindingsTest implements Runnable { ScriptEngine engine; + int value; Object x; + Object name; Throwable exception; - public ThreadLocalBindingsTest(ScriptEngine engine) { + public ThreadLocalBindingsTest(ScriptEngine engine, int value) { this.engine = engine; + this.value = value; } + //@formatter:off + static final String script = String.join("\n", new String[] { + "try:", + " a", + "except NameError:", + " pass", + "else:", + " raise Exception('a is defined', a)"}); + //@formatter:on + @Override public void run() { try { Bindings bindings = engine.createBindings(); - assertNull(engine.eval( - "try: a\nexcept NameError: pass\nelse: raise Exception('a is defined', a)", - bindings)); - bindings.put("x", -7); + assertNull(engine.eval(script, bindings)); + bindings.put("x", value); x = engine.eval("x", bindings); + name = engine.eval("__name__", bindings); } catch (Throwable e) { e.printStackTrace(); exception = e; @@ -186,6 +199,13 @@ public void run() { } } + /** + * Test that, with the use of a {@code Bindings} argument to {@code ScriptEngine.eval}, the + * interpreter is presented with a distinct name space, whether in a thread or not, and + * that __name__ == "__main__" in the engine-scoped name space (only). + * + * @throws Exception + */ public void testThreadLocalBindings() throws ScriptException, InterruptedException { ScriptEngineManager manager = new ScriptEngineManager(); ScriptEngine pythonEngine = manager.getEngineByName("python"); @@ -193,15 +213,27 @@ public void testThreadLocalBindings() throws ScriptException, InterruptedExcepti pythonEngine.put("a", 42); pythonEngine.put("x", 15); - ThreadLocalBindingsTest test = new ThreadLocalBindingsTest(pythonEngine); - Thread thread = new Thread(test); - thread.run(); - thread.join(); + // Examine name space of the engine with Bindings + ThreadLocalBindingsTest test = new ThreadLocalBindingsTest(pythonEngine, -7); + test.run(); // This does not start a thread assertNull(test.exception); assertEquals(-7, test.x); + assertEquals("__builtin__", test.name); + + // Examine name space of the engine with Bindings and in a thread + ThreadLocalBindingsTest test2 = new ThreadLocalBindingsTest(pythonEngine, -22); + Thread thread = new Thread(test2); + thread.start(); // This *does* start a thread + thread.join(); + assertNull(test2.exception); + assertEquals(-22, test2.x); + assertEquals("__builtin__", test2.name); + + // Test name space of the pythonEngine without Bindings is unaffected assertEquals(15, pythonEngine.get("x")); assertNull(pythonEngine.eval("del x")); assertNull(pythonEngine.get("x")); + assertEquals("__main__", pythonEngine.eval("__name__")); } public void testInvoke() throws ScriptException, NoSuchMethodException { @@ -295,9 +327,10 @@ public void testScope_iter() throws ScriptException { ScriptEngine pythonEngine = manager.getEngineByName("python"); pythonEngine.eval("a = 4"); pythonEngine.eval("b = 'hi'"); - assertEquals( - "['__builtins__', 'a', 'b']", - pythonEngine.eval("repr(sorted((item for item in locals())))")); + PyList locals = (PyList) pythonEngine.eval("sorted((item for item in locals()))"); + Assert.assertTrue(locals.contains("a")); + Assert.assertTrue(locals.contains("b")); + Assert.assertTrue(locals.contains("__name__")); } public void testScope_lookup() throws ScriptException {