Skip to content

gh-148529: Accept any contiguous bytes-like object for the struct 's' and 'p' formats#152029

Open
iamsharduld wants to merge 1 commit into
python:mainfrom
iamsharduld:local-gh-148529-struct-pack-buffer
Open

gh-148529: Accept any contiguous bytes-like object for the struct 's' and 'p' formats#152029
iamsharduld wants to merge 1 commit into
python:mainfrom
iamsharduld:local-gh-148529-struct-pack-buffer

Conversation

@iamsharduld

@iamsharduld iamsharduld commented Jun 23, 2026

Copy link
Copy Markdown
Contributor

struct.pack (and pack_into / Struct.pack) only accepted bytes and bytearray for the s and p format codes. Passing any other buffer — memoryview, array.array, mmap, ... — failed with struct.error, even though it's a contiguous chunk of bytes that can be copied straight in:

>>> struct.pack("4s", memoryview(b"abad"))
struct.error: argument for 's' must be a bytes object

Both codes now accept any contiguous bytes-like object. bytes/bytearray keep their existing fast path; anything else goes through the buffer protocol (PyObject_GetBuffer with PyBUF_SIMPLE), and the buffer is released on every exit path. Non-contiguous buffers and objects that don't expose a buffer still raise struct.error (with a slightly clearer message now).

serhiy-storchaka said as much on the issue — "there is no reason to limit it to bytes and bytearray, any object providing continuous buffer can be supported".

Added a regression test covering memoryview and array.array through pack, pack_into and Struct.pack, and updated the docs, which until now spelled out the bytes/bytearray-only restriction.

@read-the-docs-community

Copy link
Copy Markdown

Documentation build overview

📚 cpython-previews | 🛠️ Build #33277486 | 📁 Comparing ce9d4be against main (7928a8b)

  🔍 Preview build  

2 files changed
± library/struct.html
± whatsnew/changelog.html

@serhiy-storchaka serhiy-storchaka self-requested a review July 13, 2026 08:00

@serhiy-storchaka serhiy-storchaka left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All looks fine. I only left few minor suggestions.

Comment thread Modules/_struct.c
gotview = 1;
}
else {
PyErr_Format(state->StructError,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is better to only raise StructError if there were no error set or it was a TypeError. Otherwise it can shadow errors like MemoryError, OverflowError or KeyboardInterrupt.

Comment thread Modules/_struct.c
}
else {
PyErr_Format(state->StructError,
"argument for 's' must be a bytes-like object, "

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"must be a contiguous bytes-like object"

Otherwise it will be confusing for non-contiguous memoryview.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants