Issue1681

classification
Title: JSR-223, Jython 2.5.2 and implementing Java Interfaces from Python
Type: behaviour Severity: major
Components: Core Versions: 2.5.1, 2.5b1, 2.5b0, 2.5.0, 2.5.2b1, 2.5.2rc
process
Status: closed Resolution: fixed
Dependencies: Superseder:
Assigned To: Nosy List: nriley, otmarhumbel, pjenvey, zyasoft
Priority: Keywords: patch

Created on 2010-12-05.10:09:13 by otmarhumbel, last changed 2010-12-24.01:37:07 by pjenvey.

Files
File name Uploaded Description Edit Remove
1681-type-check.diff pjenvey, 2010-12-24.00:22:34
Messages
msg6267 (view) Author: Oti Humbel (otmarhumbel) Date: 2010-12-05.10:09:13
[submitted on behalf of Christian Blichmann]

Calling methods from an embedded Jython script does nothing when
using JSR-223 and Jython 2.5.2rc2, while Jython 2.2.1 just works fine.

- ------------- myscript/ScriptingTest.java -------------
package myscript;

import java.io.InputStream;
import java.io.InputStreamReader;

import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;

public class ScriptingTest {
   public static void main(String[] args) {
       try {
           final ScriptEngineManager manager =
               new ScriptEngineManager();
           final ScriptEngine engine =
               manager.getEngineByName("python");

           final InputStream is =
               ScriptingTest.class.getResourceAsStream(
                       "/myscript/myscript.py");
           engine.eval(new InputStreamReader(is));
       } catch (final Exception e) {
           e.printStackTrace();
       }
   }
}
- ------------- myscript/PythonCallable.java -------------
package myscript;

public interface PythonCallable {
   String getAString();
   void callAVoid();
}
- ------------- myscript/myscript.py -------------
from myscript import PythonCallable as PythonCallable

class MyPythonCallable(PythonCallable):
   def getAString(self):
       return 'A string'

   def callAVoid(self):
       print 'Called a void method'

print 'getAString() returns: %s' % \
   MyPythonCallable().getAString()
print 'callAVoid():'
MyPythonCallable().callAVoid()
- ------------------------------------------------

Using Jython 2.2.1, I get:
 $ java -cp .:jython.jar:jython-engine.jar myscript.ScriptingTest
 getAString() returns: A string
 callAVoid():
 Called a void method
msg6292 (view) Author: Philip Jenvey (pjenvey) Date: 2010-12-22.20:55:27
The problem here lies in PyScriptEngineScope.__setitem__. All values that pass through it are first converted via value.__tojava__(Object.class)

In this case, the __tojava__ call is made on the user defined MyPythonCallable class. Its __tojava__ returns its Proxy object here, which is the cause of the havoc we're seeing

I'm not sure who's at fault -- Nick, what's the point of the __tojava__(Object.class) call here? Is it necessary in all cases?

We either need to add special cases to the scope__setitem__, or fix the __tojava__ result for user defined classes that have an underlying proxy. Might the latter break anything else?
msg6293 (view) Author: Nicholas Riley (nriley) Date: 2010-12-22.23:53:00
I never really understood the full implications of __tojava__ so I think I was probably just copying something else (perhaps the previous JSR 223 implementation).  Please feel free to change it as you wish.
msg6295 (view) Author: Philip Jenvey (pjenvey) Date: 2010-12-24.00:22:33
It seems the original jsr223 impl had a similar issue to this one:

https://scripting.dev.java.net/issues/show_bug.cgi?id=5

Its fix (which was really for Jython 2.2) basically added this line to __setitem__

            if (!(obj instanceof PyClass)) {
                obj = JythonScriptEngine.py2java(value);
            }

This isn't the most efficient fix in the world (adding an instanceof check for any kind of assignment). But whatever -- I propose the attached patch with a similar fix
msg6296 (view) Author: Philip Jenvey (pjenvey) Date: 2010-12-24.00:23:12
Their JythonScope class with their fix is here:

https://scripting.dev.java.net/source/browse/scripting/engines/jython/src/com/sun/script/jython/JythonScope.java?rev=1.2&view=markup
msg6297 (view) Author: Philip Jenvey (pjenvey) Date: 2010-12-24.00:26:11
I mean, we're already doing a __tojava__(Object.class) for every assignment so an additional instanceof check shouldn't matter
msg6301 (view) Author: Philip Jenvey (pjenvey) Date: 2010-12-24.01:37:07
fix+test applied in r7175
History
Date User Action Args
2010-12-24 01:37:07pjenveysetstatus: open -> closed
resolution: fixed
messages: + msg6301
2010-12-24 00:26:11pjenveysetmessages: + msg6297
2010-12-24 00:23:12pjenveysetmessages: + msg6296
2010-12-24 00:22:34pjenveysetfiles: + 1681-type-check.diff
keywords: + patch
messages: + msg6295
2010-12-22 23:53:00nrileysetmessages: + msg6293
2010-12-22 20:55:27pjenveysetnosy: + pjenvey, zyasoft, nriley
messages: + msg6292
2010-12-13 08:21:44cblichmannsetseverity: normal -> major
versions: + 2.5b0, 2.5.1, 2.5b1, 2.5.0, 2.5.2rc
2010-12-05 10:09:13otmarhumbelcreate