Skip to content

Commit a463686

Browse files
committed
Add initial attempt at int.to_bytes() and int.from_bytes() (issue #85)
1 parent d9cd16a commit a463686

File tree

2 files changed

+74
-0
lines changed

2 files changed

+74
-0
lines changed

docs/whatsnew.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ What's new in version 0.12.5
1313
(issue #81). It still converts ``obj.next()`` method calls to
1414
``next(obj)`` correctly.
1515
- Add :ref:`compatible-idioms` from Ed Schofield's PyConAU 2014 talk.
16+
- Add ``int.to_bytes()`` and ``int.from_bytes()`` (issue #85)
1617
- Add ``future.utils.raise_from`` as an equivalent to Py3's ``raise ... from ...`` syntax (issue #86).
1718

1819

future/types/newint.py

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
"""
88
from __future__ import division
99

10+
import struct
11+
1012
from future.types.newbytes import newbytes
1113
from future.utils import PY3, isint, istext, isbytes, with_metaclass
1214

@@ -274,5 +276,76 @@ def __bool__(self):
274276
def __native__(self):
275277
return long(self)
276278

279+
def to_bytes(self, length, byteorder='big', signed=False):
280+
"""
281+
Return an array of bytes representing an integer.
282+
283+
The integer is represented using length bytes. An OverflowError is
284+
raised if the integer is not representable with the given number of
285+
bytes.
286+
287+
The byteorder argument determines the byte order used to represent the
288+
integer. If byteorder is 'big', the most significant byte is at the
289+
beginning of the byte array. If byteorder is 'little', the most
290+
significant byte is at the end of the byte array. To request the native
291+
byte order of the host system, use `sys.byteorder' as the byte order value.
292+
293+
The signed keyword-only argument determines whether two's complement is
294+
used to represent the integer. If signed is False and a negative integer
295+
is given, an OverflowError is raised.
296+
"""
297+
if signed:
298+
raise NotImplementedError("Not yet implemented. Please contribute a patch at http://python-future.org")
299+
else:
300+
if self < 0:
301+
raise OverflowError("can't convert negative int to unsigned")
302+
num = self
303+
if byteorder not in ('little', 'big'):
304+
raise ValueError("byteorder must be either 'little' or 'big'")
305+
if length < 0:
306+
raise ValueError("length argument must be non-negative")
307+
if length == 0 and num == 0:
308+
return bytes()
309+
h = b'%x' % num
310+
s = newbytes((b'0'*(len(h) % 2) + h).zfill(length*2).decode('hex'))
311+
if len(s) > length:
312+
raise OverflowError("int too big to convert")
313+
return s if byteorder == 'big' else s[::-1]
314+
315+
@classmethod
316+
def from_bytes(cls, bytes, byteorder='big', signed=False):
317+
"""
318+
Return the integer represented by the given array of bytes.
319+
320+
The bytes argument must either support the buffer protocol or be an
321+
iterable object producing bytes. Bytes and bytearray are examples of
322+
built-in objects that support the buffer protocol.
323+
324+
The byteorder argument determines the byte order used to represent the
325+
integer. If byteorder is 'big', the most significant byte is at the
326+
beginning of the byte array. If byteorder is 'little', the most
327+
significant byte is at the end of the byte array. To request the native
328+
byte order of the host system, use `sys.byteorder' as the byte order value.
329+
330+
The signed keyword-only argument indicates whether two's complement is
331+
used to represent the integer.
332+
"""
333+
if signed:
334+
raise NotImplementedError("Not yet implemented. Please contribute a patch at http://python-future.org")
335+
if byteorder not in ('little', 'big'):
336+
raise ValueError("byteorder must be either 'little' or 'big'")
337+
b = bytes if byteorder == 'big' else bytes[::-1]
338+
if len(b) == 0:
339+
b = b'\x00'
340+
num = int(b.encode('hex'), 16)
341+
return cls(num)
342+
343+
344+
# def _twos_comp(val, bits):
345+
# """compute the 2's compliment of int value val"""
346+
# if( (val&(1<<(bits-1))) != 0 ):
347+
# val = val - (1<<bits)
348+
# return val
349+
277350

278351
__all__ = ['newint']

0 commit comments

Comments
 (0)