Skip to content

Commit

Permalink
bpo-16580: [doc] Add examples to int.to_bytes and int.from_bytes (pyt…
Browse files Browse the repository at this point in the history
…honGH-27760)

* added code equivs. for to_bytes and from_bytes

Based on woparry's patch[1] from the relevant issue thread[2].

[1]: https://bugs.python.org/file30372/issue16580.patch
[2]: https://bugs.python.org/issue16580

Co-authored-by: Mark Dickinson <[email protected]>
  • Loading branch information
quantumgc and mdickinson authored Aug 15, 2021
1 parent ed524b4 commit ad0a8a9
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 0 deletions.
28 changes: 28 additions & 0 deletions Doc/library/stdtypes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -529,6 +529,18 @@ class`. In addition, it provides a few more methods:
given, an :exc:`OverflowError` is raised. The default value for *signed*
is ``False``.

Equivalent to::

def to_bytes(n, length, byteorder, signed=False):
if byteorder == 'little':
order = range(length)
elif byteorder == 'big':
order = reversed(range(length))
else:
raise ValueError("byteorder must be either 'little' or 'big'")

return bytes((n >> i*8) & 0xff for i in order)

.. versionadded:: 3.2

.. classmethod:: int.from_bytes(bytes, byteorder, *, signed=False)
Expand Down Expand Up @@ -559,6 +571,22 @@ class`. In addition, it provides a few more methods:
The *signed* argument indicates whether two's complement is used to
represent the integer.

Equivalent to::

def from_bytes(bytes, byteorder, signed=False):
if byteorder == 'little':
little_ordered = list(bytes)
elif byteorder == 'big':
little_ordered = list(reversed(bytes))
else:
raise ValueError("byteorder must be either 'little' or 'big'")

n = sum(b << i*8 for i, b in enumerate(little_ordered))
if signed and little_ordered and (little_ordered[-1] & 0x80):
n -= 1 << 8*len(little_ordered)

return n

.. versionadded:: 3.2

.. method:: int.as_integer_ratio()
Expand Down
42 changes: 42 additions & 0 deletions Lib/test/test_long.py
Original file line number Diff line number Diff line change
Expand Up @@ -1103,6 +1103,13 @@ def test_round(self):

def test_to_bytes(self):
def check(tests, byteorder, signed=False):
def equivalent_python(n, length, byteorder, signed=False):
if byteorder == 'little':
order = range(length)
elif byteorder == 'big':
order = reversed(range(length))
return bytes((n >> i*8) & 0xff for i in order)

for test, expected in tests.items():
try:
self.assertEqual(
Expand All @@ -1113,6 +1120,18 @@ def check(tests, byteorder, signed=False):
"failed to convert {0} with byteorder={1} and signed={2}"
.format(test, byteorder, signed)) from err

try:
self.assertEqual(
equivalent_python(
test, len(expected), byteorder, signed=signed),
expected
)
except Exception as err:
raise AssertionError(
"Code equivalent from docs is not equivalent for "
"conversion of {0} with byteorder byteorder={1} and "
"signed={2}".format(test, byteorder, signed)) from err

# Convert integers to signed big-endian byte arrays.
tests1 = {
0: b'\x00',
Expand Down Expand Up @@ -1202,6 +1221,18 @@ def check(tests, byteorder, signed=False):

def test_from_bytes(self):
def check(tests, byteorder, signed=False):
def equivalent_python(byte_array, byteorder, signed=False):
if byteorder == 'little':
little_ordered = list(byte_array)
elif byteorder == 'big':
little_ordered = list(reversed(byte_array))

n = sum(b << i*8 for i, b in enumerate(little_ordered))
if signed and little_ordered and (little_ordered[-1] & 0x80):
n -= 1 << 8*len(little_ordered)

return n

for test, expected in tests.items():
try:
self.assertEqual(
Expand All @@ -1212,6 +1243,17 @@ def check(tests, byteorder, signed=False):
"failed to convert {0} with byteorder={1!r} and signed={2}"
.format(test, byteorder, signed)) from err

try:
self.assertEqual(
equivalent_python(test, byteorder, signed=signed),
expected
)
except Exception as err:
raise AssertionError(
"Code equivalent from docs is not equivalent for "
"conversion of {0} with byteorder={1!r} and signed={2}"
.format(test, byteorder, signed)) from err

# Convert signed big-endian byte arrays to integers.
tests1 = {
b'': 0,
Expand Down
1 change: 1 addition & 0 deletions Misc/ACKS
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,7 @@ Mitch Chapman
Matt Chaput
William Chargin
Yogesh Chaudhari
Gautam Chaudhuri
David Chaum
Nicolas Chauvat
Jerry Chen
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Added code equivalents for the :meth:`int.to_bytes` and :meth:`int.from_bytes`
methods, as well as tests ensuring that these code equivalents are valid.

0 comments on commit ad0a8a9

Please sign in to comment.