Issue2717

classification
Title: Arguments mis-handled passing **kwargs from Java to Python
Type: Severity: normal
Components: None Versions: Jython 2.7
Milestone:
process
Status: open Resolution:
Dependencies: Superseder:
Assigned To: Nosy List: jeff.allen, mohamad.mahajna, stefan.richthofer
Priority: normal Keywords:

Created on 2018-11-23.19:39:19 by mohamad.mahajna, last changed 2018-12-04.11:37:04 by mohamad.mahajna.

Messages
msg12183 (view) Author: mohamad (mohamad.mahajna) Date: 2018-11-23.19:39:18
how to pass **kwargs form java to python using Jython .

The python method :

def start_trex (self, f, d, block_to_success = True, timeout = 40, user = None, trex_development = False, **trex_cmd_options):

My java code :

Map<String, Object> kwargs = new HashMap<>();
kwargs.put("cfg","/etc/trex_cfg_stf.yaml");
boolean z =objectTrex.start_trex("astf/http_simple.py",20,true,40,"momham",true,kwargs);
I'm getting the following error :

Exception in thread "MainThread" TypeError: start_trex() takes at most 7 arguments (8 given)

although i passing just 7 arguments I think the problem with the way of passing the **kwargs argument
msg12191 (view) Author: Jeff Allen (jeff.allen) Date: 2018-12-02.08:24:35
The figure supplied as the number of arguments in that message from Python (not just Jython) can be off by one from what you'd expect, because of the treatment of 'self'.

I assume your "def start_trex (self, ..." is within a class definition and objectTrex is an instance of that class in Java. At a first look, what you've done appears right. I (or someone else) would have to step through the call to see what actually happens during the argument processing, in a toy version of the problem. Could you provide a bit more context, or an equivalent demonstration of the problem in isolation?

Also, what version of Jython are you on?
msg12192 (view) Author: mohamad (mohamad.mahajna) Date: 2018-12-02.11:01:10
Also, what version of Jython are you on?
jython-standalone-2.7.1

Python class : 

	#!/router/bin/python

	from trexImp import TrexClient
	class testAdd(TrexClient):
	    def func1 (self,**kwargs):
	        print(kwargs)

Java code : 

Interface : 

	import java.util.Map;
	public interface TrexClient{
	    public void func1(Map<String,String> kwargs);
	}

Class :
	
	import org.python.core.*;
	import org.python.util.PythonInterpreter;

	import java.util.HashMap;
	import java.util.Map;


	public class TrexClientFactory {
	    public TrexClientFactory() {
	        PythonInterpreter interpreter = new PythonInterpreter();
	        interpreter.exec("import sys");
	        interpreter.exec("sys.path.append('/Users/mohamad.mahajna/IdeaProjects/new_stepsNG/aa/src/main/javatrex_stf_lib1')");
	        interpreter.exec("from testAdd import *");
	        PyObject trexClientClass = interpreter.get("testAdd");
	        PyObject buildingObject = trexClientClass.__call__();
	        TrexClient x = (TrexClient) buildingObject.__tojava__(TrexClient.class);
	        Map<String,String> kwargs = new HashMap<>();
	        kwargs.put("cfg","abcf");
	        x.func1(kwargs);
	    }

	}

	Exception in thread "main" TypeError: func1() takes exactly 1 argument (2 given)
msg12193 (view) Author: Stefan Richthofer (stefan.richthofer) Date: 2018-12-04.03:24:33
Mohamad,
I am not sure if this type of coercion is currently supported by Jython. 
There is one more thing you can try. Internally, Jython represents Python functions in Java with the same signature style as PyObject.__call__.
PyObject.__call__, see http://www.javadoc.io/doc/org.python/jython-standalone/2.7.1

For your use-case this is relevant:
PyObject __call__(PyObject[] args, String[] keywords)

Please try it like this:

public interface TrexClient{
  public void func1(PyObject[] args, String[] keywords);
}
msg12194 (view) Author: mohamad (mohamad.mahajna) Date: 2018-12-04.09:17:31
Still the same error : 

public interface TrexClient{
  public void func1(PyObject[] args, String[] keywords);
}


PythonInterpreter interpreter = new PythonInterpreter();
        interpreter.exec("import sys");
        interpreter.exec("sys.path.append('/Users/mohamad.mahajna/IdeaProjects/new_stepsNG/aa/src/main/java/trex_stf_lib1')");
        interpreter.exec("from testAdd import *");
        PyObject trexClientClass = interpreter.get("testAdd");
        PyObject buildingObject = trexClientClass.__call__();
        TrexClient x = (TrexClient) buildingObject.__tojava__(TrexClient.class);
//        Map<String,PyObject> kwargs = new HashMap<>();
//        kwargs.put("cfg",new PyString("abcf"));
        x.func1(new PyObject[]{},new String[]{"cfg:123"});


Exception in thread "main" TypeError: func1() takes exactly 1 argument (3 given)
msg12195 (view) Author: Stefan Richthofer (stefan.richthofer) Date: 2018-12-04.10:11:31
For the record, the call would have to be

x.func1(new PyObject[]{"123"},new String[]{"cfg"});

In case the binding to x was messed up for some reason, also

x.func1(new PyObject[]{x, "123"}, new String[]{"cfg"});

would be worth a try (i.e. explicitly providing self).
However, this will probably make no difference given the error message. On the other hand, these things are involved and the error message might not be reliable. Then I suppose Jython's Java binding abilities do not cover this case. A workaround using a more explicit signature would be the way to go for now.
msg12196 (view) Author: Stefan Richthofer (stefan.richthofer) Date: 2018-12-04.10:13:13
In the examples above, use

new PyString("123")

instead of plain "123".
msg12197 (view) Author: mohamad (mohamad.mahajna) Date: 2018-12-04.11:37:04
the same error .
History
Date User Action Args
2018-12-04 11:37:04mohamad.mahajnasetmessages: + msg12197
2018-12-04 10:13:13stefan.richthofersetmessages: + msg12196
2018-12-04 10:11:31stefan.richthofersetmessages: + msg12195
2018-12-04 09:17:32mohamad.mahajnasetmessages: + msg12194
2018-12-04 03:24:34stefan.richthofersetnosy: + stefan.richthofer
messages: + msg12193
2018-12-02 11:01:11mohamad.mahajnasetmessages: + msg12192
2018-12-02 08:24:36jeff.allensetpriority: normal
nosy: + jeff.allen
messages: + msg12191
title: passing**kwargs form java to python using Jython -> Arguments mis-handled passing **kwargs from Java to Python
2018-11-23 19:39:19mohamad.mahajnacreate