https://github.com/python/cpython/commit/780e9692fefe03c9dfe3bd00bde12dc83ace60c1
commit: 780e9692fefe03c9dfe3bd00bde12dc83ace60c1
branch: main
author: Serhiy Storchaka <[email protected]>
committer: serhiy-storchaka <[email protected]>
date: 2026-01-16T13:35:23+02:00
summary:

gh-143672: Finish conversion of the struct module to Argument Clinic (GH-143857)

Co-authored-by: Sergey B Kirpichev <[email protected]>

files:
M Lib/test/test_inspect/test_inspect.py
M Modules/_struct.c
M Modules/clinic/_struct.c.h

diff --git a/Lib/test/test_inspect/test_inspect.py 
b/Lib/test/test_inspect/test_inspect.py
index 075e1802bebc3e..b25414bea659b7 100644
--- a/Lib/test/test_inspect/test_inspect.py
+++ b/Lib/test/test_inspect/test_inspect.py
@@ -6266,6 +6266,10 @@ def test_stat_module_has_signatures(self):
         import stat
         self._test_module_has_signatures(stat)
 
+    def test_struct_module_has_signatures(self):
+        import struct
+        self._test_module_has_signatures(struct)
+
     def test_string_module_has_signatures(self):
         import string
         self._test_module_has_signatures(string)
diff --git a/Modules/_struct.c b/Modules/_struct.c
index a8e9021f0a303a..34e931790ebb39 100644
--- a/Modules/_struct.c
+++ b/Modules/_struct.c
@@ -1784,15 +1784,13 @@ Struct.__init__
 
 Create a compiled struct object.
 
-Return a new Struct object which writes and reads binary data according to
-the format string.
-
-See help(struct) for more on format strings.
+Return a new Struct object which writes and reads binary data according
+to the format string.  See help(struct) for more on format strings.
 [clinic start generated code]*/
 
 static int
 Struct___init___impl(PyStructObject *self, PyObject *format)
