[pypy-svn] r58722 - in pypy/branch/2.5-merge/pypy/objspace: . test

arigo at codespeak.net arigo at codespeak.net
Tue Oct 7 13:27:06 CEST 2008


Author: arigo
Date: Tue Oct  7 13:27:05 2008
New Revision: 58722

Modified:
   pypy/branch/2.5-merge/pypy/objspace/descroperation.py
   pypy/branch/2.5-merge/pypy/objspace/test/test_descriptor.py
Log:
Test and fix: __hash__ could return subclasses of 'int' or 'long',
but that should be handled just like regular ints or longs.


Modified: pypy/branch/2.5-merge/pypy/objspace/descroperation.py
==============================================================================
--- pypy/branch/2.5-merge/pypy/objspace/descroperation.py	(original)
+++ pypy/branch/2.5-merge/pypy/objspace/descroperation.py	Tue Oct  7 13:27:05 2008
@@ -293,10 +293,18 @@
         # XXX CPython has a special case for types with "__hash__ = None"
         # to produce a nicer error message, namely "unhashable type: 'X'".
         w_result = space.get_and_call_function(w_hash, w_obj)
-        if space.is_true(space.isinstance(w_result, space.w_int)):
+        w_resulttype = space.type(w_result)
+        if space.is_w(w_resulttype, space.w_int):
             return w_result
-        elif space.is_true(space.isinstance(w_result, space.w_long)): 
+        elif space.is_w(w_resulttype, space.w_long):
             return space.hash(w_result)
+        elif space.is_true(space.isinstance(w_result, space.w_int)):
+            # be careful about subclasses of 'int'...
+            return space.wrap(space.int_w(w_result))
+        elif space.is_true(space.isinstance(w_result, space.w_long)):
+            # be careful about subclasses of 'long'...
+            bigint = space.bigint_w(w_result)
+            return space.wrap(bigint.hash())
         else: 
             raise OperationError(space.w_TypeError, 
                     space.wrap("__hash__() should return an int or long"))

Modified: pypy/branch/2.5-merge/pypy/objspace/test/test_descriptor.py
==============================================================================
--- pypy/branch/2.5-merge/pypy/objspace/test/test_descriptor.py	(original)
+++ pypy/branch/2.5-merge/pypy/objspace/test/test_descriptor.py	Tue Oct  7 13:27:05 2008
@@ -81,3 +81,22 @@
             def __hash__(self):
                 return 1
         assert isinstance(hash(G()), int)
+
+        # __hash__ can return a subclass of long, but the fact that it's
+        # a subclass is ignored
+        class mylong(long):
+            def __hash__(self):
+                return 0
+        class H(object):
+            def __hash__(self):
+                return mylong(42)
+        assert hash(H()) == hash(42L)
+
+        # don't return a subclass of int, either
+        class myint(int):
+            pass
+        class I(object):
+            def __hash__(self):
+                return myint(15)
+        assert hash(I()) == 15
+        assert type(hash(I())) is int



More information about the Pypy-commit mailing list