/usr/lib/python2.7/dist-packages/future/types/newrange.py is in python-future 0.15.2-4ubuntu2.
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 | """
Nearly identical to xrange.py, by Dan Crosta, from
https://github.com/dcrosta/xrange.git
This is included here in the ``future`` package rather than pointed to as
a dependency because there is no package for ``xrange`` on PyPI. It is
also tweaked to appear like a regular Python 3 ``range`` object rather
than a Python 2 xrange.
From Dan Crosta's README:
"A pure-Python implementation of Python 2.7's xrange built-in, with
some features backported from the Python 3.x range built-in (which
replaced xrange) in that version."
Read more at
https://late.am/post/2012/06/18/what-the-heck-is-an-xrange
"""
from __future__ import absolute_import
from collections import Sequence, Iterator
from itertools import islice
from future.backports.misc import count # with step parameter on Py2.6
# For backward compatibility with python-future versions < 0.14.4:
_count = count
class newrange(Sequence):
"""
Pure-Python backport of Python 3's range object. See `the CPython
documentation for details:
<http://docs.python.org/py3k/library/functions.html#range>`_
"""
def __init__(self, *args):
if len(args) == 1:
start, stop, step = 0, args[0], 1
elif len(args) == 2:
start, stop, step = args[0], args[1], 1
elif len(args) == 3:
start, stop, step = args
else:
raise TypeError('range() requires 1-3 int arguments')
try:
start, stop, step = int(start), int(stop), int(step)
except ValueError:
raise TypeError('an integer is required')
if step == 0:
raise ValueError('range() arg 3 must not be zero')
elif step < 0:
stop = min(stop, start)
else:
stop = max(stop, start)
self._start = start
self._stop = stop
self._step = step
self._len = (stop - start) // step + bool((stop - start) % step)
@property
def start(self):
return self._start
@property
def stop(self):
return self._stop
@property
def step(self):
return self._step
def __repr__(self):
if self._step == 1:
return 'range(%d, %d)' % (self._start, self._stop)
return 'range(%d, %d, %d)' % (self._start, self._stop, self._step)
def __eq__(self, other):
return (isinstance(other, newrange) and
(self._len == 0 == other._len or
(self._start, self._step, self._len) ==
(other._start, other._step, self._len)))
def __len__(self):
return self._len
def index(self, value):
"""Return the 0-based position of integer `value` in
the sequence this range represents."""
diff = value - self._start
quotient, remainder = divmod(diff, self._step)
if remainder == 0 and 0 <= quotient < self._len:
return abs(quotient)
raise ValueError('%r is not in range' % value)
def count(self, value):
"""Return the number of ocurrences of integer `value`
in the sequence this range represents."""
# a value can occur exactly zero or one times
return int(value in self)
def __contains__(self, value):
"""Return ``True`` if the integer `value` occurs in
the sequence this range represents."""
try:
self.index(value)
return True
except ValueError:
return False
def __reversed__(self):
return iter(self[::-1])
def __getitem__(self, index):
"""Return the element at position ``index`` in the sequence
this range represents, or raise :class:`IndexError` if the
position is out of range."""
if isinstance(index, slice):
return self.__getitem_slice(index)
if index < 0:
# negative indexes access from the end
index = self._len + index
if index < 0 or index >= self._len:
raise IndexError('range object index out of range')
return self._start + index * self._step
def __getitem_slice(self, slce):
"""Return a range which represents the requested slce
of the sequence represented by this range.
"""
scaled_indices = (self._step * n for n in slce.indices(self._len))
start_offset, stop_offset, new_step = scaled_indices
return newrange(self._start + start_offset,
self._start + stop_offset,
new_step)
def __iter__(self):
"""Return an iterator which enumerates the elements of the
sequence this range represents."""
return range_iterator(self)
class range_iterator(Iterator):
"""An iterator for a :class:`range`.
"""
def __init__(self, range_):
self._stepper = islice(count(range_.start, range_.step), len(range_))
def __iter__(self):
return self
def next(self):
return next(self._stepper)
__all__ = ['newrange']
|