mirror of https://github.com/python/cpython
bpo-45155 : Default arguments for int.to_bytes(length=1, byteorder=sys.byteorder) (#28265)
Add default arguments for int.to_bytes() and int.from_bytes() Co-authored-by: Brandt Bucher <brandtbucher@gmail.com>
This commit is contained in:
parent
a9757bf34d
commit
07e737d002
|
@ -499,7 +499,7 @@ class`. In addition, it provides a few more methods:
|
|||
|
||||
.. versionadded:: 3.10
|
||||
|
||||
.. method:: int.to_bytes(length, byteorder, *, signed=False)
|
||||
.. method:: int.to_bytes(length=1, byteorder='big', *, signed=False)
|
||||
|
||||
Return an array of bytes representing an integer.
|
||||
|
||||
|
@ -513,25 +513,31 @@ class`. In addition, it provides a few more methods:
|
|||
>>> x.to_bytes((x.bit_length() + 7) // 8, byteorder='little')
|
||||
b'\xe8\x03'
|
||||
|
||||
The integer is represented using *length* bytes. An :exc:`OverflowError`
|
||||
is raised if the integer is not representable with the given number of
|
||||
bytes.
|
||||
The integer is represented using *length* bytes, and defaults to 1. An
|
||||
:exc:`OverflowError` is raised if the integer is not representable with
|
||||
the given number of bytes.
|
||||
|
||||
The *byteorder* argument determines the byte order used to represent the
|
||||
integer. If *byteorder* is ``"big"``, the most significant byte is at the
|
||||
beginning of the byte array. If *byteorder* is ``"little"``, the most
|
||||
significant byte is at the end of the byte array. To request the native
|
||||
byte order of the host system, use :data:`sys.byteorder` as the byte order
|
||||
value.
|
||||
integer, and defaults to ``"big"``. If *byteorder* is
|
||||
``"big"``, the most significant byte is at the beginning of the byte
|
||||
array. If *byteorder* is ``"little"``, the most significant byte is at
|
||||
the end of the byte array.
|
||||
|
||||
The *signed* argument determines whether two's complement is used to
|
||||
represent the integer. If *signed* is ``False`` and a negative integer is
|
||||
given, an :exc:`OverflowError` is raised. The default value for *signed*
|
||||
is ``False``.
|
||||
|
||||
The default values can be used to conveniently turn an integer into a
|
||||
single byte object. However, when using the default arguments, don't try
|
||||
to convert a value greater than 255 or you'll get an :exc:`OverflowError`::
|
||||
|
||||
>>> (65).to_bytes()
|
||||
b'A'
|
||||
|
||||
Equivalent to::
|
||||
|
||||
def to_bytes(n, length, byteorder, signed=False):
|
||||
def to_bytes(n, length=1, byteorder='big', signed=False):
|
||||
if byteorder == 'little':
|
||||
order = range(length)
|
||||
elif byteorder == 'big':
|
||||
|
@ -542,8 +548,10 @@ class`. In addition, it provides a few more methods:
|
|||
return bytes((n >> i*8) & 0xff for i in order)
|
||||
|
||||
.. versionadded:: 3.2
|
||||
.. versionchanged:: 3.11
|
||||
Added default argument values for ``length`` and ``byteorder``.
|
||||
|
||||
.. classmethod:: int.from_bytes(bytes, byteorder, *, signed=False)
|
||||
.. classmethod:: int.from_bytes(bytes, byteorder='big', *, signed=False)
|
||||
|
||||
Return the integer represented by the given array of bytes.
|
||||
|
||||
|
@ -562,18 +570,18 @@ class`. In addition, it provides a few more methods:
|
|||
iterable producing bytes.
|
||||
|
||||
The *byteorder* argument determines the byte order used to represent the
|
||||
integer. If *byteorder* is ``"big"``, the most significant byte is at the
|
||||
beginning of the byte array. If *byteorder* is ``"little"``, the most
|
||||
significant byte is at the end of the byte array. To request the native
|
||||
byte order of the host system, use :data:`sys.byteorder` as the byte order
|
||||
value.
|
||||
integer, and defaults to ``"big"``. If *byteorder* is
|
||||
``"big"``, the most significant byte is at the beginning of the byte
|
||||
array. If *byteorder* is ``"little"``, the most significant byte is at
|
||||
the end of the byte array. To request the native byte order of the host
|
||||
system, use :data:`sys.byteorder` as the byte order value.
|
||||
|
||||
The *signed* argument indicates whether two's complement is used to
|
||||
represent the integer.
|
||||
|
||||
Equivalent to::
|
||||
|
||||
def from_bytes(bytes, byteorder, signed=False):
|
||||
def from_bytes(bytes, byteorder='big', signed=False):
|
||||
if byteorder == 'little':
|
||||
little_ordered = list(bytes)
|
||||
elif byteorder == 'big':
|
||||
|
@ -588,6 +596,8 @@ class`. In addition, it provides a few more methods:
|
|||
return n
|
||||
|
||||
.. versionadded:: 3.2
|
||||
.. versionchanged:: 3.11
|
||||
Added default argument value for ``byteorder``.
|
||||
|
||||
.. method:: int.as_integer_ratio()
|
||||
|
||||
|
|
|
@ -39,7 +39,7 @@ class CFunctionCallsErrorMessages(unittest.TestCase):
|
|||
self.assertRaisesRegex(TypeError, msg, {}.__contains__, 0, 1)
|
||||
|
||||
def test_varargs3(self):
|
||||
msg = r"^from_bytes\(\) takes exactly 2 positional arguments \(3 given\)"
|
||||
msg = r"^from_bytes\(\) takes at most 2 positional arguments \(3 given\)"
|
||||
self.assertRaisesRegex(TypeError, msg, int.from_bytes, b'a', 'little', False)
|
||||
|
||||
def test_varargs1min(self):
|
||||
|
|
|
@ -1117,9 +1117,18 @@ class LongTest(unittest.TestCase):
|
|||
expected)
|
||||
except Exception as err:
|
||||
raise AssertionError(
|
||||
"failed to convert {0} with byteorder={1} and signed={2}"
|
||||
"failed to convert {} with byteorder={} and signed={}"
|
||||
.format(test, byteorder, signed)) from err
|
||||
|
||||
# Test for all default arguments.
|
||||
if len(expected) == 1 and byteorder == 'big' and not signed:
|
||||
try:
|
||||
self.assertEqual(test.to_bytes(), expected)
|
||||
except Exception as err:
|
||||
raise AssertionError(
|
||||
"failed to convert {} with default arguments"
|
||||
.format(test)) from err
|
||||
|
||||
try:
|
||||
self.assertEqual(
|
||||
equivalent_python(
|
||||
|
@ -1240,9 +1249,20 @@ class LongTest(unittest.TestCase):
|
|||
expected)
|
||||
except Exception as err:
|
||||
raise AssertionError(
|
||||
"failed to convert {0} with byteorder={1!r} and signed={2}"
|
||||
"failed to convert {} with byteorder={!r} and signed={}"
|
||||
.format(test, byteorder, signed)) from err
|
||||
|
||||
# Test for all default arguments.
|
||||
if byteorder == 'big' and not signed:
|
||||
try:
|
||||
self.assertEqual(
|
||||
int.from_bytes(test),
|
||||
expected)
|
||||
except Exception as err:
|
||||
raise AssertionError(
|
||||
"failed to convert {} with default arugments"
|
||||
.format(test)) from err
|
||||
|
||||
try:
|
||||
self.assertEqual(
|
||||
equivalent_python(test, byteorder, signed=signed),
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
:meth:`int.to_bytes` and :meth:`int.from_bytes` now take a default value of
|
||||
``"big"`` for the ``byteorder`` argument. :meth:`int.to_bytes` also takes a
|
||||
default value of ``1`` for the ``length`` argument.
|
|
@ -226,20 +226,21 @@ int_as_integer_ratio(PyObject *self, PyObject *Py_UNUSED(ignored))
|
|||
}
|
||||
|
||||
PyDoc_STRVAR(int_to_bytes__doc__,
|
||||
"to_bytes($self, /, length, byteorder, *, signed=False)\n"
|
||||
"to_bytes($self, /, length=1, byteorder=\'big\', *, signed=False)\n"
|
||||
"--\n"
|
||||
"\n"
|
||||
"Return an array of bytes representing an integer.\n"
|
||||
"\n"
|
||||
" length\n"
|
||||
" Length of bytes object to use. An OverflowError is raised if the\n"
|
||||
" integer is not representable with the given number of bytes.\n"
|
||||
" integer is not representable with the given number of bytes. Default\n"
|
||||
" is length 1.\n"
|
||||
" byteorder\n"
|
||||
" The byte order used to represent the integer. If byteorder is \'big\',\n"
|
||||
" the most significant byte is at the beginning of the byte array. If\n"
|
||||
" byteorder is \'little\', the most significant byte is at the end of the\n"
|
||||
" byte array. To request the native byte order of the host system, use\n"
|
||||
" `sys.byteorder\' as the byte order value.\n"
|
||||
" `sys.byteorder\' as the byte order value. Default is to use \'big\'.\n"
|
||||
" signed\n"
|
||||
" Determines whether two\'s complement is used to represent the integer.\n"
|
||||
" If signed is False and a negative integer is given, an OverflowError\n"
|
||||
|
@ -259,35 +260,49 @@ int_to_bytes(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *
|
|||
static const char * const _keywords[] = {"length", "byteorder", "signed", NULL};
|
||||
static _PyArg_Parser _parser = {NULL, _keywords, "to_bytes", 0};
|
||||
PyObject *argsbuf[3];
|
||||
Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2;
|
||||
Py_ssize_t length;
|
||||
PyObject *byteorder;
|
||||
Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0;
|
||||
Py_ssize_t length = 1;
|
||||
PyObject *byteorder = NULL;
|
||||
int is_signed = 0;
|
||||
|
||||
args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf);
|
||||
args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 2, 0, argsbuf);
|
||||
if (!args) {
|
||||
goto exit;
|
||||
}
|
||||
{
|
||||
Py_ssize_t ival = -1;
|
||||
PyObject *iobj = _PyNumber_Index(args[0]);
|
||||
if (iobj != NULL) {
|
||||
ival = PyLong_AsSsize_t(iobj);
|
||||
Py_DECREF(iobj);
|
||||
if (!noptargs) {
|
||||
goto skip_optional_pos;
|
||||
}
|
||||
if (args[0]) {
|
||||
{
|
||||
Py_ssize_t ival = -1;
|
||||
PyObject *iobj = _PyNumber_Index(args[0]);
|
||||
if (iobj != NULL) {
|
||||
ival = PyLong_AsSsize_t(iobj);
|
||||
Py_DECREF(iobj);
|
||||
}
|
||||
if (ival == -1 && PyErr_Occurred()) {
|
||||
goto exit;
|
||||
}
|
||||
length = ival;
|
||||
}
|
||||
if (ival == -1 && PyErr_Occurred()) {
|
||||
if (!--noptargs) {
|
||||
goto skip_optional_pos;
|
||||
}
|
||||
}
|
||||
if (args[1]) {
|
||||
if (!PyUnicode_Check(args[1])) {
|
||||
_PyArg_BadArgument("to_bytes", "argument 'byteorder'", "str", args[1]);
|
||||
goto exit;
|
||||
}
|
||||
length = ival;
|
||||
if (PyUnicode_READY(args[1]) == -1) {
|
||||
goto exit;
|
||||
}
|
||||
byteorder = args[1];
|
||||
if (!--noptargs) {
|
||||
goto skip_optional_pos;
|
||||
}
|
||||
}
|
||||
if (!PyUnicode_Check(args[1])) {
|
||||
_PyArg_BadArgument("to_bytes", "argument 'byteorder'", "str", args[1]);
|
||||
goto exit;
|
||||
}
|
||||
if (PyUnicode_READY(args[1]) == -1) {
|
||||
goto exit;
|
||||
}
|
||||
byteorder = args[1];
|
||||
skip_optional_pos:
|
||||
if (!noptargs) {
|
||||
goto skip_optional_kwonly;
|
||||
}
|
||||
|
@ -303,7 +318,7 @@ exit:
|
|||
}
|
||||
|
||||
PyDoc_STRVAR(int_from_bytes__doc__,
|
||||
"from_bytes($type, /, bytes, byteorder, *, signed=False)\n"
|
||||
"from_bytes($type, /, bytes, byteorder=\'big\', *, signed=False)\n"
|
||||
"--\n"
|
||||
"\n"
|
||||
"Return the integer represented by the given array of bytes.\n"
|
||||
|
@ -318,7 +333,7 @@ PyDoc_STRVAR(int_from_bytes__doc__,
|
|||
" the most significant byte is at the beginning of the byte array. If\n"
|
||||
" byteorder is \'little\', the most significant byte is at the end of the\n"
|
||||
" byte array. To request the native byte order of the host system, use\n"
|
||||
" `sys.byteorder\' as the byte order value.\n"
|
||||
" `sys.byteorder\' as the byte order value. Default is to use \'big\'.\n"
|
||||
" signed\n"
|
||||
" Indicates whether two\'s complement is used to represent the integer.");
|
||||
|
||||
|
@ -336,24 +351,33 @@ int_from_bytes(PyTypeObject *type, PyObject *const *args, Py_ssize_t nargs, PyOb
|
|||
static const char * const _keywords[] = {"bytes", "byteorder", "signed", NULL};
|
||||
static _PyArg_Parser _parser = {NULL, _keywords, "from_bytes", 0};
|
||||
PyObject *argsbuf[3];
|
||||
Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2;
|
||||
Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1;
|
||||
PyObject *bytes_obj;
|
||||
PyObject *byteorder;
|
||||
PyObject *byteorder = NULL;
|
||||
int is_signed = 0;
|
||||
|
||||
args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf);
|
||||
args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 2, 0, argsbuf);
|
||||
if (!args) {
|
||||
goto exit;
|
||||
}
|
||||
bytes_obj = args[0];
|
||||
if (!PyUnicode_Check(args[1])) {
|
||||
_PyArg_BadArgument("from_bytes", "argument 'byteorder'", "str", args[1]);
|
||||
goto exit;
|
||||
if (!noptargs) {
|
||||
goto skip_optional_pos;
|
||||
}
|
||||
if (PyUnicode_READY(args[1]) == -1) {
|
||||
goto exit;
|
||||
if (args[1]) {
|
||||
if (!PyUnicode_Check(args[1])) {
|
||||
_PyArg_BadArgument("from_bytes", "argument 'byteorder'", "str", args[1]);
|
||||
goto exit;
|
||||
}
|
||||
if (PyUnicode_READY(args[1]) == -1) {
|
||||
goto exit;
|
||||
}
|
||||
byteorder = args[1];
|
||||
if (!--noptargs) {
|
||||
goto skip_optional_pos;
|
||||
}
|
||||
}
|
||||
byteorder = args[1];
|
||||
skip_optional_pos:
|
||||
if (!noptargs) {
|
||||
goto skip_optional_kwonly;
|
||||
}
|
||||
|
@ -367,4 +391,4 @@ skip_optional_kwonly:
|
|||
exit:
|
||||
return return_value;
|
||||
}
|
||||
/*[clinic end generated code: output=ea18e51af5b53591 input=a9049054013a1b77]*/
|
||||
/*[clinic end generated code: output=16a375d93769b227 input=a9049054013a1b77]*/
|
||||
|
|
|
@ -5521,15 +5521,16 @@ int_as_integer_ratio_impl(PyObject *self)
|
|||
/*[clinic input]
|
||||
int.to_bytes
|
||||
|
||||
length: Py_ssize_t
|
||||
length: Py_ssize_t = 1
|
||||
Length of bytes object to use. An OverflowError is raised if the
|
||||
integer is not representable with the given number of bytes.
|
||||
byteorder: unicode
|
||||
integer is not representable with the given number of bytes. Default
|
||||
is length 1.
|
||||
byteorder: unicode(c_default="NULL") = "big"
|
||||
The byte order used to represent the integer. If byteorder is 'big',
|
||||
the most significant byte is at the beginning of the byte array. If
|
||||
byteorder is 'little', the most significant byte is at the end of the
|
||||
byte array. To request the native byte order of the host system, use
|
||||
`sys.byteorder' as the byte order value.
|
||||
`sys.byteorder' as the byte order value. Default is to use 'big'.
|
||||
*
|
||||
signed as is_signed: bool = False
|
||||
Determines whether two's complement is used to represent the integer.
|
||||
|
@ -5542,12 +5543,14 @@ Return an array of bytes representing an integer.
|
|||
static PyObject *
|
||||
int_to_bytes_impl(PyObject *self, Py_ssize_t length, PyObject *byteorder,
|
||||
int is_signed)
|
||||
/*[clinic end generated code: output=89c801df114050a3 input=ddac63f4c7bf414c]*/
|
||||
/*[clinic end generated code: output=89c801df114050a3 input=d42ecfb545039d71]*/
|
||||
{
|
||||
int little_endian;
|
||||
PyObject *bytes;
|
||||
|
||||
if (_PyUnicode_EqualToASCIIId(byteorder, &PyId_little))
|
||||
if (byteorder == NULL)
|
||||
little_endian = 0;
|
||||
else if (_PyUnicode_EqualToASCIIId(byteorder, &PyId_little))
|
||||
little_endian = 1;
|
||||
else if (_PyUnicode_EqualToASCIIId(byteorder, &PyId_big))
|
||||
little_endian = 0;
|
||||
|
@ -5586,12 +5589,12 @@ int.from_bytes
|
|||
support the buffer protocol or be an iterable object producing bytes.
|
||||
Bytes and bytearray are examples of built-in objects that support the
|
||||
buffer protocol.
|
||||
byteorder: unicode
|
||||
byteorder: unicode(c_default="NULL") = "big"
|
||||
The byte order used to represent the integer. If byteorder is 'big',
|
||||
the most significant byte is at the beginning of the byte array. If
|
||||
byteorder is 'little', the most significant byte is at the end of the
|
||||
byte array. To request the native byte order of the host system, use
|
||||
`sys.byteorder' as the byte order value.
|
||||
`sys.byteorder' as the byte order value. Default is to use 'big'.
|
||||
*
|
||||
signed as is_signed: bool = False
|
||||
Indicates whether two's complement is used to represent the integer.
|
||||
|
@ -5602,12 +5605,14 @@ Return the integer represented by the given array of bytes.
|
|||
static PyObject *
|
||||
int_from_bytes_impl(PyTypeObject *type, PyObject *bytes_obj,
|
||||
PyObject *byteorder, int is_signed)
|
||||
/*[clinic end generated code: output=efc5d68e31f9314f input=cdf98332b6a821b0]*/
|
||||
/*[clinic end generated code: output=efc5d68e31f9314f input=33326dccdd655553]*/
|
||||
{
|
||||
int little_endian;
|
||||
PyObject *long_obj, *bytes;
|
||||
|
||||
if (_PyUnicode_EqualToASCIIId(byteorder, &PyId_little))
|
||||
if (byteorder == NULL)
|
||||
little_endian = 0;
|
||||
else if (_PyUnicode_EqualToASCIIId(byteorder, &PyId_little))
|
||||
little_endian = 1;
|
||||
else if (_PyUnicode_EqualToASCIIId(byteorder, &PyId_big))
|
||||
little_endian = 0;
|
||||
|
|
Loading…
Reference in New Issue