]> granicus.if.org Git - python/commitdiff
__hash__ may now return long int; the final hash
authorMartin v. Löwis <martin@v.loewis.de>
Wed, 9 Aug 2006 07:57:39 +0000 (07:57 +0000)
committerMartin v. Löwis <martin@v.loewis.de>
Wed, 9 Aug 2006 07:57:39 +0000 (07:57 +0000)
  value is obtained by invoking hash on the long int.
Fixes #1536021.

Doc/ref/ref3.tex
Lib/test/test_builtin.py
Misc/NEWS
Objects/classobject.c
Objects/typeobject.c

index 8ec9e2b18eda4ba223652a5909fec8f7108eebfd..15fc18820eebd4ec9efcad7717f26bb8f1a51c79 100644 (file)
@@ -1307,6 +1307,11 @@ defines mutable objects and implements a \method{__cmp__()} or
 since the dictionary implementation requires that a key's hash value
 is immutable (if the object's hash value changes, it will be in the
 wrong hash bucket).
+
+\versionchanged[\method{__hash__()} may now also return a long
+integer object; the 32-bit integer is then derived from the hash
+of that object]{2.5}
+
 \withsubitem{(object method)}{\ttindex{__cmp__()}}
 \end{methoddesc}
 
index 70480bef013bffd4632bc9944dbec5d6a1999bb9..26bfe877a1e369d52d3a7624b8d47422e44c307e 100644 (file)
@@ -640,6 +640,15 @@ class BuiltinTest(unittest.TestCase):
         def f(): pass
         self.assertRaises(TypeError, hash, [])
         self.assertRaises(TypeError, hash, {})
+        # Bug 1536021: Allow hash to return long objects
+        class X:
+            def __hash__(self):
+                return 2**100
+        self.assertEquals(type(hash(X())), int)
+        class Y(object):
+            def __hash__(self):
+                return 2**100
+        self.assertEquals(type(hash(Y())), int)
 
     def test_hex(self):
         self.assertEqual(hex(16), '0x10')
index 24b16453d177cae2441fc0d48c1ebd12d7f4a845..d7f17a45f5c8c9e4ab784776e69f2b0c913f56b0 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -12,6 +12,9 @@ What's New in Python 2.5 release candidate 1?
 Core and builtins
 -----------------
 
+- Bug #1536021: __hash__ may now return long int; the final hash
+  value is obtained by invoking hash on the long int.
+
 - Bug #1536786: buffer comparison could emit a RuntimeWarning.
 
 - Bug #1535165: fixed a segfault in input() and raw_input() when
index c69ba744e62f62d736cc5a62ee5b64589daaa59e..56bf29c5b5ab44c423378ce00f81bcdfc041236c 100644 (file)
@@ -934,11 +934,9 @@ instance_hash(PyInstanceObject *inst)
        Py_DECREF(func);
        if (res == NULL)
                return -1;
-       if (PyInt_Check(res)) {
-               outcome = PyInt_AsLong(res);
-               if (outcome == -1)
-                       outcome = -2;
-       }
+       if (PyInt_Check(res) || PyLong_Check(res))
+               /* This already converts a -1 result to -2. */
+               outcome = res->ob_type->tp_hash(res);
        else {
                PyErr_SetString(PyExc_TypeError,
                                "__hash__() should return an int");
index 67e6104fd3d1d3328e1a8fae6b2a7258b9fa08e2..652009b0d60d2ff8711b30c3bb08efadeb5de131 100644 (file)
@@ -4559,7 +4559,10 @@ slot_tp_hash(PyObject *self)
                Py_DECREF(func);
                if (res == NULL)
                        return -1;
-               h = PyInt_AsLong(res);
+               if (PyLong_Check(res))
+                       h = res->ob_type->tp_hash(res);
+               else
+                       h = PyInt_AsLong(res);
                Py_DECREF(res);
        }
        else {