diff options
author | Gautam Chaudhuri <gautam.chaudhuri.1803@gmail.com> | 2021-08-15 11:29:05 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-08-15 11:29:05 (GMT) |
commit | ad0a8a9c629a7a0fa306fbdf019be63c701a8028 (patch) | |
tree | b9a3bb5d459ffa6934ba402c5c121448afebed64 | |
parent | ed524b4569b1e4a166886c880018418d46284378 (diff) | |
download | cpython-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.rst | 28 | ||||
-rw-r--r-- | Lib/test/test_long.py | 42 | ||||
-rw-r--r-- | Misc/ACKS | 1 | ||||
-rw-r--r-- | Misc/NEWS.d/next/Documentation/2021-08-13-20-17-59.bpo-16580.MZ_iK9.rst | 2 |
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, @@ -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. |