diff -r bb6cababa5bd -r 63cf8ba004b8 Lib/test/test_dict_jy.py --- a/Lib/test/test_dict_jy.py Sun May 17 09:10:22 2015 +0100 +++ b/Lib/test/test_dict_jy.py Fri Jun 19 11:57:29 2015 -0700 @@ -257,6 +257,128 @@ return newdict +class Issue2367DictTest(unittest.TestCase): + + class HashDict(dict): + """Dict with __hash__ and __eq__ that checks both type and dict values.""" + def __hash__(self): + return hash(frozenset(self.items())) + + def __eq__(self, other): + if type(self) is type(other): + return dict.__eq__(self, other) + return False + + def __ne__(self, other): + return not(self == other) + + class Dict1(HashDict): + pass + + class Dict2(HashDict): + pass + + a = Dict1() + b = Dict2() + + def test_equal_hashes(self): + """Ensure that we are in fact dealing with a hash collision. + + """ + self.assertEqual(hash(self.a), hash(self.b)) + + def test_unequal_objects(self): + """Test that the objects do in fact compare unequal, and should be + simultaneously usable as keys. + + """ + # Ensures no funny business is going on with __ne__ and __eq__ + self.assertTrue(self.a != self.b) + self.assertTrue(self.b != self.a) + self.assertFalse(self.a == self.b) + self.assertFalse(self.b == self.a) + self.assertFalse(self.a.__eq__(self.b)) + self.assertFalse(self.b.__eq__(self.a)) + + def test_distinct_as_keys(self): + """Test that both elements may be used as different keys in a dict. + + """ + # Python should first compare by hash. As the hashes are the same, it + # should proceed to compare for equality. As Dict1 and Dict2 have + # different types, their __eq__ methods will return false, thus we + # should have a hash collision, and both elements should be in the + # dict. + # + # In CPython and PyPy, this is what happens. Jython seems to ignore + # the custom __eq__. + d = {} + d[self.a] = 1 + d[self.b] = 2 + self.assertEqual(len(d), 2) + + def test_both_in_set(self): + """That both objects may be placed in a set. + + """ + s = {self.a, self.b} + self.assertIn(self.a, s) + self.assertIn(self.b, s) + + def test_distinct_in_set(self): + """Test that both elements are viewd as distinct in a set. + + """ + s = {self.a, self.b} + self.assertEqual(len(s), 2) + + def test_hash_collisions_on_same_type(self): + """Test that hash collisions on same type are resolved normally. + + """ + d1 = self.Dict1({2**128: 1}) + d2 = self.Dict1({hash(2**128): 1}) + self.assertEqual(hash(d1), hash(d2)) + d = {} + d[d1] = 1 + d[d2] = 2 + self.assertEqual(2, len(d)) + +class DictDerivedTest(unittest.TestCase): + + class HashDict(dict): + def __hash__(self): + return hash(frozenset(self.items())) + # no __eq__ defined + + class Dict1(HashDict): + pass + + class Dict2(HashDict): + pass + + a = Dict1() + b = Dict2() + + def test_noeq_equal_hashes(self): + self.assertTrue(self.a == self.b) + self.assertTrue(self.b == self.a) + self.assertFalse(self.a != self.b) + self.assertFalse(self.b != self.a) + + def test_noeq_collides_in_set(self): + s = {self.a, self.b} + self.assertEqual(1, len(s)) + + def test_unhashable_dict(self): + class UnhashableDict(dict): + pass + + x = UnhashableDict() + with self.assertRaises(TypeError): + s = {x,} + + def test_main(): test_support.run_unittest( DictInitTest, @@ -265,7 +387,9 @@ DerivedDictTest, JavaIntegrationTest, JavaDictTest, - PyStringMapTest) + PyStringMapTest, + Issue2367DictTest, + DictDerivedTest) if __name__ == '__main__': test_main() diff -r bb6cababa5bd -r 63cf8ba004b8 src/org/python/core/PyDictionary.java --- a/src/org/python/core/PyDictionary.java Sun May 17 09:10:22 2015 +0100 +++ b/src/org/python/core/PyDictionary.java Fri Jun 19 11:57:29 2015 -0700 @@ -257,7 +257,8 @@ PyType thisType = getType(); PyType otherType = otherObj.getType(); if (otherType != thisType && !thisType.isSubType(otherType) - && !otherType.isSubType(thisType) || otherType == PyObject.TYPE) { + && !otherType.isSubType(thisType) && !otherType.isSubType(PyDictionary.TYPE) + || otherType == PyObject.TYPE) { return null; } PyDictionary other = (PyDictionary)otherObj; diff -r bb6cababa5bd -r 63cf8ba004b8 src/org/python/core/PyDictionaryDerived.java --- a/src/org/python/core/PyDictionaryDerived.java Sun May 17 09:10:22 2015 +0100 +++ b/src/org/python/core/PyDictionaryDerived.java Fri Jun 19 11:57:29 2015 -0700 @@ -21,7 +21,7 @@ public void __del_derived__() { PyType self_type=getType(); PyObject impl=self_type.lookup("__del__"); - if (impl!=null) { + if (impl != null && impl != Py.None) { impl.__get__(this,self_type).__call__(); } } @@ -98,7 +98,7 @@ public PyString __str__() { PyType self_type=getType(); PyObject impl=self_type.lookup("__str__"); - if (impl!=null) { + if (impl != null && impl != Py.None) { PyObject res=impl.__get__(this,self_type).__call__(); if (res instanceof PyString) return(PyString)res; @@ -110,7 +110,7 @@ public PyString __repr__() { PyType self_type=getType(); PyObject impl=self_type.lookup("__repr__"); - if (impl!=null) { + if (impl != null && impl != Py.None) { PyObject res=impl.__get__(this,self_type).__call__(); if (res instanceof PyString) return(PyString)res; @@ -122,7 +122,7 @@ public PyString __hex__() { PyType self_type=getType(); PyObject impl=self_type.lookup("__hex__"); - if (impl!=null) { + if (impl != null && impl != Py.None) { PyObject res=impl.__get__(this,self_type).__call__(); if (res instanceof PyString) return(PyString)res; @@ -134,7 +134,7 @@ public PyString __oct__() { PyType self_type=getType(); PyObject impl=self_type.lookup("__oct__"); - if (impl!=null) { + if (impl != null && impl != Py.None) { PyObject res=impl.__get__(this,self_type).__call__(); if (res instanceof PyString) return(PyString)res; @@ -146,7 +146,7 @@ public PyFloat __float__() { PyType self_type=getType(); PyObject impl=self_type.lookup("__float__"); - if (impl!=null) { + if (impl != null && impl != Py.None) { PyObject res=impl.__get__(this,self_type).__call__(); if (res instanceof PyFloat) return(PyFloat)res; @@ -158,7 +158,7 @@ public PyComplex __complex__() { PyType self_type=getType(); PyObject impl=self_type.lookup("__complex__"); - if (impl!=null) { + if (impl != null && impl != Py.None) { PyObject res=impl.__get__(this,self_type).__call__(); if (res instanceof PyComplex) return(PyComplex)res; @@ -170,7 +170,7 @@ public PyObject __pos__() { PyType self_type=getType(); PyObject impl=self_type.lookup("__pos__"); - if (impl!=null) + if (impl != null && impl != Py.None) return impl.__get__(this,self_type).__call__(); return super.__pos__(); } @@ -178,7 +178,7 @@ public PyObject __neg__() { PyType self_type=getType(); PyObject impl=self_type.lookup("__neg__"); - if (impl!=null) + if (impl != null && impl != Py.None) return impl.__get__(this,self_type).__call__(); return super.__neg__(); } @@ -186,7 +186,7 @@ public PyObject __abs__() { PyType self_type=getType(); PyObject impl=self_type.lookup("__abs__"); - if (impl!=null) + if (impl != null && impl != Py.None) return impl.__get__(this,self_type).__call__(); return super.__abs__(); } @@ -194,7 +194,7 @@ public PyObject __invert__() { PyType self_type=getType(); PyObject impl=self_type.lookup("__invert__"); - if (impl!=null) + if (impl != null && impl != Py.None) return impl.__get__(this,self_type).__call__(); return super.__invert__(); } @@ -202,7 +202,7 @@ public PyObject __reduce__() { PyType self_type=getType(); PyObject impl=self_type.lookup("__reduce__"); - if (impl!=null) + if (impl != null && impl != Py.None) return impl.__get__(this,self_type).__call__(); return super.__reduce__(); } @@ -210,7 +210,7 @@ public PyObject __dir__() { PyType self_type=getType(); PyObject impl=self_type.lookup("__dir__"); - if (impl!=null) + if (impl != null && impl != Py.None) return impl.__get__(this,self_type).__call__(); return super.__dir__(); } @@ -218,7 +218,7 @@ public PyObject __add__(PyObject other) { PyType self_type=getType(); PyObject impl=self_type.lookup("__add__"); - if (impl!=null) { + if (impl != null && impl != Py.None) { PyObject res=impl.__get__(this,self_type).__call__(other); if (res==Py.NotImplemented) return null; @@ -230,7 +230,7 @@ public PyObject __radd__(PyObject other) { PyType self_type=getType(); PyObject impl=self_type.lookup("__radd__"); - if (impl!=null) { + if (impl != null && impl != Py.None) { PyObject res=impl.__get__(this,self_type).__call__(other); if (res==Py.NotImplemented) return null; @@ -242,7 +242,7 @@ public PyObject __sub__(PyObject other) { PyType self_type=getType(); PyObject impl=self_type.lookup("__sub__"); - if (impl!=null) { + if (impl != null && impl != Py.None) { PyObject res=impl.__get__(this,self_type).__call__(other); if (res==Py.NotImplemented) return null; @@ -254,7 +254,7 @@ public PyObject __rsub__(PyObject other) { PyType self_type=getType(); PyObject impl=self_type.lookup("__rsub__"); - if (impl!=null) { + if (impl != null && impl != Py.None) { PyObject res=impl.__get__(this,self_type).__call__(other); if (res==Py.NotImplemented) return null; @@ -266,7 +266,7 @@ public PyObject __mul__(PyObject other) { PyType self_type=getType(); PyObject impl=self_type.lookup("__mul__"); - if (impl!=null) { + if (impl != null && impl != Py.None) { PyObject res=impl.__get__(this,self_type).__call__(other); if (res==Py.NotImplemented) return null; @@ -278,7 +278,7 @@ public PyObject __rmul__(PyObject other) { PyType self_type=getType(); PyObject impl=self_type.lookup("__rmul__"); - if (impl!=null) { + if (impl != null && impl != Py.None) { PyObject res=impl.__get__(this,self_type).__call__(other); if (res==Py.NotImplemented) return null; @@ -290,7 +290,7 @@ public PyObject __div__(PyObject other) { PyType self_type=getType(); PyObject impl=self_type.lookup("__div__"); - if (impl!=null) { + if (impl != null && impl != Py.None) { PyObject res=impl.__get__(this,self_type).__call__(other); if (res==Py.NotImplemented) return null; @@ -302,7 +302,7 @@ public PyObject __rdiv__(PyObject other) { PyType self_type=getType(); PyObject impl=self_type.lookup("__rdiv__"); - if (impl!=null) { + if (impl != null && impl != Py.None) { PyObject res=impl.__get__(this,self_type).__call__(other); if (res==Py.NotImplemented) return null; @@ -314,7 +314,7 @@ public PyObject __floordiv__(PyObject other) { PyType self_type=getType(); PyObject impl=self_type.lookup("__floordiv__"); - if (impl!=null) { + if (impl != null && impl != Py.None) { PyObject res=impl.__get__(this,self_type).__call__(other); if (res==Py.NotImplemented) return null; @@ -326,7 +326,7 @@ public PyObject __rfloordiv__(PyObject other) { PyType self_type=getType(); PyObject impl=self_type.lookup("__rfloordiv__"); - if (impl!=null) { + if (impl != null && impl != Py.None) { PyObject res=impl.__get__(this,self_type).__call__(other); if (res==Py.NotImplemented) return null; @@ -338,7 +338,7 @@ public PyObject __truediv__(PyObject other) { PyType self_type=getType(); PyObject impl=self_type.lookup("__truediv__"); - if (impl!=null) { + if (impl != null && impl != Py.None) { PyObject res=impl.__get__(this,self_type).__call__(other); if (res==Py.NotImplemented) return null; @@ -350,7 +350,7 @@ public PyObject __rtruediv__(PyObject other) { PyType self_type=getType(); PyObject impl=self_type.lookup("__rtruediv__"); - if (impl!=null) { + if (impl != null && impl != Py.None) { PyObject res=impl.__get__(this,self_type).__call__(other); if (res==Py.NotImplemented) return null; @@ -362,7 +362,7 @@ public PyObject __mod__(PyObject other) { PyType self_type=getType(); PyObject impl=self_type.lookup("__mod__"); - if (impl!=null) { + if (impl != null && impl != Py.None) { PyObject res=impl.__get__(this,self_type).__call__(other); if (res==Py.NotImplemented) return null; @@ -374,7 +374,7 @@ public PyObject __rmod__(PyObject other) { PyType self_type=getType(); PyObject impl=self_type.lookup("__rmod__"); - if (impl!=null) { + if (impl != null && impl != Py.None) { PyObject res=impl.__get__(this,self_type).__call__(other); if (res==Py.NotImplemented) return null; @@ -386,7 +386,7 @@ public PyObject __divmod__(PyObject other) { PyType self_type=getType(); PyObject impl=self_type.lookup("__divmod__"); - if (impl!=null) { + if (impl != null && impl != Py.None) { PyObject res=impl.__get__(this,self_type).__call__(other); if (res==Py.NotImplemented) return null; @@ -398,7 +398,7 @@ public PyObject __rdivmod__(PyObject other) { PyType self_type=getType(); PyObject impl=self_type.lookup("__rdivmod__"); - if (impl!=null) { + if (impl != null && impl != Py.None) { PyObject res=impl.__get__(this,self_type).__call__(other); if (res==Py.NotImplemented) return null; @@ -410,7 +410,7 @@ public PyObject __rpow__(PyObject other) { PyType self_type=getType(); PyObject impl=self_type.lookup("__rpow__"); - if (impl!=null) { + if (impl != null && impl != Py.None) { PyObject res=impl.__get__(this,self_type).__call__(other); if (res==Py.NotImplemented) return null; @@ -422,7 +422,7 @@ public PyObject __lshift__(PyObject other) { PyType self_type=getType(); PyObject impl=self_type.lookup("__lshift__"); - if (impl!=null) { + if (impl != null && impl != Py.None) { PyObject res=impl.__get__(this,self_type).__call__(other); if (res==Py.NotImplemented) return null; @@ -434,7 +434,7 @@ public PyObject __rlshift__(PyObject other) { PyType self_type=getType(); PyObject impl=self_type.lookup("__rlshift__"); - if (impl!=null) { + if (impl != null && impl != Py.None) { PyObject res=impl.__get__(this,self_type).__call__(other); if (res==Py.NotImplemented) return null; @@ -446,7 +446,7 @@ public PyObject __rshift__(PyObject other) { PyType self_type=getType(); PyObject impl=self_type.lookup("__rshift__"); - if (impl!=null) { + if (impl != null && impl != Py.None) { PyObject res=impl.__get__(this,self_type).__call__(other); if (res==Py.NotImplemented) return null; @@ -458,7 +458,7 @@ public PyObject __rrshift__(PyObject other) { PyType self_type=getType(); PyObject impl=self_type.lookup("__rrshift__"); - if (impl!=null) { + if (impl != null && impl != Py.None) { PyObject res=impl.__get__(this,self_type).__call__(other); if (res==Py.NotImplemented) return null; @@ -470,7 +470,7 @@ public PyObject __and__(PyObject other) { PyType self_type=getType(); PyObject impl=self_type.lookup("__and__"); - if (impl!=null) { + if (impl != null && impl != Py.None) { PyObject res=impl.__get__(this,self_type).__call__(other); if (res==Py.NotImplemented) return null; @@ -482,7 +482,7 @@ public PyObject __rand__(PyObject other) { PyType self_type=getType(); PyObject impl=self_type.lookup("__rand__"); - if (impl!=null) { + if (impl != null && impl != Py.None) { PyObject res=impl.__get__(this,self_type).__call__(other); if (res==Py.NotImplemented) return null; @@ -494,7 +494,7 @@ public PyObject __or__(PyObject other) { PyType self_type=getType(); PyObject impl=self_type.lookup("__or__"); - if (impl!=null) { + if (impl != null && impl != Py.None) { PyObject res=impl.__get__(this,self_type).__call__(other); if (res==Py.NotImplemented) return null; @@ -506,7 +506,7 @@ public PyObject __ror__(PyObject other) { PyType self_type=getType(); PyObject impl=self_type.lookup("__ror__"); - if (impl!=null) { + if (impl != null && impl != Py.None) { PyObject res=impl.__get__(this,self_type).__call__(other); if (res==Py.NotImplemented) return null; @@ -518,7 +518,7 @@ public PyObject __xor__(PyObject other) { PyType self_type=getType(); PyObject impl=self_type.lookup("__xor__"); - if (impl!=null) { + if (impl != null && impl != Py.None) { PyObject res=impl.__get__(this,self_type).__call__(other); if (res==Py.NotImplemented) return null; @@ -530,7 +530,7 @@ public PyObject __rxor__(PyObject other) { PyType self_type=getType(); PyObject impl=self_type.lookup("__rxor__"); - if (impl!=null) { + if (impl != null && impl != Py.None) { PyObject res=impl.__get__(this,self_type).__call__(other); if (res==Py.NotImplemented) return null; @@ -542,7 +542,7 @@ public PyObject __lt__(PyObject other) { PyType self_type=getType(); PyObject impl=self_type.lookup("__lt__"); - if (impl!=null) { + if (impl != null && impl != Py.None) { PyObject res=impl.__get__(this,self_type).__call__(other); if (res==Py.NotImplemented) return null; @@ -554,7 +554,7 @@ public PyObject __le__(PyObject other) { PyType self_type=getType(); PyObject impl=self_type.lookup("__le__"); - if (impl!=null) { + if (impl != null && impl != Py.None) { PyObject res=impl.__get__(this,self_type).__call__(other); if (res==Py.NotImplemented) return null; @@ -566,7 +566,7 @@ public PyObject __gt__(PyObject other) { PyType self_type=getType(); PyObject impl=self_type.lookup("__gt__"); - if (impl!=null) { + if (impl != null && impl != Py.None) { PyObject res=impl.__get__(this,self_type).__call__(other); if (res==Py.NotImplemented) return null; @@ -578,7 +578,7 @@ public PyObject __ge__(PyObject other) { PyType self_type=getType(); PyObject impl=self_type.lookup("__ge__"); - if (impl!=null) { + if (impl != null && impl != Py.None) { PyObject res=impl.__get__(this,self_type).__call__(other); if (res==Py.NotImplemented) return null; @@ -590,7 +590,7 @@ public PyObject __eq__(PyObject other) { PyType self_type=getType(); PyObject impl=self_type.lookup("__eq__"); - if (impl!=null) { + if (impl != null && impl != Py.None) { PyObject res=impl.__get__(this,self_type).__call__(other); if (res==Py.NotImplemented) return null; @@ -602,7 +602,7 @@ public PyObject __ne__(PyObject other) { PyType self_type=getType(); PyObject impl=self_type.lookup("__ne__"); - if (impl!=null) { + if (impl != null && impl != Py.None) { PyObject res=impl.__get__(this,self_type).__call__(other); if (res==Py.NotImplemented) return null; @@ -614,7 +614,7 @@ public PyObject __format__(PyObject other) { PyType self_type=getType(); PyObject impl=self_type.lookup("__format__"); - if (impl!=null) { + if (impl != null && impl != Py.None) { PyObject res=impl.__get__(this,self_type).__call__(other); if (res==Py.NotImplemented) return null; @@ -626,7 +626,7 @@ public PyObject __iadd__(PyObject other) { PyType self_type=getType(); PyObject impl=self_type.lookup("__iadd__"); - if (impl!=null) { + if (impl != null && impl != Py.None) { PyObject res=impl.__get__(this,self_type).__call__(other); if (res==Py.NotImplemented) return null; @@ -638,7 +638,7 @@ public PyObject __isub__(PyObject other) { PyType self_type=getType(); PyObject impl=self_type.lookup("__isub__"); - if (impl!=null) { + if (impl != null && impl != Py.None) { PyObject res=impl.__get__(this,self_type).__call__(other); if (res==Py.NotImplemented) return null; @@ -650,7 +650,7 @@ public PyObject __imul__(PyObject other) { PyType self_type=getType(); PyObject impl=self_type.lookup("__imul__"); - if (impl!=null) { + if (impl != null && impl != Py.None) { PyObject res=impl.__get__(this,self_type).__call__(other); if (res==Py.NotImplemented) return null; @@ -662,7 +662,7 @@ public PyObject __idiv__(PyObject other) { PyType self_type=getType(); PyObject impl=self_type.lookup("__idiv__"); - if (impl!=null) { + if (impl != null && impl != Py.None) { PyObject res=impl.__get__(this,self_type).__call__(other); if (res==Py.NotImplemented) return null; @@ -674,7 +674,7 @@ public PyObject __ifloordiv__(PyObject other) { PyType self_type=getType(); PyObject impl=self_type.lookup("__ifloordiv__"); - if (impl!=null) { + if (impl != null && impl != Py.None) { PyObject res=impl.__get__(this,self_type).__call__(other); if (res==Py.NotImplemented) return null; @@ -686,7 +686,7 @@ public PyObject __itruediv__(PyObject other) { PyType self_type=getType(); PyObject impl=self_type.lookup("__itruediv__"); - if (impl!=null) { + if (impl != null && impl != Py.None) { PyObject res=impl.__get__(this,self_type).__call__(other); if (res==Py.NotImplemented) return null; @@ -698,7 +698,7 @@ public PyObject __imod__(PyObject other) { PyType self_type=getType(); PyObject impl=self_type.lookup("__imod__"); - if (impl!=null) { + if (impl != null && impl != Py.None) { PyObject res=impl.__get__(this,self_type).__call__(other); if (res==Py.NotImplemented) return null; @@ -710,7 +710,7 @@ public PyObject __ipow__(PyObject other) { PyType self_type=getType(); PyObject impl=self_type.lookup("__ipow__"); - if (impl!=null) { + if (impl != null && impl != Py.None) { PyObject res=impl.__get__(this,self_type).__call__(other); if (res==Py.NotImplemented) return null; @@ -722,7 +722,7 @@ public PyObject __ilshift__(PyObject other) { PyType self_type=getType(); PyObject impl=self_type.lookup("__ilshift__"); - if (impl!=null) { + if (impl != null && impl != Py.None) { PyObject res=impl.__get__(this,self_type).__call__(other); if (res==Py.NotImplemented) return null; @@ -734,7 +734,7 @@ public PyObject __irshift__(PyObject other) { PyType self_type=getType(); PyObject impl=self_type.lookup("__irshift__"); - if (impl!=null) { + if (impl != null && impl != Py.None) { PyObject res=impl.__get__(this,self_type).__call__(other); if (res==Py.NotImplemented) return null; @@ -746,7 +746,7 @@ public PyObject __iand__(PyObject other) { PyType self_type=getType(); PyObject impl=self_type.lookup("__iand__"); - if (impl!=null) { + if (impl != null && impl != Py.None) { PyObject res=impl.__get__(this,self_type).__call__(other); if (res==Py.NotImplemented) return null; @@ -758,7 +758,7 @@ public PyObject __ior__(PyObject other) { PyType self_type=getType(); PyObject impl=self_type.lookup("__ior__"); - if (impl!=null) { + if (impl != null && impl != Py.None) { PyObject res=impl.__get__(this,self_type).__call__(other); if (res==Py.NotImplemented) return null; @@ -770,7 +770,7 @@ public PyObject __ixor__(PyObject other) { PyType self_type=getType(); PyObject impl=self_type.lookup("__ixor__"); - if (impl!=null) { + if (impl != null && impl != Py.None) { PyObject res=impl.__get__(this,self_type).__call__(other); if (res==Py.NotImplemented) return null; @@ -782,7 +782,7 @@ public PyObject __int__() { PyType self_type=getType(); PyObject impl=self_type.lookup("__int__"); - if (impl!=null) { + if (impl != null && impl != Py.None) { PyObject res=impl.__get__(this,self_type).__call__(); if (res instanceof PyInteger||res instanceof PyLong) return res; @@ -794,7 +794,7 @@ public PyObject __long__() { PyType self_type=getType(); PyObject impl=self_type.lookup("__long__"); - if (impl!=null) { + if (impl != null && impl != Py.None) { PyObject res=impl.__get__(this,self_type).__call__(); if (res instanceof PyLong||res instanceof PyInteger) return res; @@ -803,10 +803,11 @@ return super.__long__(); } + @Override public int hashCode() { PyType self_type=getType(); PyObject impl=self_type.lookup("__hash__"); - if (impl!=null) { + if (impl != null && impl != Py.None) { PyObject res=impl.__get__(this,self_type).__call__(); if (res instanceof PyInteger) { return((PyInteger)res).getValue(); @@ -822,10 +823,26 @@ return super.hashCode(); } + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj instanceof PyObject) { + PyObject res = __eq__((PyObject) obj); + if (res == null) { + // not sure what an appropriate message should be + throw Py.TypeError(String.format("unhashable type: '%.200s'",getType().fastGetName())); + } + return res.__nonzero__(); + } + return super.equals(obj); + } + public PyUnicode __unicode__() { PyType self_type=getType(); PyObject impl=self_type.lookup("__unicode__"); - if (impl!=null) { + if (impl != null && impl != Py.None) { PyObject res=impl.__get__(this,self_type).__call__(); if (res instanceof PyUnicode) return(PyUnicode)res; @@ -883,7 +900,7 @@ public int __len__() { PyType self_type=getType(); PyObject impl=self_type.lookup("__len__"); - if (impl!=null) { + if (impl != null && impl != Py.None) { PyObject res=impl.__get__(this,self_type).__call__(); return res.asInt(); } @@ -893,7 +910,7 @@ public PyObject __iter__() { PyType self_type=getType(); PyObject impl=self_type.lookup("__iter__"); - if (impl!=null) + if (impl != null && impl != Py.None) return impl.__get__(this,self_type).__call__(); impl=self_type.lookup("__getitem__"); if (impl==null) @@ -904,7 +921,7 @@ public PyObject __iternext__() { PyType self_type=getType(); PyObject impl=self_type.lookup("next"); - if (impl!=null) { + if (impl != null && impl != Py.None) { try { return impl.__get__(this,self_type).__call__(); } catch (PyException exc) { @@ -919,7 +936,7 @@ public PyObject __finditem__(PyObject key) { // ??? PyType self_type=getType(); PyObject impl=self_type.lookup("__getitem__"); - if (impl!=null) + if (impl != null && impl != Py.None) try { return impl.__get__(this,self_type).__call__(key); } catch (PyException exc) { @@ -933,7 +950,7 @@ public PyObject __finditem__(int key) { PyType self_type=getType(); PyObject impl=self_type.lookup("__getitem__"); - if (impl!=null) + if (impl != null && impl != Py.None) try { return impl.__get__(this,self_type).__call__(new PyInteger(key)); } catch (PyException exc) { @@ -965,7 +982,7 @@ PyType self_type=getType(); PyObject impl=self_type.lookup("__getitem__"); - if (impl!=null) + if (impl != null && impl != Py.None) return impl.__get__(this,self_type).__call__(key); return super.__getitem__(key); } @@ -973,7 +990,7 @@ public void __setitem__(PyObject key,PyObject value) { // ??? PyType self_type=getType(); PyObject impl=self_type.lookup("__setitem__"); - if (impl!=null) { + if (impl != null && impl != Py.None) { impl.__get__(this,self_type).__call__(key,value); return; } @@ -986,7 +1003,7 @@ } PyType self_type=getType(); PyObject impl=self_type.lookup("__getslice__"); - if (impl!=null) { + if (impl != null && impl != Py.None) { PyObject[]indices=PySlice.indices2(this,start,stop); return impl.__get__(this,self_type).__call__(indices[0],indices[1]); } @@ -1000,7 +1017,7 @@ } PyType self_type=getType(); PyObject impl=self_type.lookup("__setslice__"); - if (impl!=null) { + if (impl != null && impl != Py.None) { PyObject[]indices=PySlice.indices2(this,start,stop); impl.__get__(this,self_type).__call__(indices[0],indices[1],value); return; @@ -1015,7 +1032,7 @@ } PyType self_type=getType(); PyObject impl=self_type.lookup("__delslice__"); - if (impl!=null) { + if (impl != null && impl != Py.None) { PyObject[]indices=PySlice.indices2(this,start,stop); impl.__get__(this,self_type).__call__(indices[0],indices[1]); return; @@ -1026,7 +1043,7 @@ public void __delitem__(PyObject key) { // ??? PyType self_type=getType(); PyObject impl=self_type.lookup("__delitem__"); - if (impl!=null) { + if (impl != null && impl != Py.None) { impl.__get__(this,self_type).__call__(key); return; } @@ -1036,7 +1053,7 @@ public PyObject __call__(PyObject args[],String keywords[]) { PyType self_type=getType(); PyObject impl=self_type.lookup("__call__"); - if (impl!=null) { + if (impl != null && impl != Py.None) { return impl.__get__(this,self_type).__call__(args,keywords); } return super.__call__(args,keywords); @@ -1049,7 +1066,7 @@ public void __setattr__(String name,PyObject value) { PyType self_type=getType(); PyObject impl=self_type.lookup("__setattr__"); - if (impl!=null) { + if (impl != null && impl != Py.None) { impl.__get__(this,self_type).__call__(PyString.fromInterned(name),value); //CPython does not support instance-acquired finalizers. //So we don't check for __del__ here. @@ -1061,7 +1078,7 @@ public void __delattr__(String name) { PyType self_type=getType(); PyObject impl=self_type.lookup("__delattr__"); - if (impl!=null) { + if (impl != null && impl != Py.None) { impl.__get__(this,self_type).__call__(PyString.fromInterned(name)); return; } @@ -1071,7 +1088,7 @@ public PyObject __get__(PyObject obj,PyObject type) { PyType self_type=getType(); PyObject impl=self_type.lookup("__get__"); - if (impl!=null) { + if (impl != null && impl != Py.None) { if (obj==null) obj=Py.None; if (type==null) @@ -1084,7 +1101,7 @@ public void __set__(PyObject obj,PyObject value) { PyType self_type=getType(); PyObject impl=self_type.lookup("__set__"); - if (impl!=null) { + if (impl != null && impl != Py.None) { impl.__get__(this,self_type).__call__(obj,value); return; } @@ -1094,7 +1111,7 @@ public void __delete__(PyObject obj) { PyType self_type=getType(); PyObject impl=self_type.lookup("__delete__"); - if (impl!=null) { + if (impl != null && impl != Py.None) { impl.__get__(this,self_type).__call__(obj); return; } @@ -1104,7 +1121,7 @@ public PyObject __pow__(PyObject other,PyObject modulo) { PyType self_type=getType(); PyObject impl=self_type.lookup("__pow__"); - if (impl!=null) { + if (impl != null && impl != Py.None) { PyObject res; if (modulo==null) { res=impl.__get__(this,self_type).__call__(other); @@ -1125,7 +1142,7 @@ public PyObject __index__() { PyType self_type=getType(); PyObject impl=self_type.lookup("__index__"); - if (impl!=null) { + if (impl != null && impl != Py.None) { PyObject res=impl.__get__(this,self_type).__call__(); if (res instanceof PyInteger||res instanceof PyLong) { return res; @@ -1147,7 +1164,7 @@ // Otherwise, we call the derived __tojava__, if it exists: PyType self_type=getType(); PyObject impl=self_type.lookup("__tojava__"); - if (impl!=null) { + if (impl != null && impl != Py.None) { PyObject delegate=impl.__get__(this,self_type).__call__(Py.java2py(c)); if (delegate!=this) return delegate.__tojava__(Object.class); @@ -1158,7 +1175,7 @@ public Object __coerce_ex__(PyObject o) { PyType self_type=getType(); PyObject impl=self_type.lookup("__coerce__"); - if (impl!=null) { + if (impl != null && impl != Py.None) { PyObject res=impl.__get__(this,self_type).__call__(o); if (res==Py.NotImplemented) return Py.None; @@ -1172,7 +1189,7 @@ public String toString() { PyType self_type=getType(); PyObject impl=self_type.lookup("__repr__"); - if (impl!=null) { + if (impl != null && impl != Py.None) { PyObject res=impl.__get__(this,self_type).__call__(); if (!(res instanceof PyString)) throw Py.TypeError("__repr__ returned non-string (type "+res.getType().fastGetName()+")");