summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGautam Chaudhuri <gautam.chaudhuri.1803@gmail.com>2021-08-15 11:29:05 (GMT)
committerGitHub <noreply@github.com>2021-08-15 11:29:05 (GMT)
commitad0a8a9c629a7a0fa306fbdf019be63c701a8028 (patch)
treeb9a3bb5d459ffa6934ba402c5c121448afebed64
parented524b4569b1e4a166886c880018418d46284378 (diff)
downloadcpython-ad0a8a9c629a7a0fa306fbdf019be63c701a8028.zip
cpython-ad0a8a9c629a7a0fa306fbdf019be63c701a8028.tar.gz
cpython-ad0a8a9c629a7a0fa306fbdf019be63c701a8028.tar.bz2
bpo-16580: [doc] Add examples to int.to_bytes and int.from_bytes (GH-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 <dickinsm@gmail.com>
-rw-r--r--Doc/library/stdtypes.rst28
-rw-r--r--Lib/test/test_long.py42
-rw-r--r--Misc/ACKS1
-rw-r--r--Misc/NEWS.d/next/Documentation/2021-08-13-20-17-59.bpo-16580.MZ_iK9.rst2
4 files changed, 73 insertions, 0 deletions
diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst
index d6eff14..f0a3eda 100644
--- a/Doc/library/stdtypes.rst
+++ b/Doc/library/stdtypes.rst
@@ -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)
@@ -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()
diff --git a/Lib/test/test_long.py b/Lib/test/test_long.py
index c97842b..1de75bf 100644
--- a/Lib/test/test_long.py
+++ b/Lib/test/test_long.py
@@ -1103,6 +1103,13 @@ class LongTest(unittest.TestCase):
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(
@@ -1113,6 +1120,18 @@ class LongTest(unittest.TestCase):
"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',
@@ -1202,6 +1221,18 @@ class LongTest(unittest.TestCase):
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(
@@ -1212,6 +1243,17 @@ class LongTest(unittest.TestCase):
"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,
diff --git a/Misc/ACKS b/Misc/ACKS
index 7829fee..9123350 100644
--- a/Misc/ACKS
+++ b/Misc/ACKS
@@ -306,6 +306,7 @@ Mitch Chapman
Matt Chaput
William Chargin
Yogesh Chaudhari
+Gautam Chaudhuri
David Chaum
Nicolas Chauvat
Jerry Chen
diff --git a/Misc/NEWS.d/next/Documentation/2021-08-13-20-17-59.bpo-16580.MZ_iK9.rst b/Misc/NEWS.d/next/Documentation/2021-08-13-20-17-59.bpo-16580.MZ_iK9.rst
new file mode 100644
index 0000000..edeca6f
--- /dev/null
+++ b/Misc/NEWS.d/next/Documentation/2021-08-13-20-17-59.bpo-16580.MZ_iK9.rst
@@ -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.