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