-/*[clinic end generated code: output=b8e80862444e92d0 input=192a4575a3dde802]*/
+/*[clinic end generated code: output=b8e80862444e92d0 input=1af78a5f57d82cec]*/
 {
     int ret = 0;
 
@@ -1914,15 +1912,14 @@ Struct.unpack
 
 Return a tuple containing unpacked values.
 
-Unpack according to the format string Struct.format. The buffer's size
-in bytes must be Struct.size.
-
-See help(struct) for more on format strings.
+Unpack according to the struct format string.  The buffer's
+size in bytes must be the struct size.  See help(struct) for more on
+format strings.
 [clinic start generated code]*/
 
 static PyObject *
 Struct_unpack_impl(PyStructObject *self, Py_buffer *buffer)
-/*[clinic end generated code: output=873a24faf02e848a input=3113f8e7038b2f6c]*/
+/*[clinic end generated code: output=873a24faf02e848a input=488843a57c47065a]*/
 {
     _structmodulestate *state = get_struct_state_structinst(self);
     ENSURE_STRUCT_IS_READY(self);
@@ -1943,18 +1940,16 @@ Struct.unpack_from
 
 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.
-
-See help(struct) for more on format strings.
+Values are unpacked according to the struct format string.  The
+buffer's size in bytes, starting at position offset, must be at
+least the struct size.  See help(struct) for more on format
+strings.
 [clinic start generated code]*/
 
 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=57cfcf84c088faa4]*/
 {
     _structmodulestate *state = get_struct_state_structinst(self);
     ENSURE_STRUCT_IS_READY(self);
@@ -2098,14 +2093,13 @@ Struct.iter_unpack
 Return an iterator yielding tuples.
 
 Tuples are unpacked from the given bytes source, like a repeated
-invocation of unpack_from().
-
-Requires that the bytes length be a multiple of the struct size.
+invocation of unpack_from().  Requires that the bytes length be
+a multiple of the struct size.
 [clinic start generated code]*/
 
 static PyObject *
 Struct_iter_unpack_impl(PyStructObject *self, PyObject *buffer)
-/*[clinic end generated code: output=818f89ad4afa8d64 input=6d65b3f3107dbc99]*/
+/*[clinic end generated code: output=818f89ad4afa8d64 input=9555d2d29d1d9cd2]*/
 {
     _structmodulestate *state = get_struct_state_structinst(self);
     unpackiterobject *iter;
@@ -2150,7 +2144,7 @@ Struct_iter_unpack_impl(PyStructObject *self, PyObject 
*buffer)
  *
  */
 static int
-s_pack_internal(PyStructObject *soself, PyObject *const *args, int offset,
+s_pack_internal(PyStructObject *soself, PyObject *const *args,
                 char* buf, _structmodulestate *state)
 {
     formatcode *code;
@@ -2159,7 +2153,7 @@ s_pack_internal(PyStructObject *soself, PyObject *const 
*args, int offset,
     Py_ssize_t i;
 
     memset(buf, '\0', soself->s_size);
-    i = offset;
+    i = 0;
     for (code = soself->s_codes; code->fmtdef != NULL; code++) {
         const formatdef *e = code->fmtdef;
         char *res = buf + code->offset;
@@ -2234,145 +2228,132 @@ s_pack_internal(PyStructObject *soself, PyObject 
*const *args, int offset,
 }
 
 
-PyDoc_STRVAR(s_pack__doc__,
-"S.pack(v1, v2, ...) -> bytes\n\
-\n\
-Return a bytes object containing values v1, v2, ... packed according\n\
-to the format string S.format.  See help(struct) for more on format\n\
-strings.");
+/*[clinic input]
+Struct.pack
+
+    *values: array
+
+Pack values and return the packed bytes.
+
+Return a bytes object containing the provided values packed
+according to the struct format string.  See help(struct) for more on
+format strings.
+[clinic start generated code]*/
 
 static PyObject *
-s_pack(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
+Struct_pack_impl(PyStructObject *self, PyObject * const *values,
+                 Py_ssize_t values_length)
+/*[clinic end generated code: output=5766e18f596cae9e input=295f4b1a97747458]*/
 {
-    PyStructObject *soself;
     _structmodulestate *state = get_struct_state_structinst(self);
 
     /* Validate arguments. */
-    soself = PyStructObject_CAST(self);
-    ENSURE_STRUCT_IS_READY(soself);
-    assert(PyStruct_Check(self, state));
-    if (nargs != soself->s_len)
-    {
+    ENSURE_STRUCT_IS_READY(self);
+    if (values_length != self->s_len) {
         PyErr_Format(state->StructError,
-            "pack expected %zd items for packing (got %zd)", soself->s_len, 
nargs);
+                     "pack expected %zd items for packing (got %zd)",
+                     self->s_len, values_length);
         return NULL;
     }
 
-    /* Allocate a new string */
-    PyBytesWriter *writer = PyBytesWriter_Create(soself->s_size);
+    PyBytesWriter *writer = PyBytesWriter_Create(self->s_size);
     if (writer == NULL) {
         return NULL;
     }
     char *buf = PyBytesWriter_GetData(writer);
 
     /* Call the guts */
-    if ( s_pack_internal(soself, args, 0, buf, state) != 0 ) {
+    if (s_pack_internal(self, values, buf, state) != 0) {
         PyBytesWriter_Discard(writer);
         return NULL;
     }
 
-    return PyBytesWriter_FinishWithSize(writer, soself->s_size);
+    return PyBytesWriter_FinishWithSize(writer, self->s_size);
 }
 
-PyDoc_STRVAR(s_pack_into__doc__,
-"S.pack_into(buffer, offset, v1, v2, ...)\n\
-\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.");
+/*[clinic input]
+Struct.pack_into
+
+    buffer: Py_buffer(accept={rwbuffer})
+    offset as offset_obj: object
+    /
+    *values: array
+
+Pack values and write the packed bytes into the buffer.
+
+Pack the provided values according to the struct format string
+and write the packed bytes into the writable buffer starting at
+offset.  Note that the offset is a required argument.  See
+help(struct) for more on format strings.
+[clinic start generated code]*/
 
 static PyObject *
-s_pack_into(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
+Struct_pack_into_impl(PyStructObject *self, Py_buffer *buffer,
+                      PyObject *offset_obj, PyObject * const *values,
+                      Py_ssize_t values_length)
+/*[clinic end generated code: output=b0c2ef496135dad3 input=d0de9b9f138c782d]*/
 {
-    PyStructObject *soself;
-    Py_buffer buffer;
     Py_ssize_t offset;
     _structmodulestate *state = get_struct_state_structinst(self);
 
-    /* Validate arguments.  +1 is for the first arg as buffer. */
-    soself = PyStructObject_CAST(self);
-    ENSURE_STRUCT_IS_READY(soself);
-    assert(PyStruct_Check(self, state));
-    if (nargs != (soself->s_len + 2))
-    {
-        if (nargs == 0) {
-            PyErr_Format(state->StructError,
-                        "pack_into expected buffer argument");
-        }
-        else if (nargs == 1) {
-            PyErr_Format(state->StructError,
-                        "pack_into expected offset argument");
-        }
-        else {
-            PyErr_Format(state->StructError,
-                        "pack_into expected %zd items for packing (got %zd)",
-                        soself->s_len, (nargs - 2));
-        }
+    ENSURE_STRUCT_IS_READY(self);
+    if (values_length != self->s_len) {
+        PyErr_Format(state->StructError,
+                     "pack_into expected %zd items for packing (got %zd)",
+                     self->s_len, values_length);
         return NULL;
     }
 
-    /* Extract a writable memory buffer from the first argument */
-    if (!PyArg_Parse(args[0], "w*", &buffer))
-        return NULL;
-    assert(buffer.len >= 0);
-
     /* Extract the offset from the first argument */
-    offset = PyNumber_AsSsize_t(args[1], PyExc_IndexError);
+    offset = PyNumber_AsSsize_t(offset_obj, PyExc_IndexError);
     if (offset == -1 && PyErr_Occurred()) {
-        PyBuffer_Release(&buffer);
         return NULL;
     }
 
     /* Support negative offsets. */
     if (offset < 0) {
          /* Check that negative offset is low enough to fit data */
-        if (offset + soself->s_size > 0) {
+        if (offset + self->s_size > 0) {
             PyErr_Format(state->StructError,
                          "no space to pack %zd bytes at offset %zd",
-                         soself->s_size,
+                         self->s_size,
                          offset);
-            PyBuffer_Release(&buffer);
             return NULL;
         }
 
         /* Check that negative offset is not crossing buffer boundary */
-        if (offset + buffer.len < 0) {
+        if (offset + buffer->len < 0) {
             PyErr_Format(state->StructError,
                          "offset %zd out of range for %zd-byte buffer",
                          offset,
-                         buffer.len);
-            PyBuffer_Release(&buffer);
+                         buffer->len);
             return NULL;
         }
 
-        offset += buffer.len;
+        offset += buffer->len;
     }
 
     /* Check boundaries */
-    if ((buffer.len - offset) < soself->s_size) {
+    if ((buffer->len - offset) < self->s_size) {
         assert(offset >= 0);
-        assert(soself->s_size >= 0);
+        assert(self->s_size >= 0);
 
         PyErr_Format(state->StructError,
                      "pack_into requires a buffer of at least %zu bytes for "
                      "packing %zd bytes at offset %zd "
                      "(actual buffer size is %zd)",
-                     (size_t)soself->s_size + (size_t)offset,
-                     soself->s_size,
+                     (size_t)self->s_size + (size_t)offset,
+                     self->s_size,
                      offset,
-                     buffer.len);
-        PyBuffer_Release(&buffer);
+                     buffer->len);
         return NULL;
     }
 
     /* Call the guts */
-    if (s_pack_internal(soself, args, 2, (char*)buffer.buf + offset, state) != 
0) {
-        PyBuffer_Release(&buffer);
+    if (s_pack_internal(self, values, (char*)buffer->buf + offset, state) != 
0) {
         return NULL;
     }
 
-    PyBuffer_Release(&buffer);
     Py_RETURN_NONE;
 }
 
@@ -2392,13 +2373,14 @@ s_get_size(PyObject *op, void *Py_UNUSED(closure))
     return PyLong_FromSsize_t(self->s_size);
 }
 
-PyDoc_STRVAR(s_sizeof__doc__,
-"S.__sizeof__() -> size of S in memory, in bytes");
+/*[clinic input]
+Struct.__sizeof__
+[clinic start generated code]*/
 
 static PyObject *
-s_sizeof(PyObject *op, PyObject *Py_UNUSED(dummy))
+Struct___sizeof___impl(PyStructObject *self)
+/*[clinic end generated code: output=2d0d78900b4cdb4e input=faca5925c1f1ffd0]*/
 {
-    PyStructObject *self = PyStructObject_CAST(op);
     size_t size = _PyObject_SIZE(Py_TYPE(self)) + sizeof(formatcode);
     for (formatcode *code = self->s_codes; code->fmtdef != NULL; code++) {
         size += sizeof(formatcode);
@@ -2424,11 +2406,11 @@ s_repr(PyObject *op)
 
 static struct PyMethodDef s_methods[] = {
     STRUCT_ITER_UNPACK_METHODDEF
-    {"pack",            _PyCFunction_CAST(s_pack), METH_FASTCALL, 
s_pack__doc__},
-    {"pack_into",       _PyCFunction_CAST(s_pack_into), METH_FASTCALL, 
s_pack_into__doc__},
+    STRUCT_PACK_METHODDEF
+    STRUCT_PACK_INTO_METHODDEF
     STRUCT_UNPACK_METHODDEF
     STRUCT_UNPACK_FROM_METHODDEF
-    {"__sizeof__",      s_sizeof, METH_NOARGS, s_sizeof__doc__},
+    STRUCT___SIZEOF___METHODDEF
     {NULL,       NULL}          /* sentinel */
 };
 
@@ -2443,17 +2425,12 @@ static PyGetSetDef s_getsetlist[] = {
     {NULL} /* sentinel */
 };
 
-PyDoc_STRVAR(s__doc__,
-"Struct(fmt) --> compiled struct object\n"
-"\n"
-);
-
 static PyType_Slot PyStructType_slots[] = {
     {Py_tp_dealloc, s_dealloc},
     {Py_tp_getattro, PyObject_GenericGetAttr},
     {Py_tp_setattro, PyObject_GenericSetAttr},
     {Py_tp_repr, s_repr},
-    {Py_tp_doc, (void*)s__doc__},
+    {Py_tp_doc, (void*)Struct___init____doc__},
     {Py_tp_traverse, s_traverse},
     {Py_tp_clear, s_clear},
     {Py_tp_methods, s_methods},
@@ -2543,58 +2520,52 @@ calcsize_impl(PyObject *module, PyStructObject 
*s_object)
     return s_object->s_size;
 }
 
-PyDoc_STRVAR(pack_doc,
-"pack(format, v1, v2, ...) -> bytes\n\
-\n\
-Return a bytes object containing the values v1, v2, ... packed according\n\
-to the format string.  See help(struct) for more on format strings.");
+/*[clinic input]
+pack
+
+    format as s_object: cache_struct
+    /
+    *values: array
+
+Pack values and return the packed bytes.
+
+Return a bytes object containing the provided values packed according
+to the format string.  See help(struct) for more on format strings.
+[clinic start generated code]*/
 
 static PyObject *
-pack(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
+pack_impl(PyObject *module, PyStructObject *s_object,
+          PyObject * const *values, Py_ssize_t values_length)
+/*[clinic end generated code: output=2f874191ddecdec0 input=8144972342391de1]*/
 {
-    PyObject *s_object = NULL;
-    PyObject *format, *result;
+    return Struct_pack_impl(s_object, values, values_length);
+}
 
-    if (nargs == 0) {
-        PyErr_SetString(PyExc_TypeError, "missing format argument");
-        return NULL;
-    }
-    format = args[0];
+/*[clinic input]
+pack_into
 
-    if (!cache_struct_converter(module, format, (PyStructObject **)&s_object)) 
{
-        return NULL;
-    }
-    result = s_pack(s_object, args + 1, nargs - 1);
-    Py_DECREF(s_object);
-    return result;
-}
+    format as s_object: cache_struct
+    buffer: Py_buffer(accept={rwbuffer})
+    offset as offset_obj: object
+    /
+    *values: array
 
-PyDoc_STRVAR(pack_into_doc,
-"pack_into(format, buffer, offset, v1, v2, ...)\n\
-\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.");
+Pack values and write the packed bytes into the buffer.
+
+Pack the provided values according to the format string and write the
+packed bytes into the writable buffer starting at offset.  Note that the
+offset is a required argument.  See help(struct) for more on format
+strings.
+[clinic start generated code]*/
 
 static PyObject *
-pack_into(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
+pack_into_impl(PyObject *module, PyStructObject *s_object, Py_buffer *buffer,
+               PyObject *offset_obj, PyObject * const *values,
+               Py_ssize_t values_length)
+/*[clinic end generated code: output=148ef659a490eec3 input=3c5fe5bd3b6fd396]*/
 {
-    PyObject *s_object = NULL;
-    PyObject *format, *result;
-
-    if (nargs == 0) {
-        PyErr_SetString(PyExc_TypeError, "missing format argument");
-        return NULL;
-    }
-    format = args[0];
-
-    if (!cache_struct_converter(module, format, (PyStructObject **)&s_object)) 
{
-        return NULL;
-    }
-    result = s_pack_into(s_object, args + 1, nargs - 1);
-    Py_DECREF(s_object);
-    return result;
+    return Struct_pack_into_impl(s_object, buffer, offset_obj,
+                                 values, values_length);
 }
 
 /*[clinic input]
@@ -2606,14 +2577,13 @@ unpack
 
 Return a tuple containing values unpacked according to the format string.
 
-The buffer's size in bytes must be calcsize(format).
-
-See help(struct) for more on format strings.
+The buffer's size in bytes must be calcsize(format).  See help(struct)
+for more on format strings.
 [clinic start generated code]*/
 
 static PyObject *
 unpack_impl(PyObject *module, PyStructObject *s_object, Py_buffer *buffer)
-/*[clinic end generated code: output=48ddd4d88eca8551 input=05fa3b91678da727]*/
+/*[clinic end generated code: output=48ddd4d88eca8551 input=7df28c5d0b5b6f4e]*/
 {
     return Struct_unpack_impl(s_object, buffer);
 }
@@ -2628,15 +2598,14 @@ 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).
-
-See help(struct) for more on format strings.
+The buffer's size, minus offset, must be at least calcsize(format).  See
+help(struct) for more on format strings.
 [clinic start generated code]*/
 
 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=599262b23559f6c5]*/
 {
     return Struct_unpack_from_impl(s_object, buffer, offset);
 }
@@ -2650,26 +2619,25 @@ iter_unpack
 
 Return an iterator yielding tuples unpacked from the given bytes.
 
-The bytes are unpacked according to the format string, like
-a repeated invocation of unpack_from().
-
-Requires that the bytes length be a multiple of the format struct size.
+The bytes are unpacked according to the format string, like a repeated
+invocation of unpack_from().  Requires that the bytes length be
+a multiple of calcsize(format).
 [clinic start generated code]*/
 
 static PyObject *
 iter_unpack_impl(PyObject *module, PyStructObject *s_object,
                  PyObject *buffer)
-/*[clinic end generated code: output=0ae50e250d20e74d input=b214a58869a3c98d]*/
+/*[clinic end generated code: output=0ae50e250d20e74d input=ac5086c5c4ed68bb]*/
 {
-    return Struct_iter_unpack((PyObject*)s_object, buffer);
+    return Struct_iter_unpack_impl(s_object, buffer);
 }
 
 static struct PyMethodDef module_functions[] = {
     _CLEARCACHE_METHODDEF
     CALCSIZE_METHODDEF
     ITER_UNPACK_METHODDEF
-    {"pack",            _PyCFunction_CAST(pack), METH_FASTCALL,   pack_doc},
-    {"pack_into",       _PyCFunction_CAST(pack_into), METH_FASTCALL,   
pack_into_doc},
+    PACK_METHODDEF
+    PACK_INTO_METHODDEF
     UNPACK_METHODDEF
     UNPACK_FROM_METHODDEF
     {NULL,       NULL}          /* sentinel */
diff --git a/Modules/clinic/_struct.c.h b/Modules/clinic/_struct.c.h
index e4eaadb91eb231..11cd26174a3418 100644
--- a/Modules/clinic/_struct.c.h
+++ b/Modules/clinic/_struct.c.h
@@ -15,10 +15,8 @@ PyDoc_STRVAR(Struct___init____doc__,
 "\n"
 "Create a compiled struct object.\n"
 "\n"
-"Return a new Struct object which writes and reads binary data according to\n"
-"the format string.\n"
-"\n"
-"See help(struct) for more on format strings.");
+"Return a new Struct object which writes and reads binary data according\n"
+"to the format string.  See help(struct) for more on format strings.");
 
 static int
 Struct___init___impl(PyStructObject *self, PyObject *format);
@@ -77,10 +75,9 @@ PyDoc_STRVAR(Struct_unpack__doc__,
 "\n"
 "Return a tuple containing unpacked values.\n"
 "\n"
-"Unpack according to the format string Struct.format. The buffer\'s size\n"
-"in bytes must be Struct.size.\n"
-"\n"
-"See help(struct) for more on format strings.");
+"Unpack according to the struct format string.  The buffer\'s\n"
+"size in bytes must be the struct size.  See help(struct) for more on\n"
+"format strings.");
 
 #define STRUCT_UNPACK_METHODDEF    \
     {"unpack", (PyCFunction)Struct_unpack, METH_O, Struct_unpack__doc__},
@@ -114,12 +111,10 @@ PyDoc_STRVAR(Struct_unpack_from__doc__,
 "\n"
 "Return a tuple containing unpacked values.\n"
 "\n"
-"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"
-"\n"
-"See help(struct) for more on format strings.");
+"Values are unpacked according to the struct format string.  The\n"
+"buffer\'s size in bytes, starting at position offset, must be at\n"
+"least the struct size.  See help(struct) for more on format\n"
+"strings.");
 
 #define STRUCT_UNPACK_FROM_METHODDEF    \
     {"unpack_from", _PyCFunction_CAST(Struct_unpack_from), 
METH_FASTCALL|METH_KEYWORDS, Struct_unpack_from__doc__},
@@ -206,9 +201,8 @@ PyDoc_STRVAR(Struct_iter_unpack__doc__,
 "Return an iterator yielding tuples.\n"
 "\n"
 "Tuples are unpacked from the given bytes source, like a repeated\n"
-"invocation of unpack_from().\n"
-"\n"
-"Requires that the bytes length be a multiple of the struct size.");
+"invocation of unpack_from().  Requires that the bytes length be\n"
+"a multiple of the struct size.");
 
 #define STRUCT_ITER_UNPACK_METHODDEF    \
     {"iter_unpack", (PyCFunction)Struct_iter_unpack, METH_O, 
Struct_iter_unpack__doc__},
@@ -226,6 +220,103 @@ Struct_iter_unpack(PyObject *self, PyObject *buffer)
     return return_value;
 }
 
+PyDoc_STRVAR(Struct_pack__doc__,
+"pack($self, /, *values)\n"
+"--\n"
+"\n"
+"Pack values and return the packed bytes.\n"
+"\n"
+"Return a bytes object containing the provided values packed\n"
+"according to the struct format string.  See help(struct) for more on\n"
+"format strings.");
+
+#define STRUCT_PACK_METHODDEF    \
+    {"pack", _PyCFunction_CAST(Struct_pack), METH_FASTCALL, 
Struct_pack__doc__},
+
+static PyObject *
+Struct_pack_impl(PyStructObject *self, PyObject * const *values,
+                 Py_ssize_t values_length);
+
+static PyObject *
+Struct_pack(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
+{
+    PyObject *return_value = NULL;
+    PyObject * const *values;
+    Py_ssize_t values_length;
+
+    values = args;
+    values_length = nargs;
+    return_value = Struct_pack_impl((PyStructObject *)self, values, 
values_length);
+
+    return return_value;
+}
+
+PyDoc_STRVAR(Struct_pack_into__doc__,
+"pack_into($self, buffer, offset, /, *values)\n"
+"--\n"
+"\n"
+"Pack values and write the packed bytes into the buffer.\n"
+"\n"
+"Pack the provided values according to the struct format string\n"
+"and write the packed bytes into the writable buffer starting at\n"
+"offset.  Note that the offset is a required argument.  See\n"
+"help(struct) for more on format strings.");
+
+#define STRUCT_PACK_INTO_METHODDEF    \
+    {"pack_into", _PyCFunction_CAST(Struct_pack_into), METH_FASTCALL, 
Struct_pack_into__doc__},
+
+static PyObject *
+Struct_pack_into_impl(PyStructObject *self, Py_buffer *buffer,
+                      PyObject *offset_obj, PyObject * const *values,
+                      Py_ssize_t values_length);
+
+static PyObject *
+Struct_pack_into(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
+{
+    PyObject *return_value = NULL;
+    Py_buffer buffer = {NULL, NULL};
+    PyObject *offset_obj;
+    PyObject * const *values;
+    Py_ssize_t values_length;
+
+    if (!_PyArg_CheckPositional("pack_into", nargs, 2, PY_SSIZE_T_MAX)) {
+        goto exit;
+    }
+    if (PyObject_GetBuffer(args[0], &buffer, PyBUF_WRITABLE) < 0) {
+        _PyArg_BadArgument("pack_into", "argument 1", "read-write bytes-like 
object", args[0]);
+        goto exit;
+    }
+    offset_obj = args[1];
+    values = args + 2;
+    values_length = nargs - 2;
+    return_value = Struct_pack_into_impl((PyStructObject *)self, &buffer, 
offset_obj, values, values_length);
+
+exit:
+    /* Cleanup for buffer */
+    if (buffer.obj) {
+       PyBuffer_Release(&buffer);
+    }
+
+    return return_value;
+}
+
+PyDoc_STRVAR(Struct___sizeof____doc__,
+"__sizeof__($self, /)\n"
+"--\n"
+"\n");
+
+#define STRUCT___SIZEOF___METHODDEF    \
+    {"__sizeof__", (PyCFunction)Struct___sizeof__, METH_NOARGS, 
Struct___sizeof____doc__},
+
+static PyObject *
+Struct___sizeof___impl(PyStructObject *self);
+
+static PyObject *
+Struct___sizeof__(PyObject *self, PyObject *Py_UNUSED(ignored))
+{
+    return Struct___sizeof___impl((PyStructObject *)self);
+}
+
 PyDoc_STRVAR(_clearcache__doc__,
 "_clearcache($module, /)\n"
 "--\n"
@@ -279,15 +370,110 @@ calcsize(PyObject *module, PyObject *arg)
     return return_value;
 }
 
+PyDoc_STRVAR(pack__doc__,
+"pack($module, format, /, *values)\n"
+"--\n"
+"\n"
+"Pack values and return the packed bytes.\n"
+"\n"
+"Return a bytes object containing the provided values packed according\n"
+"to the format string.  See help(struct) for more on format strings.");
+
+#define PACK_METHODDEF    \
+    {"pack", _PyCFunction_CAST(pack), METH_FASTCALL, pack__doc__},
+
+static PyObject *
+pack_impl(PyObject *module, PyStructObject *s_object,
+          PyObject * const *values, Py_ssize_t values_length);
+
+static PyObject *
+pack(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
+{
+    PyObject *return_value = NULL;
+    PyStructObject *s_object = NULL;
+    PyObject * const *values;
+    Py_ssize_t values_length;
+
+    if (!_PyArg_CheckPositional("pack", nargs, 1, PY_SSIZE_T_MAX)) {
+        goto exit;
+    }
+    if (!cache_struct_converter(module, args[0], &s_object)) {
+        goto exit;
+    }
+    values = args + 1;
+    values_length = nargs - 1;
+    return_value = pack_impl(module, s_object, values, values_length);
+
+exit:
+    /* Cleanup for s_object */
+    Py_XDECREF(s_object);
+
+    return return_value;
+}
+
+PyDoc_STRVAR(pack_into__doc__,
+"pack_into($module, format, buffer, offset, /, *values)\n"
+"--\n"
+"\n"
+"Pack values and write the packed bytes into the buffer.\n"
+"\n"
+"Pack the provided values according to the format string and write the\n"
+"packed bytes into the writable buffer starting at offset.  Note that the\n"
+"offset is a required argument.  See help(struct) for more on format\n"
+"strings.");
+
+#define PACK_INTO_METHODDEF    \
+    {"pack_into", _PyCFunction_CAST(pack_into), METH_FASTCALL, 
pack_into__doc__},
+
+static PyObject *
+pack_into_impl(PyObject *module, PyStructObject *s_object, Py_buffer *buffer,
+               PyObject *offset_obj, PyObject * const *values,
+               Py_ssize_t values_length);
+
+static PyObject *
+pack_into(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
+{
+    PyObject *return_value = NULL;
+    PyStructObject *s_object = NULL;
+    Py_buffer buffer = {NULL, NULL};
+    PyObject *offset_obj;
+    PyObject * const *values;
+    Py_ssize_t values_length;
+
+    if (!_PyArg_CheckPositional("pack_into", nargs, 3, PY_SSIZE_T_MAX)) {
+        goto exit;
+    }
+    if (!cache_struct_converter(module, args[0], &s_object)) {
+        goto exit;
+    }
+    if (PyObject_GetBuffer(args[1], &buffer, PyBUF_WRITABLE) < 0) {
+        _PyArg_BadArgument("pack_into", "argument 2", "read-write bytes-like 
object", args[1]);
+        goto exit;
+    }
+    offset_obj = args[2];
+    values = args + 3;
+    values_length = nargs - 3;
+    return_value = pack_into_impl(module, s_object, &buffer, offset_obj, 
values, values_length);
+
+exit:
+    /* Cleanup for s_object */
+    Py_XDECREF(s_object);
+    /* Cleanup for buffer */
+    if (buffer.obj) {
+       PyBuffer_Release(&buffer);
+    }
+
+    return return_value;
+}
+
 PyDoc_STRVAR(unpack__doc__,
 "unpack($module, format, buffer, /)\n"
 "--\n"
 "\n"
 "Return a tuple containing values unpacked according to the format string.\n"
 "\n"
-"The buffer\'s size in bytes must be calcsize(format).\n"
-"\n"
-"See help(struct) for more on format strings.");
+"The buffer\'s size in bytes must be calcsize(format).  See help(struct)\n"
+"for more on format strings.");
 
 #define UNPACK_METHODDEF    \
     {"unpack", _PyCFunction_CAST(unpack), METH_FASTCALL, unpack__doc__},
@@ -330,9 +516,8 @@ PyDoc_STRVAR(unpack_from__doc__,
 "\n"
 "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"
-"\n"
-"See help(struct) for more on format strings.");
+"The buffer\'s size, minus offset, must be at least calcsize(format).  See\n"
+"help(struct) for more on format strings.");
 
 #define UNPACK_FROM_METHODDEF    \
     {"unpack_from", _PyCFunction_CAST(unpack_from), 
METH_FASTCALL|METH_KEYWORDS, unpack_from__doc__},
@@ -424,10 +609,9 @@ PyDoc_STRVAR(iter_unpack__doc__,
 "\n"
 "Return an iterator yielding tuples unpacked from the given bytes.\n"
 "\n"
-"The bytes are unpacked according to the format string, like\n"
-"a repeated invocation of unpack_from().\n"
-"\n"
-"Requires that the bytes length be a multiple of the format struct size.");
+"The bytes are unpacked according to the format string, like a repeated\n"
+"invocation of unpack_from().  Requires that the bytes length be\n"
+"a multiple of calcsize(format).");
 
 #define ITER_UNPACK_METHODDEF    \
     {"iter_unpack", _PyCFunction_CAST(iter_unpack), METH_FASTCALL, 
iter_unpack__doc__},
@@ -458,4 +642,4 @@ iter_unpack(PyObject *module, PyObject *const *args, 
Py_ssize_t nargs)
 
     return return_value;
 }
-/*[clinic end generated code: output=caa7f36443e91cb9 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=dc4f86c77ab3b1c9 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