https://github.com/python/cpython/commit/16b03d8cceaac67ae846c451d22a045f06d8a0f4
commit: 16b03d8cceaac67ae846c451d22a045f06d8a0f4
branch: 3.13
author: Serhiy Storchaka <[email protected]>
committer: serhiy-storchaka <[email protected]>
date: 2026-07-15T09:43:32Z
summary:

[3.13] gh-71086: Document negative offset support in struct.pack_into() and 
unpack_from() (GH-153650) (GH-153754)

(cherry picked from commit 1706d14a2a1f009f786b8d7599e53c168b0392e0)

Co-authored-by: Claude Opus 4.8 (1M context) <[email protected]>

files:
M Doc/library/struct.rst
M Modules/_struct.c
M Modules/clinic/_struct.c.h

diff --git a/Doc/library/struct.rst b/Doc/library/struct.rst
index 56930274914a150..3c0a7f07cff9d87 100644
--- a/Doc/library/struct.rst
+++ b/Doc/library/struct.rst
@@ -68,6 +68,7 @@ The module defines the following exception and functions:
    Pack the values *v1*, *v2*, ... according to the format string *format* and
    write the packed bytes into the writable buffer *buffer* starting at
    position *offset*.  Note that *offset* is a required argument.
+   A negative *offset* counts from the end of *buffer*.
 
 
 .. function:: unpack(format, buffer)
@@ -84,6 +85,7 @@ The module defines the following exception and functions:
    string *format*.  The result is a tuple even if it contains exactly one
    item.  The buffer's size in bytes, starting at position *offset*, must be at
    least the size required by the format, as reflected by :func:`calcsize`.
+   A negative *offset* counts from the end of *buffer*.
 
 
 .. function:: iter_unpack(format, buffer)
diff --git a/Modules/_struct.c b/Modules/_struct.c
index 8ca52b23fd1923d..1195f6f0d7434ff 100644
--- a/Modules/_struct.c
+++ b/Modules/_struct.c
@@ -1758,7 +1758,8 @@ Return a tuple containing unpacked values.
 Values are unpacked according to the format string Struct.format.
 
 The buffer's size in bytes, starting at position offset, must be
-at least Struct.size.
+at least Struct.size.  A negative offset counts from the end of the
+buffer.
 
 See help(struct) for more on format strings.
 [clinic start generated code]*/
@@ -1766,7 +1767,7 @@ See help(struct) for more on format strings.
 static PyObject *
 Struct_unpack_from_impl(PyStructObject *self, Py_buffer *buffer,
                         Py_ssize_t offset)
-/*[clinic end generated code: output=57fac875e0977316 input=cafd4851d473c894]*/
+/*[clinic end generated code: output=57fac875e0977316 input=3451f778ed8a5345]*/
 {
     _structmodulestate *state = get_struct_state_structinst(self);
     ENSURE_STRUCT_IS_READY(self);
@@ -2085,8 +2086,9 @@ PyDoc_STRVAR(s_pack_into__doc__,
 \n\
 Pack the values v1, v2, ... according to the format string S.format\n\
 and write the packed bytes into the writable buffer buf starting at\n\
-offset.  Note that the offset is a required argument.  See\n\
-help(struct) for more on format strings.");
+offset.  Note that the offset is a required argument.  A negative\n\
+offset counts from the end of the buffer.  See help(struct) for more\n\
+on format strings.");
 
 static PyObject *
 s_pack_into(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
@@ -2378,8 +2380,8 @@ PyDoc_STRVAR(pack_into_doc,
 \n\
 Pack the values v1, v2, ... according to the format string and write\n\
 the packed bytes into the writable buffer buf starting at offset.  Note\n\
-that the offset is a required argument.  See help(struct) for more\n\
-on format strings.");
+that the offset is a required argument.  A negative offset counts from\n\
+the end of the buffer.  See help(struct) for more on format strings.");
 
 static PyObject *
 pack_into(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
@@ -2433,6 +2435,7 @@ unpack_from
 Return a tuple containing values unpacked according to the format string.
 
 The buffer's size, minus offset, must be at least calcsize(format).
+A negative offset counts from the end of the buffer.
 
 See help(struct) for more on format strings.
 [clinic start generated code]*/
@@ -2440,7 +2443,7 @@ See help(struct) for more on format strings.
 static PyObject *
 unpack_from_impl(PyObject *module, PyStructObject *s_object,
                  Py_buffer *buffer, Py_ssize_t offset)
-/*[clinic end generated code: output=1042631674c6e0d3 input=6e80a5398e985025]*/
+/*[clinic end generated code: output=1042631674c6e0d3 input=e383ecb97728be2b]*/
 {
     return Struct_unpack_from_impl(s_object, buffer, offset);
 }
diff --git a/Modules/clinic/_struct.c.h b/Modules/clinic/_struct.c.h
index 1a07532bdd75ad5..ae7a87aa3839cd9 100644
--- a/Modules/clinic/_struct.c.h
+++ b/Modules/clinic/_struct.c.h
@@ -114,7 +114,8 @@ PyDoc_STRVAR(Struct_unpack_from__doc__,
 "Values are unpacked according to the format string Struct.format.\n"
 "\n"
 "The buffer\'s size in bytes, starting at position offset, must be\n"
-"at least Struct.size.\n"
+"at least Struct.size.  A negative offset counts from the end of the\n"
+"buffer.\n"
 "\n"
 "See help(struct) for more on format strings.");
 
@@ -312,6 +313,7 @@ PyDoc_STRVAR(unpack_from__doc__,
 "Return a tuple containing values unpacked according to the format string.\n"
 "\n"
 "The buffer\'s size, minus offset, must be at least calcsize(format).\n"
+"A negative offset counts from the end of the buffer.\n"
 "\n"
 "See help(struct) for more on format strings.");
 
@@ -436,4 +438,4 @@ iter_unpack(PyObject *module, PyObject *const *args, 
Py_ssize_t nargs)
 
     return return_value;
 }
-/*[clinic end generated code: output=67bd299e5d72fee0 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=d74ae26e398819db input=a9049054013a1b77]*/

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]

Reply via email to