[Python-checkins] cpython (2.7): Issue #22113: struct.pack_into() now supports new buffer protocol (in

serhiy.storchaka python-checkins at python.org
Sat Feb 21 18:57:14 CET 2015


https://hg.python.org/cpython/rev/4d8e37e54a7d
changeset: 94719:4d8e37e54a7d
branch: 2.7
parent: 94715:5387095b8675
user: Serhiy Storchaka <storchaka at gmail.com>
date: Sat Feb 21 19:51:17 2015 +0200
summary:
 Issue #22113: struct.pack_into() now supports new buffer protocol (in
particular accepts writable memoryview).
files:
 Lib/test/test_struct.py | 19 ++++++++++++++-----
 Misc/NEWS | 3 +++
 Modules/_struct.c | 22 ++++++++++++----------
 3 files changed, 29 insertions(+), 15 deletions(-)
diff --git a/Lib/test/test_struct.py b/Lib/test/test_struct.py
--- a/Lib/test/test_struct.py
+++ b/Lib/test/test_struct.py
@@ -433,24 +433,24 @@
 self.assertRaises(struct.error, s.unpack_from, data, i)
 self.assertRaises(struct.error, struct.unpack_from, fmt, data, i)
 
- def test_pack_into(self):
+ def test_pack_into(self, cls=bytearray, tobytes=str):
 test_string = 'Reykjavik rocks, eow!'
- writable_buf = array.array('c', ' '*100)
+ writable_buf = cls(' '*100)
 fmt = '21s'
 s = struct.Struct(fmt)
 
 # Test without offset
 s.pack_into(writable_buf, 0, test_string)
- from_buf = writable_buf.tostring()[:len(test_string)]
+ from_buf = tobytes(writable_buf)[:len(test_string)]
 self.assertEqual(from_buf, test_string)
 
 # Test with offset.
 s.pack_into(writable_buf, 10, test_string)
- from_buf = writable_buf.tostring()[:len(test_string)+10]
+ from_buf = tobytes(writable_buf)[:len(test_string)+10]
 self.assertEqual(from_buf, test_string[:10] + test_string)
 
 # Go beyond boundaries.
- small_buf = array.array('c', ' '*10)
+ small_buf = cls(' '*10)
 self.assertRaises((ValueError, struct.error), s.pack_into, small_buf, 0,
 test_string)
 self.assertRaises((ValueError, struct.error), s.pack_into, small_buf, 2,
@@ -461,6 +461,15 @@
 self.assertRaises((TypeError, struct.error), struct.pack_into, b'', sb,
 None)
 
+ def test_pack_into_array(self):
+ self.test_pack_into(cls=lambda b: array.array('c', b),
+ tobytes=array.array.tostring)
+
+ def test_pack_into_memoryview(self):
+ # Issue #22113
+ self.test_pack_into(cls=lambda b: memoryview(bytearray(b)),
+ tobytes=memoryview.tobytes)
+
 def test_pack_into_fn(self):
 test_string = 'Reykjavik rocks, eow!'
 writable_buf = array.array('c', ' '*100)
diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -18,6 +18,9 @@
 Library
 -------
 
+- Issue #22113: struct.pack_into() now supports new buffer protocol (in
+ particular accepts writable memoryview).
+
 - Issues #814253, #9179: Warnings now are raised when group references and
 conditional group references are used in lookbehind assertions in regular
 expressions.
diff --git a/Modules/_struct.c b/Modules/_struct.c
--- a/Modules/_struct.c
+++ b/Modules/_struct.c
@@ -1657,8 +1657,8 @@
 s_pack_into(PyObject *self, PyObject *args)
 {
 PyStructObject *soself;
- char *buffer;
- Py_ssize_t buffer_len, offset;
+ Py_buffer buf;
+ Py_ssize_t offset;
 
 /* Validate arguments. +1 is for the first arg as buffer. */
 soself = (PyStructObject *)self;
@@ -1683,33 +1683,35 @@
 }
 
 /* Extract a writable memory buffer from the first argument */
- if ( PyObject_AsWriteBuffer(PyTuple_GET_ITEM(args, 0),
- (void**)&buffer, &buffer_len) == -1 ) {
+ if (!PyArg_Parse(PyTuple_GET_ITEM(args, 0), "w*", &buf))
 return NULL;
- }
- assert( buffer_len >= 0 );
 
 /* Extract the offset from the first argument */
 offset = PyInt_AsSsize_t(PyTuple_GET_ITEM(args, 1));
- if (offset == -1 && PyErr_Occurred())
+ if (offset == -1 && PyErr_Occurred()) {
+ PyBuffer_Release(&buf);
 return NULL;
+ }
 
 /* Support negative offsets. */
 if (offset < 0)
- offset += buffer_len;
+ offset += buf.len;
 
 /* Check boundaries */
- if (offset < 0 || (buffer_len - offset) < soself->s_size) {
+ if (offset < 0 || (buf.len - offset) < soself->s_size) {
 PyErr_Format(StructError,
 "pack_into requires a buffer of at least %zd bytes",
 soself->s_size);
+ PyBuffer_Release(&buf);
 return NULL;
 }
 
 /* Call the guts */
- if ( s_pack_internal(soself, args, 2, buffer + offset) != 0 ) {
+ if (s_pack_internal(soself, args, 2, (char *)buf.buf + offset) != 0) {
+ PyBuffer_Release(&buf);
 return NULL;
 }
+ PyBuffer_Release(&buf);
 
 Py_RETURN_NONE;
 }
-- 
Repository URL: https://hg.python.org/cpython


More information about the Python-checkins mailing list

AltStyle によって変換されたページ (->オリジナル) /