Index: third_party/google-endpoints/future/types/newrange.py |
diff --git a/third_party/google-endpoints/future/types/newrange.py b/third_party/google-endpoints/future/types/newrange.py |
new file mode 100644 |
index 0000000000000000000000000000000000000000..c190ba9e3da07df0b60c89ce5f85603b7ada0eec |
--- /dev/null |
+++ b/third_party/google-endpoints/future/types/newrange.py |
@@ -0,0 +1,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'] |