From f8ce5fd6e596a57e498337f9e7423c36efe1c9c4 Mon Sep 17 00:00:00 2001 From: Gautam Chaudhuri Date: Wed, 11 Aug 2021 12:38:24 +0100 Subject: [PATCH 1/2] 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 --- Doc/library/stdtypes.rst | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst index d6eff144cc..acc9994eee 100644 --- a/Doc/library/stdtypes.rst +++ b/Doc/library/stdtypes.rst @@ -529,6 +529,15 @@ 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)) + return bytes((n >> i*8) & 0xff for i in order) + .. versionadded:: 3.2 .. classmethod:: int.from_bytes(bytes, byteorder, *, signed=False) @@ -559,6 +568,23 @@ 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() -- 2.32.0 From b430e64b175b0c3f740e4ea37c2aea874b4b3846 Mon Sep 17 00:00:00 2001 From: Gautam Chaudhuri Date: Wed, 11 Aug 2021 13:26:51 +0100 Subject: [PATCH 2/2] add code equiv. tests for to_bytes and from_bytes Added tests for the code equivalents for int.to_butes and int.from_bytes writen in the documentation. Based on woparry's patch[1] from the issue thread[2]. [1]: https://bugs.python.org/file30372/issue16580.patch [2]: https://bugs.python.org/issue16580 --- Lib/test/test_long.py | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/Lib/test/test_long.py b/Lib/test/test_long.py index c97842b5bf..fe5611af29 100644 --- a/Lib/test/test_long.py +++ b/Lib/test/test_long.py @@ -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( @@ -1113,6 +1120,16 @@ 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', @@ -1202,6 +1219,20 @@ 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)) + 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 + for test, expected in tests.items(): try: self.assertEqual( @@ -1212,6 +1243,16 @@ 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, -- 2.32.0