Issue2846

classification
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
process
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.

Messages
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:
   __main__

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

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");
   engine.eval("sys.modules['__main__']=sys.modules['__builtin__']"); 

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:
   https://github.com/scijava/scripting-jython/issues/9
   https://forum.image.sc/t/jython-isssue-with-if---name-----main--/5544
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/PyScriptEngine.java
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 {}
['__builtins__']

Jython 2.7.2b3:

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

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.
History
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