[Python-checkins] cpython (3.3): Issue #15814: Use hash function that is compatible with the equality

stefan.krah python-checkins at python.org
Fri Nov 2 18:07:03 CET 2012


http://hg.python.org/cpython/rev/969069d464bc
changeset:   80182:969069d464bc
branch:      3.3
parent:      80180:0b5f00ccf907
user:        Stefan Krah <skrah at bytereef.org>
date:        Fri Nov 02 17:49:22 2012 +0100
summary:
  Issue #15814: Use hash function that is compatible with the equality
definition from #15573.

files:
  Doc/library/stdtypes.rst |   6 -----
  Lib/test/test_buffer.py  |  32 ++++++++++++++++++++++++++-
  Objects/memoryobject.c   |   8 +++++++
  3 files changed, 38 insertions(+), 8 deletions(-)


diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst
--- a/Doc/library/stdtypes.rst
+++ b/Doc/library/stdtypes.rst
@@ -2393,12 +2393,6 @@
    .. versionchanged:: 3.3
       One-dimensional memoryviews with formats 'B', 'b' or 'c' are now hashable.
 
-   .. note::
-      Hashing of memoryviews with formats other than 'B', 'b' or 'c' as well
-      as hashing of multi-dimensional memoryviews is possible in version 3.3.0,
-      but will raise an error in 3.3.1 in order to be compatible with the new
-      memoryview equality definition.
-
    :class:`memoryview` has several methods:
 
    .. method:: __eq__(exporter)
diff --git a/Lib/test/test_buffer.py b/Lib/test/test_buffer.py
--- a/Lib/test/test_buffer.py
+++ b/Lib/test/test_buffer.py
@@ -3999,14 +3999,42 @@
         m = memoryview(x)
         self.assertEqual(hash(m), hash(x))
 
+        # equality-hash invariant
+        x = ndarray(list(range(12)), shape=[12], format='B')
+        a = memoryview(nd)
+
+        y = ndarray(list(range(12)), shape=[12], format='b')
+        b = memoryview(nd)
+
+        z = ndarray(list(bytes(chr(x), 'latin-1') for x in range(12)),
+                    shape=[12], format='c')
+        c = memoryview(nd)
+
+        if (a == b):
+            self.assertEqual(hash(a), hash(b))
+
+        if (a == c):
+            self.assertEqual(hash(a), hash(c))
+
+        if (b == c):
+            self.assertEqual(hash(b), hash(c))
+
         # non-byte formats
         nd = ndarray(list(range(12)), shape=[2,2,3], format='L')
         m = memoryview(nd)
-        self.assertEqual(hash(m), hash(nd.tobytes()))
+        self.assertRaises(ValueError, m.__hash__)
 
         nd = ndarray(list(range(-6, 6)), shape=[2,2,3], format='h')
         m = memoryview(nd)
-        self.assertEqual(hash(m), hash(nd.tobytes()))
+        self.assertRaises(ValueError, m.__hash__)
+
+        nd = ndarray(list(range(12)), shape=[2,2,3], format='= L')
+        m = memoryview(nd)
+        self.assertRaises(ValueError, m.__hash__)
+
+        nd = ndarray(list(range(-6, 6)), shape=[2,2,3], format='< h')
+        m = memoryview(nd)
+        self.assertRaises(ValueError, m.__hash__)
 
     def test_memoryview_release(self):
 
diff --git a/Objects/memoryobject.c b/Objects/memoryobject.c
--- a/Objects/memoryobject.c
+++ b/Objects/memoryobject.c
@@ -2707,6 +2707,8 @@
     if (self->hash == -1) {
         Py_buffer *view = &self->view;
         char *mem = view->buf;
+        Py_ssize_t ret;
+        char fmt;
 
         CHECK_RELEASED_INT(self);
 
@@ -2715,6 +2717,12 @@
                 "cannot hash writable memoryview object");
             return -1;
         }
+        ret = get_native_fmtchar(&fmt, view->format);
+        if (ret < 0 || !IS_BYTE_FORMAT(fmt)) {
+            PyErr_SetString(PyExc_ValueError,
+                "memoryview: hashing is restricted to formats 'B', 'b' or 'c'");
+            return -1;
+        }
         if (view->obj != NULL && PyObject_Hash(view->obj) == -1) {
             /* Keep the original error message */
             return -1;

-- 
Repository URL: http://hg.python.org/cpython


More information about the Python-checkins mailing list