Skip to content

Commit

Permalink
Create a __main__ module and set __name__ in JSR-223 (fixes #2846).
Browse files Browse the repository at this point in the history
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
  • Loading branch information
jeff5 committed Jan 30, 2020
1 parent bb660f5 commit 528d027
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 19 deletions.
1 change: 1 addition & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
6 changes: 2 additions & 4 deletions src/org/python/util/PythonInterpreter.java
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
63 changes: 48 additions & 15 deletions tests/java/org/python/jsr223/ScriptEngineTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -160,48 +161,79 @@ 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;
}
}
}

/**
* 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");

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 {
Expand Down Expand Up @@ -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 {
Expand Down

0 comments on commit 528d027

Please sign in to comment.