diff --git a/Lib/test/test_getargs2.py b/Lib/test/test_getargs2.py --- a/Lib/test/test_getargs2.py +++ b/Lib/test/test_getargs2.py @@ -70,6 +70,8 @@ def __int__(self): return True +m = memoryview(bytearray(b'noncontig')) +NONCONTIG_WRITABLE = m[::-2] class Unsigned_TestCase(unittest.TestCase): def test_b(self): @@ -496,6 +498,7 @@ self.assertEqual(getargs_s_star(bytearray(b'bytearray')), b'bytearray') self.assertEqual(getargs_s_star(memoryview(b'memoryview')), b'memoryview') self.assertRaises(TypeError, getargs_s_star, None) + self.assertRaises(BufferError, getargs_s_star, NONCONTIG_WRITABLE) def test_s_hash(self): from _testcapi import getargs_s_hash @@ -505,6 +508,8 @@ self.assertRaises(TypeError, getargs_s_hash, bytearray(b'bytearray')) self.assertRaises(TypeError, getargs_s_hash, memoryview(b'memoryview')) self.assertRaises(TypeError, getargs_s_hash, None) + # TypeError: must be read-only bytes-like object, not memoryview + self.assertRaises(TypeError, getargs_s_hash, NONCONTIG_WRITABLE) def test_z(self): from _testcapi import getargs_z @@ -523,6 +528,7 @@ self.assertEqual(getargs_z_star(bytearray(b'bytearray')), b'bytearray') self.assertEqual(getargs_z_star(memoryview(b'memoryview')), b'memoryview') self.assertIsNone(getargs_z_star(None)) + self.assertRaises(BufferError, getargs_z_star, NONCONTIG_WRITABLE) def test_z_hash(self): from _testcapi import getargs_z_hash @@ -532,6 +538,8 @@ self.assertRaises(TypeError, getargs_z_hash, bytearray(b'bytearray')) self.assertRaises(TypeError, getargs_z_hash, memoryview(b'memoryview')) self.assertIsNone(getargs_z_hash(None)) + # TypeError: must be read-only bytes-like object, not memoryview + self.assertRaises(TypeError, getargs_z_hash, NONCONTIG_WRITABLE) def test_y(self): from _testcapi import getargs_y @@ -550,6 +558,7 @@ self.assertEqual(getargs_y_star(bytearray(b'bytearray')), b'bytearray') self.assertEqual(getargs_y_star(memoryview(b'memoryview')), b'memoryview') self.assertRaises(TypeError, getargs_y_star, None) + self.assertRaises(BufferError, getargs_y_star, NONCONTIG_WRITABLE) def test_y_hash(self): from _testcapi import getargs_y_hash @@ -559,6 +568,8 @@ self.assertRaises(TypeError, getargs_y_hash, bytearray(b'bytearray')) self.assertRaises(TypeError, getargs_y_hash, memoryview(b'memoryview')) self.assertRaises(TypeError, getargs_y_hash, None) + # TypeError: must be read-only bytes-like object, not memoryview + self.assertRaises(TypeError, getargs_y_hash, NONCONTIG_WRITABLE) def test_w_star(self): # getargs_w_star() modifies first and last byte @@ -571,6 +582,7 @@ self.assertEqual(getargs_w_star(memoryview(bytearray(b'memoryview'))), b'[emoryvie]') self.assertRaises(TypeError, getargs_w_star, None) + self.assertRaises(TypeError, getargs_w_star, NONCONTIG_WRITABLE) class Unicode_TestCase(unittest.TestCase): diff --git a/Python/getargs.c b/Python/getargs.c --- a/Python/getargs.c +++ b/Python/getargs.c @@ -1240,17 +1240,14 @@ arg, msgbuf, bufsize); format++; - /* Caller is interested in Py_buffer, and the object - supports it directly. */ + /* Caller is interested in Py_buffer, and the object supports it + directly. The request implicitly asks for PyBUF_SIMPLE, so the + result is C-contiguous with format 'B'. */ if (PyObject_GetBuffer(arg, (Py_buffer*)p, PyBUF_WRITABLE) < 0) { PyErr_Clear(); return converterr("read-write bytes-like object", arg, msgbuf, bufsize); } - if (!PyBuffer_IsContiguous((Py_buffer*)p, 'C')) { - PyBuffer_Release((Py_buffer*)p); - return converterr("contiguous buffer", arg, msgbuf, bufsize); - } if (addcleanup(p, freelist, cleanup_buffer)) { return converterr( "(cleanup problem)", @@ -1298,15 +1295,12 @@ static int getbuffer(PyObject *arg, Py_buffer *view, char **errmsg) { + /* PyBUF_SIMPLE implies C-contiguous */ if (PyObject_GetBuffer(arg, view, PyBUF_SIMPLE) != 0) { *errmsg = "bytes-like object"; return -1; } - if (!PyBuffer_IsContiguous(view, 'C')) { - PyBuffer_Release(view); - *errmsg = "contiguous buffer"; - return -1; - } + return 0; }