On Sat, Jan 17, 2009 at 5:47 PM, Marc Downie <marc@openendedgroup.com> wrote:


I added an example of how I'd do this and a test case that exercises
the example in r5940.  All of the method wrapping action is in
http://tr.im/994n

The basic technique is to create a subclass of PyBuiltinMethodNarrow
that has implementations of __call__ for the argument widths you're
after.  That new method is added to the PyJavaType for the class in
question to override its default behavior.  In the case of
__getattribute__ -  the method you want to use instead of __findattr__
from PyJavaClass - it grabs the PyObject version of __getattribute__
and first tries that to see if the class already has an attribute
under that name.  If it doesn't find an existing attribute, it returns
whatever the Map held by that class has for that name.  If that all
sounds pretty vague, I think the code makes it a little clearer.
PyJavaType itself also contains several examples of code like this.

Ok, I have this approach 'working' (and is about a third of the length of my old code).

However, there's a surprise (for me at least). Attaching special methods to java interfaces doesn't work and I can't tell if it's by design or not:

If I write (as you wrote in your example):

PyType.fromClass(MyClass.class).addMethod(myGetAttribute) 

All is well for MyClass instances and all instances of subclasses of MyClass. myGetAttribute gets called when I'd expect it to get called.

But if MyClass implements MyInterface and I write:

PyType.fromClass(MyInterface.class).addMethod(myGetAttribute) 

myGetAttribute will never be called on any instances that implement MyInterface.

Staring at the debugger, all Java interfaces are put after <type 'object'> in the computed MRO for the PyJavaType of any Java Instance that happen to implement MyInterface. So 'object' supplies the first __getattribute__ for the instances of that type and myGetAttribute never called. 

The same is true of any other '__xxx___' method that 'object' has. While 'object' doesn't actually include __getattr__ (which I could use in this case rather than __getattribute__) it does include __setattr__ & __delattr__ . This seams to mean. confusingly enough, in the case of __setattr__ that I get mySetAttr called and an AttributeError printed to stderr.

I'm not actually sure how to re-architect my app which uses Java-idiomatic like interfaces like 'Extensible', 'HandlesAttributes' to mark java classes wanting extra Python magic upon bridging in a nice way. I can think of plenty of slightly-not-nice ways of doing it. 

Anyway, acceptable responses, as always, include: 'file a bug report' and 'it's supposed to be like this'.

best,

Marc.