summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Doc/ref/ref3.tex5
-rw-r--r--Lib/test/test_builtin.py9
-rw-r--r--Misc/NEWS3
-rw-r--r--Objects/classobject.c8
-rw-r--r--Objects/typeobject.c5
5 files changed, 24 insertions, 6 deletions
diff --git a/Doc/ref/ref3.tex b/Doc/ref/ref3.tex
index 8ec9e2b..15fc188 100644
--- a/Doc/ref/ref3.tex
+++ b/Doc/ref/ref3.tex
@@ -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}
diff --git a/Lib/test/test_builtin.py b/Lib/test/test_builtin.py
index 70480be..26bfe87 100644
--- a/Lib/test/test_builtin.py
+++ b/Lib/test/test_builtin.py
@@ -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')
diff --git a/Misc/NEWS b/Misc/NEWS
index 24b1645..d7f17a4 100644
--- 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
diff --git a/Objects/classobject.c b/Objects/classobject.c
index c69ba74..56bf29c 100644
--- a/Objects/classobject.c
+++ b/Objects/classobject.c
@@ -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");
diff --git a/Objects/typeobject.c b/Objects/typeobject.c
index 67e6104..652009b 100644
--- a/Objects/typeobject.c
+++ b/Objects/typeobject.c
@@ -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 {