Title: Wrong name of the top-level scope when running Jython under Java Scripting API
Type: behaviour Severity: normal
Components: Core Versions: Jython 2.7.1
Milestone: Jython 2.7.2
Status: open Resolution: accepted
Dependencies: Superseder:
Assigned To: Nosy List: alexgobbo, jeff.allen, zyasoft
Priority: normal Keywords:

Created on 2019-12-11.13:18:40 by alexgobbo, last changed 2019-12-22.07:58:35 by jeff.allen.

msg12822 (view) Author: A. Gobbo (alexgobbo) Date: 2019-12-11.13:18:39
Both in Jython 2.7.1 ands 2.7.2b2 the name of the top-level scope is wrong when running Jython under Java Scripting API.

If you execute:
   org.python.util.PythonInterpreter interp = new org.python.util.PythonInterpreter();
   interp.exec("print __name__");

You get the familiar:

However, executing: 
   javax.script.ScriptEngine engine = new javax.script.ScriptEngineManager().getEngineByName("python");
   engine.eval("print __name__");
You get:

This creates of course a lot of problems. 
Many people do local workarounds like in their code:
  if __name__ in ['__builtin__', '__main__']:

I make a more global workaround to cope with code within libraries checking __name__. 
Just after initialising the engine I do:
   engine.put("__name__", "__main__");
   engine.eval("import sys");

This solve some issues, but not all. 
In particularly it is a show stopper for unittest, which does not work at all under Java Scripting API.

Note: This is an old bug, which has been reported in other places, but I didn't find it in bugs.jython:
msg12830 (view) Author: A. Gobbo (alexgobbo) Date: 2019-12-13.08:08:15
This seems to be deliberate. In the constructor of PythonInterpreter PyModule("__main__"...) is only created if !useThreadLocalState. This parameter set to true only by /jsr223/
msg12832 (view) Author: Jeff Allen (jeff.allen) Date: 2019-12-13.23:25:56
Ah, I see. It's not that we set __name__ to this surprising value. Rather, __name__ is resolved by look-up in locals, globals and builtins, and found in the last.

The difficulty is to be sure of the intent of the design. It looks like ScriptEngine.eval() is the rough equivalent of the exec statement with a user-supplied dictionary (CPython 2.7.16):

>>> exec "print globals().keys()" in {}

Jython 2.7.2b3:

>>> from javax.script import ScriptEngineManager
>>> engine = ScriptEngineManager().getEngineByName("python")
>>> engine.eval("print globals().keys()")

You're evidently expecting it to be more like executing a file using the python command. Hard to say who's right.
msg12872 (view) Author: Jeff Allen (jeff.allen) Date: 2019-12-22.07:58:35
Having poked around a bit, it looks harmless to meet these expectations, but I wish I understood the thread-dependent logic here and (what seems to be) a deliberate choice not to create a module.
Date User Action Args
2019-12-22 07:58:35jeff.allensetmessages: + msg12872
2019-12-13 23:25:56jeff.allensetnosy: + jeff.allen, zyasoft
messages: + msg12832
2019-12-13 08:08:15alexgobbosetmessages: + msg12830
2019-12-13 07:58:08jeff.allensetpriority: normal
resolution: accepted
milestone: Jython 2.7.2
2019-12-11 13:18:40alexgobbocreate