Philip Jenvey wrote:

On Feb 11, 2009, at 7:54 AM, Sébastien Boisgérault wrote:


Hi,

The code below exposes a bug that was introduced in revision 5739 (the
newstyle-java-types merge).
As far as I can tell, the current revision (6024) as well as the beta
have the same problem.

The example below is still complex and I could probably find a smaller
example that exhibits the same issue.
Before I do that (and before I submit a new bug report), does anyone
recognize a known issue ?
Has anyone a hint about what the problem is ?

AFAICT this should have never worked

Your Element class provides its own getFirstChild method that will always be looked up before __getattr__ is tried. That's explained here: http://docs.python.org/reference/datamodel.html#object.__getattr__

Since java types are new style now, you can get this behavior by overriding __getattribute__ instead.

Philip,

Thanks for the explanation, I think I now get the picture: __getattr__ being a fallback method, it is never called because a getFirstChild method is found in the object hierarchy, right ? This is the standard Python behavior for __getattr__, no issue here.

However, I consider as a surprise that the getFirstChild method is found in the hierarchy because the parent class ... is not a java class but a java interface, so I feel that the org.w3c.dom.Element getFirstChild method "does not really exist" and "should not be found", so the current behavior violates the principle of least surprise (for my heavily damaged brain ;)). Does the current behavior feel right to you ? At least the pre-5739 revision behavior seems to match the "interface methods do not really exist" philosophy (by design or accident).

I was also surprised to see that interface methods have always been available:
>>> org.w3c.dom.Element.getFirstChild
<java function getFirstChild 0x1>

but that's ok, because an error, if delayed until method call, is finally raised:

>>> org.w3c.dom.Element.getFirstChild(root)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
        at java.lang.Class.getMethod(Class.java:1605)

java.lang.NoSuchMethodException: java.lang.NoSuchMethodException: org.python.proxies.__main__$Element$1.super__getFirstChild()

(that still that feels slightly weird to me: the exception NoSuchMethodException is named as if it should be raised when we try to get the method, not call it. A standard python 'NotImplementedError' feels more natural when the method is invoked ... nitpicking I guess.)

Worse, in my example, the method does not raise any error when it is called, it simply returns None. At this stage, any error (NoSuchMethod or NotImplemented) would have been a huge hint. Do we have at this stage a hidden 'default implementation' for interface methods that does nothing (returns None) in this situation ?

But maybe I got something plain wrong in this analysis ?

Cheers,

SB





--
Philip Jenvey



# J2SE
import java.io
import javax.xml.parsers
import org.w3c.dom.Element

# Jython
import org.python.core.util

def XML(text):
    bytes = org.python.core.util.StringUtil.toBytes(text)
    byte_stream = java.io.ByteArrayInputStream(bytes)
    factory = javax.xml.parsers.DocumentBuilderFactory.newInstance()
    factory.setNamespaceAware(True)
    doc = factory.newDocumentBuilder().parse(byte_stream)
    return Element(doc.getDocumentElement())

class Element(org.w3c.dom.Element):
    def __init__(self, root):
        self._root = root
    def __getattr__(self, key):
        return getattr(self._root, key)

#------------------------------------------------------------------------------
root = XML("<root><a/></root>")
assert root.getFirstChild() is not None