[ZODB-Dev] ExtensionClass/Persistent and __cmp__ is tricky

Christian Reis kiko at async.com.br
Sat Jun 28 00:57:24 EDT 2003


So I read the docs on BTrees and `Total Ordering' at
http://www.zope.org/Wikis/ZODB/guide/node6.html again. One of the key
points here (as Tim pointed out) is that __cmp__ has to be carefully
designed:

    If you want to use class instances as keys, and there's any possibility
    that the structure may be stored in a database, it's crucial that the
    class define a __cmp__() method, and that the method is carefully
    implemented.

I'm fine with this, so I started some verification of the __cmp__ method
on IndexedObject, our Persistent-derived class. The first, basic, test I
did, however, bothers me because it seems to echo something similar to
what Greg Ward suggested back in
http://mail.zope.org/pipermail/zope-dev/2000-May/004420.html -- that
cmp() is not completely compatible with ExtensionClass. Here's my
(short) example:

    >>> from ZODB import Persistent
    >>> class Foo(Persistent):
    ...    def __cmp__(self, other):
    ...     print "Hi there"
    ...     return cmp(self, other)
    ... 
    >>> 
    >>> f = Foo()
    >>> f < 1
    Hi there [ repeated 21 times ]
    >>> f > 1
    Hi there [ repeated 21 times ]
    >>> 1 < f
    0
    >>> 1 > f
    1

This goes against what I understand of the cmp() protocol. The PSL docs
say:

   __cmp__(self, other)
       Called by comparison operations if rich comparison (see above) is
       not defined. Should return a negative integer if self < other,
       zero if self == other, a positive integer if self > other. If no
       __cmp__() operation is defined, class instances are compared by
       object identity (``address''). (Note: the restriction that
       exceptions are not propagated by __cmp__() has been removed in
       Python 1.5.)

Am I understanding this correctly? It seems you can't compare
ExtensionClass with basic types; in Python 2.1.3 at least it appears to
me that try_3way_compare doesn't want to call tp_compare on the second
instance because it's not a PyInstance.

PS: The interesting part is that it seems that comparing lists *does*
work:

    >>> [] > f
    Hi there [ repeated 21 times ]
    0

Which means I'm almost safe with using PersistentList, at any rate
(which uses its List comparison). 

PPS: Anybody know why 21 times?

Take care,
--
Christian Reis, Senior Engineer, Async Open Source, Brazil.
http://async.com.br/~kiko/ | [+55 16] 261 2331 | NMFL



More information about the ZODB-Dev mailing list