[Zope-dev] Comparison inconsistency with ExtensionClass
   
    Greg Ward
     
    gward@mems-exchange.org
       
    Mon, 1 May 2000 19:31:37 -0400
    
    
  
Hi all --
I seem to have discovered an inconsistency in the semantics of object
comparison between plain old Python instances and ExtensionClass
instances.  (I've cc'd python-dev because it looks as though one *could*
blame Python for the inconsistency, but I don't really understand the
guts of either Python or ExtensionClass enough to know.)
Here's a simple script that shows the difference:
    class Simple:
        def __init__ (self, data):
            self.data = data
        def __repr__ (self):
            return "<%s at %x: %s>" % (self.__class__.__name__,
                                       id(self),
                                       `self.data`)
        def __cmp__ (self, other):
            print "Simple.__cmp__: self=%s, other=%s" % (`self`, `other`)
            return cmp (self.data, other)
    if __name__ == "__main__":
        v1 = 36
        v2 = Simple (36)
        print "v1 == v2?", (v1 == v2 and "yes" or "no")
        print "v2 == v1?", (v2 == v1 and "yes" or "no")
        print "v1 == v2.data?", (v1 == v2.data and "yes" or "no")
        print "v2.data == v1?", (v2.data == v1 and "yes" or "no")
If I run this under Python 1.5.2, then all the comparisons come out true
and my '__cmp__()' method is called twice:
    v1 == v2? Simple.__cmp__: self=<Simple at 1b5148: 36>, other=36
    yes
    v2 == v1? Simple.__cmp__: self=<Simple at 1b5148: 36>, other=36
    yes
    v1 == v2.data? yes
    v2.data == v1? yes
The first one and the last two are obvious, but the second one only
works thanks to a trick in PyObject_Compare():
    if (PyInstance_Check(v) || PyInstance_Check(w)) {
        ...
        if (!PyInstance_Check(v))
	    return -PyObject_Compare(w, v);
        ...
    }
However, if I make Simple an ExtensionClass:
    from ExtensionClass import Base
    class Simple (Base):
Then the "swap v and w and use w's comparison method" no longer works.
Here's the output of the script with Simple as an ExtensionClass:
    v1 == v2? no
    v2 == v1? Simple.__cmp__: self=<Simple at 1b51c0: 36>, other=36
    yes
    v1 == v2.data? yes
    v2.data == v1? yes
It looks as though ExtensionClass would have to duplicate the trick in
PyObject_Compare() that I quoted, since Python has no idea that
ExtensionClass instances really should act like instances.  This smells
to me like a bug in ExtensionClass.  Comments?
BTW, I'm using the ExtensionClass provided with Zope 2.1.4.  Mostly
tested with Python 1.5.2, but also under the latest CVS Python and we
observed the same behaviour.
        Greg
-- 
Greg Ward - software developer                gward@mems-exchange.org
MEMS Exchange / CNRI                           voice: +1-703-262-5376
Reston, Virginia, USA                            fax: +1-703-262-5367