1

NB this is really a question for Jython devotees but seems to highlight a design difficulty in the language

if I do sthg like this

class XTreeModel( DefaultTreeModel ):  
  def fireTreeNodesInserted( self, source, path, child_indices, children ):
    print "fire nodes inserted"
    super( XTreeModel, self ).fireTreeNodesInserted( source, path, child_indices, children )

I get infinite recursion. When I first encountered this I was very puzzled. I still don't understand why the code can't call the Java superclass (baseclass) method, and instead calls itself again (!). To prevent this I go

class XTreeModel( DefaultTreeModel ):  
  def fireTreeNodesInserted( self, source, path, child_indices, children ):
    print "fire nodes inserted"
    self.super__fireTreeNodesInserted( source, path, child_indices, children )

... and I have learnt since starting to use Jython that these Java-base-class-calling "super__XXX" methods are in fact created spontaneously by the Jython interpreter, and only if you override a Java method in a Jython class which subclasses a Java class (as above). This is OK as far as it goes... but what if you don't know whether your superclass (baseclass) is or is not a Java class? I eventually developed the following utility method:

def get_super_method( caller, code_class ):
  stack_1 = inspect.stack()[ 1 ]
  func_name = stack_1[ 3 ]
  # unfortunately this will return code_class.func_name as standard if code_class is a derived from a Java class with method func_name
  supposed_baseclass_method = getattr( super( code_class, caller ), func_name )
  for baseclass in caller.__class__.__base__.__mro__:
    if "org.python.proxies" in str( baseclass ):
      # ... this means we have reached down as low as a Java "proxy" class without yet encountering a class with a method 'func_name',
      # which means that we must return the super__XXX version
      break
    # confusingly, even if you go caller.__class__.__base__.__mro__ this still shows all the classes for caller, including its highest class! 
    if baseclass == code_class:
      continue
    if func_name in baseclass.__dict__:
      # ... a method with the right name exists in a baseclass...
      return supposed_baseclass_method 
  java_baseclass_method = getattr( caller, "super__%s" % func_name )
  return java_baseclass_method

which you call by going, for example:

class XTreeModel( DefaultTreeModel ):  
  def fireTreeNodesInserted( self, source, path, child_indices, children ):
    print "X fire nodes inserted"
    get_super_method( self, XTreeModel )(source, path, child_indices, children )

class XXTreeModel( XTreeModel ):  
  def fireTreeNodesInserted( self, source, path, child_indices, children ):
    print "XX fire nodes inserted"
    get_super_method( self, XXTreeModel )(source, path, child_indices, children )

Here get_super_method in XXTreeModel returns super( XXTreeModel, self )... whereas get_super_method in XTreeModel returns self.super__fireTreeNodesInserted so... maybe you could just look at the code_class passed to get_super_method and if it has "org.python.proxies" in the name of its immediate baseclass that means you return the super__XXX version, right? Er, no, it's a bit more complicated:

class XTreeModel( DefaultTreeModel ):  
  def do_some_stuff( self ):
    print "do stuff"

class XXTreeModel( XTreeModel ):  
  def fireTreeNodesInserted( self, source, path, child_indices, children ):
    print "XX fire nodes inserted"
    get_super_method( self, XXTreeModel )(source, path, child_indices, children )

In this example, the XXTreeModel has a Jython class as its baseclass but this baseclass (XTreeModel) doesn't override the method of interest... so in fact get_super_method() in XXTreeModel needs to return super__ fireTreeNodesInserted... ... so this utility method seems to solve the problem: you don't need to know what type of class your baseclass is, whether or not it overrides the Java method, etc. Anyway, I wanted to find out whether this tortuous procedure was necessary, but googling "jython super" etc. produced bug entries from 10 years ago saying things like "use of super__ methods is deprecated".

Is there a better way to accomplish this calling of the superclass methods where your first baseclass (as you move down through the classes) with the method sought is in fact a Java class???

mike rodent
  • 14,126
  • 11
  • 103
  • 157

1 Answers1

0

So I'm pretty sure you can use the not-ideal form of BaseClass.method(self, *args, **kwargs) to get the behavior you're looking for, also. That's "old school" (pre 2.2) access to base class methods.

Geoff Gerrietts
  • 646
  • 4
  • 9
  • thanks... but I wouldn't have gone to such lengths if the answer were this easy. The point is to cater for a situation where you don't know whether the base class is a Java (proxy) class or a "genuine" Jython class, derived from a Java (proxy) class lower down the hierarchy. Perhaps you're just hoping that Jython is as simple as Python... but no, there is a price to be paid for the incredible power of combining Java and Python... – mike rodent May 13 '13 at 18:57
  • Well, it worked okay for me, but in looking at the code, I am calling a Jython class, not a Java one. When I used super() in the correct form, I got the "infinite recursion" bug; I shifted to the BaseClass.method form and things worked. My method also doesn't support mixins in subclasses but then I don't need subclasses. :) – Geoff Gerrietts May 15 '13 at 19:44
  • ATGeoff thanks again... but the point about my question was to find out what you do when you don't know what the name of the BaseClass is... unfortunately just using super() doesn't work and in fact for these "Java proxy"-level classes, Jython creates, on the fly and when required, methods of the type "super__fireTreeNodesInserted" for them (see above, if you're interested enough to read through my question...) – mike rodent Jun 29 '13 at 20:17
  • I read it. For the record, super() should work. Its current behavior is a defect, and it's broken for "pure python" classes in Jython also. – Geoff Gerrietts Jul 17 '13 at 20:11