Skip to content

Commit 3f2d101

Browse files
committed
Issue python#29300: Convert _struct module to Argument Clinic
* The struct module now requires contiguous buffers. * Convert most functions and methods of the _struct module to Argument Clinic * Use "Py_buffer" type for the "buffer" argument. Argument Clinic is responsible to create and release the Py_buffer object. * Use "PyStructObject *" type for self to avoid explicit conversions. * Add an unit test on the _struct.Struct.unpack_from() method to test passing arguments as keywords. * Rephrase docstrings. * Rename "fmt" argument to "format" in docstrings and the documentation. As a side effect, functions and methods which used METH_VARARGS calling convention like struct.pack() now use the METH_FASTCALL calling convention which avoids the creation of temporary tuple to pass positional arguments and so is faster. For example, struct.pack("i", 1) becomes 1.56x faster (-36%):: $ ./python -m perf timeit \ -s 'import struct; pack=struct.pack' 'pack("i", 1)' \ --compare-to=../default-ref/python Median +- std dev: 119 ns +- 1 ns -> 76.8 ns +- 0.4 ns: 1.56x faster (-36%) Significant (t=295.91) Patch co-written with Serhiy Storchaka.
1 parent fd6d0d2 commit 3f2d101

4 files changed

Lines changed: 540 additions & 239 deletions

File tree

Doc/library/struct.rst

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -48,40 +48,40 @@ The module defines the following exception and functions:
4848
is wrong.
4949

5050

51-
.. function:: pack(fmt, v1, v2, ...)
51+
.. function:: pack(format, v1, v2, ...)
5252

5353
Return a bytes object containing the values *v1*, *v2*, ... packed according
54-
to the format string *fmt*. The arguments must match the values required by
54+
to the format string *format*. The arguments must match the values required by
5555
the format exactly.
5656

5757

58-
.. function:: pack_into(fmt, buffer, offset, v1, v2, ...)
58+
.. function:: pack_into(format, buffer, offset, v1, v2, ...)
5959

60-
Pack the values *v1*, *v2*, ... according to the format string *fmt* and
60+
Pack the values *v1*, *v2*, ... according to the format string *format* and
6161
write the packed bytes into the writable buffer *buffer* starting at
6262
position *offset*. Note that *offset* is a required argument.
6363

6464

65-
.. function:: unpack(fmt, buffer)
65+
.. function:: unpack(format, buffer)
6666

67-
Unpack from the buffer *buffer* (presumably packed by ``pack(fmt, ...)``)
68-
according to the format string *fmt*. The result is a tuple even if it
67+
Unpack from the buffer *buffer* (presumably packed by ``pack(format, ...)``)
68+
according to the format string *format*. The result is a tuple even if it
6969
contains exactly one item. The buffer's size in bytes must match the
7070
size required by the format, as reflected by :func:`calcsize`.
7171

7272

73-
.. function:: unpack_from(fmt, buffer, offset=0)
73+
.. function:: unpack_from(format, buffer, offset=0)
7474

7575
Unpack from *buffer* starting at position *offset*, according to the format
76-
string *fmt*. The result is a tuple even if it contains exactly one
76+
string *format*. The result is a tuple even if it contains exactly one
7777
item. The buffer's size in bytes, minus *offset*, must be at least
7878
the size required by the format, as reflected by :func:`calcsize`.
7979

8080

81-
.. function:: iter_unpack(fmt, buffer)
81+
.. function:: iter_unpack(format, buffer)
8282

8383
Iteratively unpack from the buffer *buffer* according to the format
84-
string *fmt*. This function returns an iterator which will read
84+
string *format*. This function returns an iterator which will read
8585
equally-sized chunks from the buffer until all its contents have been
8686
consumed. The buffer's size in bytes must be a multiple of the size
8787
required by the format, as reflected by :func:`calcsize`.
@@ -91,10 +91,11 @@ The module defines the following exception and functions:
9191
.. versionadded:: 3.4
9292

9393

94-
.. function:: calcsize(fmt)
94+
.. function:: calcsize(format)
9595

9696
Return the size of the struct (and hence of the bytes object produced by
97-
``pack(fmt, ...)``) corresponding to the format string *fmt*.
97+
``pack(format, ...)``) corresponding to the format string *format*.
98+
9899

99100
.. _struct-format-strings:
100101

Lib/test/test_struct.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -412,6 +412,10 @@ def test_unpack_from(self):
412412
for i in range(6, len(test_string) + 1):
413413
self.assertRaises(struct.error, struct.unpack_from, fmt, data, i)
414414

415+
# keyword arguments
416+
self.assertEqual(s.unpack_from(buffer=test_string, offset=2),
417+
(b'cd01',))
418+
415419
def test_pack_into(self):
416420
test_string = b'Reykjavik rocks, eow!'
417421
writable_buf = array.array('b', b' '*100)

0 commit comments

Comments
 (0)