Re: [Zope-dev] [Checkins] SVN: zope.interface/trunk/ Correct comparison of interfaces from different modules but with the same name.
Hello, I ran tests in some zope modules with python3.2, and got an exception: $ cd zope.proxy $ python3.2 setup.py test ... File "/home/menesis/src/zope.proxy/build/lib.linux-i686-3.2/zope/proxy/__init__.py", line 16, in <module> from zope.interface import moduleProvides File "/home/menesis/src/zope.proxy/zope.interface-3.6.3-py3.2-linux-i686.egg/zope/interface/__init__.py", line 53, in <module> from zope.interface.interface import Interface, _wire File "/home/menesis/src/zope.proxy/zope.interface-3.6.3-py3.2-linux-i686.egg/zope/interface/interface.py", line 710, in <module> Interface = InterfaceClass("Interface", __module__ = 'zope.interface') File "/home/menesis/src/zope.proxy/zope.interface-3.6.3-py3.2-linux-i686.egg/zope/interface/interface.py", line 479, in __init__ Specification.__init__(self, bases) File "/home/menesis/src/zope.proxy/zope.interface-3.6.3-py3.2-linux-i686.egg/zope/interface/interface.py", line 266, in __init__ self.__bases__ = tuple(bases) File "/home/menesis/src/zope.proxy/zope.interface-3.6.3-py3.2-linux-i686.egg/zope/interface/interface.py", line 290, in __setBases self.changed(self) File "/home/menesis/src/zope.proxy/zope.interface-3.6.3-py3.2-linux-i686.egg/zope/interface/interface.py", line 309, in changed ancestors = ro(self) File "/home/menesis/src/zope.proxy/zope.interface-3.6.3-py3.2-linux-i686.egg/zope/interface/ro.py", line 22, in ro return mergeOrderings([_flatten(object)]) File "/home/menesis/src/zope.proxy/zope.interface-3.6.3-py3.2-linux-i686.egg/zope/interface/ro.py", line 51, in mergeOrderings if o not in seen: TypeError: unhashable type: 'InterfaceClass' I found the following to explain what happens: http://stackoverflow.com/questions/1608842/types-that-define-eq-are-unhashab... And a commit which does exactly that: define an __eq__ but not __hash__. Adding a simple def __hash__(self): return id(self) fixes the problem. This change was released as zope.interface 3.6.3. Earlier version does not have this problem. On Thu, 2011-05-26 12:10-0400, Tres Seaver wrote:
Log message for revision 121819: Correct comparison of interfaces from different modules but with the same name.
Fixes LP #570942.
Changed: U zope.interface/trunk/CHANGES.txt U zope.interface/trunk/src/zope/interface/interface.py U zope.interface/trunk/src/zope/interface/tests/test_interface.py U zope.interface/trunk/src/zope/interface/tests/test_sorting.py
-=- Modified: zope.interface/trunk/CHANGES.txt =================================================================== --- zope.interface/trunk/CHANGES.txt 2011-05-26 11:27:21 UTC (rev 121818) +++ zope.interface/trunk/CHANGES.txt 2011-05-26 16:10:57 UTC (rev 121819) @@ -1,7 +1,12 @@ ``zope.interface Changelog`` ============================
+3.6.3 (unreleased) +------------------
+- LP #570942: Now correctly compare interfaces from different modules but + with the same names. + 3.6.2 (2011-05-17) ------------------
Modified: zope.interface/trunk/src/zope/interface/interface.py =================================================================== --- zope.interface/trunk/src/zope/interface/interface.py 2011-05-26 11:27:21 UTC (rev 121818) +++ zope.interface/trunk/src/zope/interface/interface.py 2011-05-26 16:10:57 UTC (rev 121819) @@ -670,32 +670,42 @@ sort before None.
""" - if o1 == o2: - return 0 - if o1 is None: return 1 if o2 is None: return -1
- n1 = (getattr(o1, '__name__', ''), - getattr(getattr(o1, '__module__', None), '__name__', '')) - n2 = (getattr(o2, '__name__', ''), - getattr(getattr(o2, '__module__', None), '__name__', '')) + n1 = (getattr(o1, '__name__', ''), getattr(o1, '__module__', '')) + n2 = (getattr(o2, '__name__', ''), getattr(o2, '__module__', ''))
+ # This spelling works under Python3, which doesn't have cmp(). return (n1 > n2) - (n1 < n2)
+ def __eq__(self, other): + c = self.__cmp(self, other) + return c == 0 + + def __ne__(self, other): + c = self.__cmp(self, other) + return c != 0 + def __lt__(self, other): c = self.__cmp(self, other) - #print '<', self, other, c < 0, c return c < 0
+ def __le__(self, other): + c = self.__cmp(self, other) + return c <= 0 + def __gt__(self, other): c = self.__cmp(self, other) - #print '>', self, other, c > 0, c return c > 0
+ def __ge__(self, other): + c = self.__cmp(self, other) + return c >= 0
+ Interface = InterfaceClass("Interface", __module__ = 'zope.interface')
class Attribute(Element):
Modified: zope.interface/trunk/src/zope/interface/tests/test_interface.py =================================================================== --- zope.interface/trunk/src/zope/interface/tests/test_interface.py 2011-05-26 11:27:21 UTC (rev 121818) +++ zope.interface/trunk/src/zope/interface/tests/test_interface.py 2011-05-26 16:10:57 UTC (rev 121819) @@ -348,8 +348,40 @@ # Old style classes don't have a '__class__' attribute self.failUnlessRaises(AttributeError, I.providedBy, Bad)
+ def test_comparison_with_None(self): + from zope.interface import Interface
+ class IEmpty(Interface): + pass
+ self.failUnless(IEmpty < None) + self.failUnless(IEmpty <= None) + self.failIf(IEmpty == None) + self.failUnless(IEmpty != None) + self.failIf(IEmpty >= None) + self.failIf(IEmpty > None) + + self.failIf(None < IEmpty) + self.failIf(None <= IEmpty) + self.failIf(None == IEmpty) + self.failUnless(None != IEmpty) + self.failUnless(None >= IEmpty) + self.failUnless(None > IEmpty) + + def test_comparison_with_same_instance(self): + from zope.interface import Interface + + class IEmpty(Interface): + pass + + self.failIf(IEmpty < IEmpty) + self.failUnless(IEmpty <= IEmpty) + self.failUnless(IEmpty == IEmpty) + self.failIf(IEmpty != IEmpty) + self.failUnless(IEmpty >= IEmpty) + self.failIf(IEmpty > IEmpty) + + if sys.version_info >= (2, 4):
def test_invariant_as_decorator():
Modified: zope.interface/trunk/src/zope/interface/tests/test_sorting.py =================================================================== --- zope.interface/trunk/src/zope/interface/tests/test_sorting.py 2011-05-26 11:27:21 UTC (rev 121818) +++ zope.interface/trunk/src/zope/interface/tests/test_sorting.py 2011-05-26 16:10:57 UTC (rev 121819) @@ -37,6 +37,14 @@ l = [I1, None, I3, I5, I6, I4, I2] l.sort() self.assertEqual(l, [I1, I2, I3, I4, I5, I6, None]) + + def test_w_equal_names(self): + # interfaces with equal names but different modules should sort by + # module name + from zope.interface.tests.m1 import I1 as m1_I1 + l = [I1, m1_I1] + l.sort() + self.assertEqual(l, [m1_I1, I1])
def test_suite(): return TestSuite((
participants (1)
-
Gediminas Paulauskas