Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 4af77a0

Browse files
author
Stefan Krah
committed
Issue #15814: Use hash function that is compatible with the equality
definition from #15573.
1 parent e6996ed commit 4af77a0

3 files changed

Lines changed: 38 additions & 8 deletions

File tree

Doc/library/stdtypes.rst

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2393,12 +2393,6 @@ copying.
23932393
.. versionchanged:: 3.3
23942394
One-dimensional memoryviews with formats 'B', 'b' or 'c' are now hashable.
23952395

2396-
.. note::
2397-
Hashing of memoryviews with formats other than 'B', 'b' or 'c' as well
2398-
as hashing of multi-dimensional memoryviews is possible in version 3.3.0,
2399-
but will raise an error in 3.3.1 in order to be compatible with the new
2400-
memoryview equality definition.
2401-
24022396
:class:`memoryview` has several methods:
24032397

24042398
.. method:: __eq__(exporter)

Lib/test/test_buffer.py

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3999,14 +3999,42 @@ def test_memoryview_hash(self):
39993999
m = memoryview(x)
40004000
self.assertEqual(hash(m), hash(x))
40014001

4002+
# equality-hash invariant
4003+
x = ndarray(list(range(12)), shape=[12], format='B')
4004+
a = memoryview(nd)
4005+
4006+
y = ndarray(list(range(12)), shape=[12], format='b')
4007+
b = memoryview(nd)
4008+
4009+
z = ndarray(list(bytes(chr(x), 'latin-1') for x in range(12)),
4010+
shape=[12], format='c')
4011+
c = memoryview(nd)
4012+
4013+
if (a == b):
4014+
self.assertEqual(hash(a), hash(b))
4015+
4016+
if (a == c):
4017+
self.assertEqual(hash(a), hash(c))
4018+
4019+
if (b == c):
4020+
self.assertEqual(hash(b), hash(c))
4021+
40024022
# non-byte formats
40034023
nd = ndarray(list(range(12)), shape=[2,2,3], format='L')
40044024
m = memoryview(nd)
4005-
self.assertEqual(hash(m), hash(nd.tobytes()))
4025+
self.assertRaises(ValueError, m.__hash__)
40064026

40074027
nd = ndarray(list(range(-6, 6)), shape=[2,2,3], format='h')
40084028
m = memoryview(nd)
4009-
self.assertEqual(hash(m), hash(nd.tobytes()))
4029+
self.assertRaises(ValueError, m.__hash__)
4030+
4031+
nd = ndarray(list(range(12)), shape=[2,2,3], format='= L')
4032+
m = memoryview(nd)
4033+
self.assertRaises(ValueError, m.__hash__)
4034+
4035+
nd = ndarray(list(range(-6, 6)), shape=[2,2,3], format='< h')
4036+
m = memoryview(nd)
4037+
self.assertRaises(ValueError, m.__hash__)
40104038

40114039
def test_memoryview_release(self):
40124040

Objects/memoryobject.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2707,6 +2707,8 @@ memory_hash(PyMemoryViewObject *self)
27072707
if (self->hash == -1) {
27082708
Py_buffer *view = &self->view;
27092709
char *mem = view->buf;
2710+
Py_ssize_t ret;
2711+
char fmt;
27102712

27112713
CHECK_RELEASED_INT(self);
27122714

@@ -2715,6 +2717,12 @@ memory_hash(PyMemoryViewObject *self)
27152717
"cannot hash writable memoryview object");
27162718
return -1;
27172719
}
2720+
ret = get_native_fmtchar(&fmt, view->format);
2721+
if (ret < 0 || !IS_BYTE_FORMAT(fmt)) {
2722+
PyErr_SetString(PyExc_ValueError,
2723+
"memoryview: hashing is restricted to formats 'B', 'b' or 'c'");
2724+
return -1;
2725+
}
27182726
if (view->obj != NULL && PyObject_Hash(view->obj) == -1) {
27192727
/* Keep the original error message */
27202728
return -1;

0 commit comments

Comments
 (0)