Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 27 additions & 17 deletions Doc/library/stdtypes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Expand All @@ -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':
Expand All @@ -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.

Expand All @@ -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':
Expand All @@ -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()

Expand Down
2 changes: 1 addition & 1 deletion Lib/test/test_call.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ def test_varargs2(self):
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):
Expand Down
24 changes: 22 additions & 2 deletions Lib/test/test_long.py
Original file line number Diff line number Diff line change
Expand Up @@ -1117,9 +1117,18 @@ def equivalent_python(n, length, byteorder, signed=False):
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(
Expand Down Expand Up @@ -1240,9 +1249,20 @@ def equivalent_python(byte_array, byteorder, signed=False):
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),
Expand Down
Original file line number Diff line number Diff line change
@@ -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.
94 changes: 59 additions & 35 deletions Objects/clinic/longobject.c.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

25 changes: 15 additions & 10 deletions Objects/longobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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;
Comment thread
warsaw marked this conversation as resolved.
Expand Down Expand Up @@ -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.
Expand All @@ -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;
Expand Down