As the type mapping is written inside a class written in Java, I was confronted to the problem of how to instantiate datetime.* objects, which (by now) Jython implements using pure python code. The answer was very simple: Just do by hand what Python always does when you write:
import datetime
datetime.date(year, month, day)
You know, the import statement is implemented by the __import__ builtin, foo.bar is getattr(foo, 'bar') and f(x) is f.__call__(x). Then, the following is equivalent to the previous snippet:
datetime = __import__('datetime')
getattr(datetime, 'date').__call__(year, month, day)
Which, translated to Java/Jython looks almost the same:
PyObject datetime = __builtin__.__import__('datetime')
datetime.__getattr__('date').__call__(Py.newInt(year),
Py.newInt(month),
Py.newInt(day))
Once you get the idea, not only instantiating, but doing anything with classes written with Jython from Java code looks like a piece of cake.
Hey!, How easiest could it be?
Note that this works if all the Jython machinery is in place. This will be the case if your Java code is being called (directly or indirectly) from python code being ran on Jython. As any Jython module, such as zxJDBC, is always used from python code, this is something to have in mind when writing them in Java.


2 comments:
BTW, apparently .invoke() is preferable to .__getattr__().__call__(). See pjenvey's fix for my commit r5070. (Since I actually used your weblog entry to figure out how to do this, I figured it would make sense to post a correction here. :-)
Hmm, but I see that we have no invoke() shortcut for 3 args (as opposed to the 3-args __call__). Maybe it is just a matter of adding it?
BTW, the javadoc of invoke() sort of over-specify it, by saying that it calls a method on a PyObject. By looking at the implementation it will also work on my case, where I need to instantiate a class which is an attribute of its module.
Or maybe this over-specification is intentional, in order to allow future optimizations?
Post a Comment