mirror of https://github.com/python/cpython
Issue #15814: Use hash function that is compatible with the equality
definition from #15573.
This commit is contained in:
parent
e6996ed5d9
commit
4af77a0276
|
@ -2393,12 +2393,6 @@ copying.
|
||||||
.. versionchanged:: 3.3
|
.. versionchanged:: 3.3
|
||||||
One-dimensional memoryviews with formats 'B', 'b' or 'c' are now hashable.
|
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:
|
:class:`memoryview` has several methods:
|
||||||
|
|
||||||
.. method:: __eq__(exporter)
|
.. method:: __eq__(exporter)
|
||||||
|
|
|
@ -3999,14 +3999,42 @@ class TestBufferProtocol(unittest.TestCase):
|
||||||
m = memoryview(x)
|
m = memoryview(x)
|
||||||
self.assertEqual(hash(m), hash(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
|
# non-byte formats
|
||||||
nd = ndarray(list(range(12)), shape=[2,2,3], format='L')
|
nd = ndarray(list(range(12)), shape=[2,2,3], format='L')
|
||||||
m = memoryview(nd)
|
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')
|
nd = ndarray(list(range(-6, 6)), shape=[2,2,3], format='h')
|
||||||
m = memoryview(nd)
|
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):
|
def test_memoryview_release(self):
|
||||||
|
|
||||||
|
|
|
@ -2707,6 +2707,8 @@ memory_hash(PyMemoryViewObject *self)
|
||||||
if (self->hash == -1) {
|
if (self->hash == -1) {
|
||||||
Py_buffer *view = &self->view;
|
Py_buffer *view = &self->view;
|
||||||
char *mem = view->buf;
|
char *mem = view->buf;
|
||||||
|
Py_ssize_t ret;
|
||||||
|
char fmt;
|
||||||
|
|
||||||
CHECK_RELEASED_INT(self);
|
CHECK_RELEASED_INT(self);
|
||||||
|
|
||||||
|
@ -2715,6 +2717,12 @@ memory_hash(PyMemoryViewObject *self)
|
||||||
"cannot hash writable memoryview object");
|
"cannot hash writable memoryview object");
|
||||||
return -1;
|
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) {
|
if (view->obj != NULL && PyObject_Hash(view->obj) == -1) {
|
||||||
/* Keep the original error message */
|
/* Keep the original error message */
|
||||||
return -1;
|
return -1;
|
||||||
|
|
Loading…
Reference in New Issue