1"""
2Backport of Python 3's int, based on Py2's long.
3
4They are very similar. The most notable difference is:
5
6- representation: trailing L in Python 2 removed in Python 3
7"""
8from __future__ import division
9
10import struct
11
12from future.types.newbytes import newbytes
13from future.types.newobject import newobject
14from future.utils import PY3, isint, istext, isbytes, with_metaclass, native
15
16
17if PY3:
18    long = int
19    from collections.abc import Iterable
20else:
21    from collections import Iterable
22
23
24class BaseNewInt(type):
25    def __instancecheck__(cls, instance):
26        if cls == newint:
27            # Special case for Py2 short or long int
28            return isinstance(instance, (int, long))
29        else:
30            return issubclass(instance.__class__, cls)
31
32
33class newint(with_metaclass(BaseNewInt, long)):
34    """
35    A backport of the Python 3 int object to Py2
36    """
37    def __new__(cls, x=0, base=10):
38        """
39        From the Py3 int docstring:
40
41        |  int(x=0) -> integer
42        |  int(x, base=10) -> integer
43        |
44        |  Convert a number or string to an integer, or return 0 if no
45        |  arguments are given.  If x is a number, return x.__int__().  For
46        |  floating point numbers, this truncates towards zero.
47        |
48        |  If x is not a number or if base is given, then x must be a string,
49        |  bytes, or bytearray instance representing an integer literal in the
50        |  given base.  The literal can be preceded by '+' or '-' and be
51        |  surrounded by whitespace.  The base defaults to 10.  Valid bases are
52        |  0 and 2-36. Base 0 means to interpret the base from the string as an
53        |  integer literal.
54        |  >>> int('0b100', base=0)
55        |  4
56
57        """
58        try:
59            val = x.__int__()
60        except AttributeError:
61            val = x
62        else:
63            if not isint(val):
64                raise TypeError('__int__ returned non-int ({0})'.format(
65                    type(val)))
66
67        if base != 10:
68            # Explicit base
69            if not (istext(val) or isbytes(val) or isinstance(val, bytearray)):
70                raise TypeError(
71                    "int() can't convert non-string with explicit base")
72            try:
73                return super(newint, cls).__new__(cls, val, base)
74            except TypeError:
75                return super(newint, cls).__new__(cls, newbytes(val), base)
76        # After here, base is 10
77        try:
78            return super(newint, cls).__new__(cls, val)
79        except TypeError:
80            # Py2 long doesn't handle bytearray input with an explicit base, so
81            # handle this here.
82            # Py3: int(bytearray(b'10'), 2) == 2
83            # Py2: int(bytearray(b'10'), 2) == 2 raises TypeError
84            # Py2: long(bytearray(b'10'), 2) == 2 raises TypeError
85            try:
86                return super(newint, cls).__new__(cls, newbytes(val))
87            except:
88                raise TypeError("newint argument must be a string or a number,"
89                                "not '{0}'".format(type(val)))
90
91    def __repr__(self):
92        """
93        Without the L suffix
94        """
95        value = super(newint, self).__repr__()
96        assert value[-1] == 'L'
97        return value[:-1]
98
99    def __add__(self, other):
100        value = super(newint, self).__add__(other)
101        if value is NotImplemented:
102            return long(self) + other
103        return newint(value)
104
105    def __radd__(self, other):
106        value = super(newint, self).__radd__(other)
107        if value is NotImplemented:
108            return other + long(self)
109        return newint(value)
110
111    def __sub__(self, other):
112        value = super(newint, self).__sub__(other)
113        if value is NotImplemented:
114            return long(self) - other
115        return newint(value)
116
117    def __rsub__(self, other):
118        value = super(newint, self).__rsub__(other)
119        if value is NotImplemented:
120            return other - long(self)
121        return newint(value)
122
123    def __mul__(self, other):
124        value = super(newint, self).__mul__(other)
125        if isint(value):
126            return newint(value)
127        elif value is NotImplemented:
128            return long(self) * other
129        return value
130
131    def __rmul__(self, other):
132        value = super(newint, self).__rmul__(other)
133        if isint(value):
134            return newint(value)
135        elif value is NotImplemented:
136            return other * long(self)
137        return value
138
139    def __div__(self, other):
140        # We override this rather than e.g. relying on object.__div__ or
141        # long.__div__ because we want to wrap the value in a newint()
142        # call if other is another int
143        value = long(self) / other
144        if isinstance(other, (int, long)):
145            return newint(value)
146        else:
147            return value
148
149    def __rdiv__(self, other):
150        value = other / long(self)
151        if isinstance(other, (int, long)):
152            return newint(value)
153        else:
154            return value
155
156    def __idiv__(self, other):
157        # long has no __idiv__ method. Use __itruediv__ and cast back to
158        # newint:
159        value = self.__itruediv__(other)
160        if isinstance(other, (int, long)):
161            return newint(value)
162        else:
163            return value
164
165    def __truediv__(self, other):
166        value = super(newint, self).__truediv__(other)
167        if value is NotImplemented:
168            value = long(self) / other
169        return value
170
171    def __rtruediv__(self, other):
172        return super(newint, self).__rtruediv__(other)
173
174    def __itruediv__(self, other):
175        # long has no __itruediv__ method
176        mylong = long(self)
177        mylong /= other
178        return mylong
179
180    def __floordiv__(self, other):
181        return newint(super(newint, self).__floordiv__(other))
182
183    def __rfloordiv__(self, other):
184        return newint(super(newint, self).__rfloordiv__(other))
185
186    def __ifloordiv__(self, other):
187        # long has no __ifloordiv__ method
188        mylong = long(self)
189        mylong //= other
190        return newint(mylong)
191
192    def __mod__(self, other):
193        value = super(newint, self).__mod__(other)
194        if value is NotImplemented:
195            return long(self) % other
196        return newint(value)
197
198    def __rmod__(self, other):
199        value = super(newint, self).__rmod__(other)
200        if value is NotImplemented:
201            return other % long(self)
202        return newint(value)
203
204    def __divmod__(self, other):
205        value = super(newint, self).__divmod__(other)
206        if value is NotImplemented:
207            mylong = long(self)
208            return (mylong // other, mylong % other)
209        return (newint(value[0]), newint(value[1]))
210
211    def __rdivmod__(self, other):
212        value = super(newint, self).__rdivmod__(other)
213        if value is NotImplemented:
214            mylong = long(self)
215            return (other // mylong, other % mylong)
216        return (newint(value[0]), newint(value[1]))
217
218    def __pow__(self, other):
219        value = super(newint, self).__pow__(other)
220        if value is NotImplemented:
221            return long(self) ** other
222        return newint(value)
223
224    def __rpow__(self, other):
225        value = super(newint, self).__rpow__(other)
226        if value is NotImplemented:
227            return other ** long(self)
228        return newint(value)
229
230    def __lshift__(self, other):
231        if not isint(other):
232            raise TypeError(
233                "unsupported operand type(s) for <<: '%s' and '%s'" %
234                (type(self).__name__, type(other).__name__))
235        return newint(super(newint, self).__lshift__(other))
236
237    def __rshift__(self, other):
238        if not isint(other):
239            raise TypeError(
240                "unsupported operand type(s) for >>: '%s' and '%s'" %
241                (type(self).__name__, type(other).__name__))
242        return newint(super(newint, self).__rshift__(other))
243
244    def __and__(self, other):
245        if not isint(other):
246            raise TypeError(
247                "unsupported operand type(s) for &: '%s' and '%s'" %
248                (type(self).__name__, type(other).__name__))
249        return newint(super(newint, self).__and__(other))
250
251    def __or__(self, other):
252        if not isint(other):
253            raise TypeError(
254                "unsupported operand type(s) for |: '%s' and '%s'" %
255                (type(self).__name__, type(other).__name__))
256        return newint(super(newint, self).__or__(other))
257
258    def __xor__(self, other):
259        if not isint(other):
260            raise TypeError(
261                "unsupported operand type(s) for ^: '%s' and '%s'" %
262                (type(self).__name__, type(other).__name__))
263        return newint(super(newint, self).__xor__(other))
264
265    def __neg__(self):
266        return newint(super(newint, self).__neg__())
267
268    def __pos__(self):
269        return newint(super(newint, self).__pos__())
270
271    def __abs__(self):
272        return newint(super(newint, self).__abs__())
273
274    def __invert__(self):
275        return newint(super(newint, self).__invert__())
276
277    def __int__(self):
278        return self
279
280    def __nonzero__(self):
281        return self.__bool__()
282
283    def __bool__(self):
284        """
285        So subclasses can override this, Py3-style
286        """
287        return super(newint, self).__nonzero__()
288
289    def __native__(self):
290        return long(self)
291
292    def to_bytes(self, length, byteorder='big', signed=False):
293        """
294        Return an array of bytes representing an integer.
295
296        The integer is represented using length bytes.  An OverflowError is
297        raised if the integer is not representable with the given number of
298        bytes.
299
300        The byteorder argument determines the byte order used to represent the
301        integer.  If byteorder is 'big', the most significant byte is at the
302        beginning of the byte array.  If byteorder is 'little', the most
303        significant byte is at the end of the byte array.  To request the native
304        byte order of the host system, use `sys.byteorder' as the byte order value.
305
306        The signed keyword-only argument determines whether two's complement is
307        used to represent the integer.  If signed is False and a negative integer
308        is given, an OverflowError is raised.
309        """
310        if length < 0:
311            raise ValueError("length argument must be non-negative")
312        if length == 0 and self == 0:
313            return newbytes()
314        if signed and self < 0:
315            bits = length * 8
316            num = (2**bits) + self
317            if num <= 0:
318                raise OverflowError("int too smal to convert")
319        else:
320            if self < 0:
321                raise OverflowError("can't convert negative int to unsigned")
322            num = self
323        if byteorder not in ('little', 'big'):
324            raise ValueError("byteorder must be either 'little' or 'big'")
325        h = b'%x' % num
326        s = newbytes((b'0'*(len(h) % 2) + h).zfill(length*2).decode('hex'))
327        if signed:
328            high_set = s[0] & 0x80
329            if self > 0 and high_set:
330                raise OverflowError("int too big to convert")
331            if self < 0 and not high_set:
332                raise OverflowError("int too small to convert")
333        if len(s) > length:
334            raise OverflowError("int too big to convert")
335        return s if byteorder == 'big' else s[::-1]
336
337    @classmethod
338    def from_bytes(cls, mybytes, byteorder='big', signed=False):
339        """
340        Return the integer represented by the given array of bytes.
341
342        The mybytes argument must either support the buffer protocol or be an
343        iterable object producing bytes.  Bytes and bytearray are examples of
344        built-in objects that support the buffer protocol.
345
346        The byteorder argument determines the byte order used to represent the
347        integer.  If byteorder is 'big', the most significant byte is at the
348        beginning of the byte array.  If byteorder is 'little', the most
349        significant byte is at the end of the byte array.  To request the native
350        byte order of the host system, use `sys.byteorder' as the byte order value.
351
352        The signed keyword-only argument indicates whether two's complement is
353        used to represent the integer.
354        """
355        if byteorder not in ('little', 'big'):
356            raise ValueError("byteorder must be either 'little' or 'big'")
357        if isinstance(mybytes, unicode):
358            raise TypeError("cannot convert unicode objects to bytes")
359        # mybytes can also be passed as a sequence of integers on Py3.
360        # Test for this:
361        elif isinstance(mybytes, Iterable):
362            mybytes = newbytes(mybytes)
363        b = mybytes if byteorder == 'big' else mybytes[::-1]
364        if len(b) == 0:
365            b = b'\x00'
366        # The encode() method has been disabled by newbytes, but Py2's
367        # str has it:
368        num = int(native(b).encode('hex'), 16)
369        if signed and (b[0] & 0x80):
370            num = num - (2 ** (len(b)*8))
371        return cls(num)
372
373
374# def _twos_comp(val, bits):
375#     """compute the 2's compliment of int value val"""
376#     if( (val&(1<<(bits-1))) != 0 ):
377#         val = val - (1<<bits)
378#     return val
379
380
381__all__ = ['newint']
382