Index: third_party/google-endpoints/past/builtins/noniterators.py |
diff --git a/third_party/google-endpoints/past/builtins/noniterators.py b/third_party/google-endpoints/past/builtins/noniterators.py |
new file mode 100644 |
index 0000000000000000000000000000000000000000..66a4a8a57513e23af48c779b11a2380cd098a46c |
--- /dev/null |
+++ b/third_party/google-endpoints/past/builtins/noniterators.py |
@@ -0,0 +1,273 @@ |
+""" |
+This module is designed to be used as follows:: |
+ |
+ from past.builtins.noniterators import filter, map, range, reduce, zip |
+ |
+And then, for example:: |
+ |
+ assert isinstance(range(5), list) |
+ |
+The list-producing functions this brings in are:: |
+ |
+- ``filter`` |
+- ``map`` |
+- ``range`` |
+- ``reduce`` |
+- ``zip`` |
+ |
+""" |
+ |
+from __future__ import division, absolute_import, print_function |
+ |
+from itertools import chain, starmap |
+import itertools # since zip_longest doesn't exist on Py2 |
+from past.types import basestring |
+from past.utils import PY3 |
+ |
+ |
+def flatmap(f, items): |
+ return chain.from_iterable(map(f, items)) |
+ |
+ |
+if PY3: |
+ import builtins |
+ |
+ # list-producing versions of the major Python iterating functions |
+ def oldfilter(*args): |
+ """ |
+ filter(function or None, sequence) -> list, tuple, or string |
+ |
+ Return those items of sequence for which function(item) is true. |
+ If function is None, return the items that are true. If sequence |
+ is a tuple or string, return the same type, else return a list. |
+ """ |
+ mytype = type(args[1]) |
+ if isinstance(args[1], basestring): |
+ return mytype().join(builtins.filter(*args)) |
+ elif isinstance(args[1], (tuple, list)): |
+ return mytype(builtins.filter(*args)) |
+ else: |
+ # Fall back to list. Is this the right thing to do? |
+ return list(builtins.filter(*args)) |
+ |
+ # This is surprisingly difficult to get right. For example, the |
+ # solutions here fail with the test cases in the docstring below: |
+ # http://stackoverflow.com/questions/8072755/ |
+ def oldmap(func, *iterables): |
+ """ |
+ map(function, sequence[, sequence, ...]) -> list |
+ |
+ Return a list of the results of applying the function to the |
+ items of the argument sequence(s). If more than one sequence is |
+ given, the function is called with an argument list consisting of |
+ the corresponding item of each sequence, substituting None for |
+ missing values when not all sequences have the same length. If |
+ the function is None, return a list of the items of the sequence |
+ (or a list of tuples if more than one sequence). |
+ |
+ Test cases: |
+ >>> oldmap(None, 'hello world') |
+ ['h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd'] |
+ |
+ >>> oldmap(None, range(4)) |
+ [0, 1, 2, 3] |
+ |
+ More test cases are in past.tests.test_builtins. |
+ """ |
+ zipped = itertools.zip_longest(*iterables) |
+ l = list(zipped) |
+ if len(l) == 0: |
+ return [] |
+ if func is None: |
+ result = l |
+ else: |
+ result = list(starmap(func, l)) |
+ |
+ # Inspect to see whether it's a simple sequence of tuples |
+ try: |
+ if max([len(item) for item in result]) == 1: |
+ return list(chain.from_iterable(result)) |
+ # return list(flatmap(func, result)) |
+ except TypeError as e: |
+ # Simple objects like ints have no len() |
+ pass |
+ return result |
+ |
+ ############################ |
+ ### For reference, the source code for Py2.7 map function: |
+ # static PyObject * |
+ # builtin_map(PyObject *self, PyObject *args) |
+ # { |
+ # typedef struct { |
+ # PyObject *it; /* the iterator object */ |
+ # int saw_StopIteration; /* bool: did the iterator end? */ |
+ # } sequence; |
+ # |
+ # PyObject *func, *result; |
+ # sequence *seqs = NULL, *sqp; |
+ # Py_ssize_t n, len; |
+ # register int i, j; |
+ # |
+ # n = PyTuple_Size(args); |
+ # if (n < 2) { |
+ # PyErr_SetString(PyExc_TypeError, |
+ # "map() requires at least two args"); |
+ # return NULL; |
+ # } |
+ # |
+ # func = PyTuple_GetItem(args, 0); |
+ # n--; |
+ # |
+ # if (func == Py_None) { |
+ # if (PyErr_WarnPy3k("map(None, ...) not supported in 3.x; " |
+ # "use list(...)", 1) < 0) |
+ # return NULL; |
+ # if (n == 1) { |
+ # /* map(None, S) is the same as list(S). */ |
+ # return PySequence_List(PyTuple_GetItem(args, 1)); |
+ # } |
+ # } |
+ # |
+ # /* Get space for sequence descriptors. Must NULL out the iterator |
+ # * pointers so that jumping to Fail_2 later doesn't see trash. |
+ # */ |
+ # if ((seqs = PyMem_NEW(sequence, n)) == NULL) { |
+ # PyErr_NoMemory(); |
+ # return NULL; |
+ # } |
+ # for (i = 0; i < n; ++i) { |
+ # seqs[i].it = (PyObject*)NULL; |
+ # seqs[i].saw_StopIteration = 0; |
+ # } |
+ # |
+ # /* Do a first pass to obtain iterators for the arguments, and set len |
+ # * to the largest of their lengths. |
+ # */ |
+ # len = 0; |
+ # for (i = 0, sqp = seqs; i < n; ++i, ++sqp) { |
+ # PyObject *curseq; |
+ # Py_ssize_t curlen; |
+ # |
+ # /* Get iterator. */ |
+ # curseq = PyTuple_GetItem(args, i+1); |
+ # sqp->it = PyObject_GetIter(curseq); |
+ # if (sqp->it == NULL) { |
+ # static char errmsg[] = |
+ # "argument %d to map() must support iteration"; |
+ # char errbuf[sizeof(errmsg) + 25]; |
+ # PyOS_snprintf(errbuf, sizeof(errbuf), errmsg, i+2); |
+ # PyErr_SetString(PyExc_TypeError, errbuf); |
+ # goto Fail_2; |
+ # } |
+ # |
+ # /* Update len. */ |
+ # curlen = _PyObject_LengthHint(curseq, 8); |
+ # if (curlen > len) |
+ # len = curlen; |
+ # } |
+ # |
+ # /* Get space for the result list. */ |
+ # if ((result = (PyObject *) PyList_New(len)) == NULL) |
+ # goto Fail_2; |
+ # |
+ # /* Iterate over the sequences until all have stopped. */ |
+ # for (i = 0; ; ++i) { |
+ # PyObject *alist, *item=NULL, *value; |
+ # int numactive = 0; |
+ # |
+ # if (func == Py_None && n == 1) |
+ # alist = NULL; |
+ # else if ((alist = PyTuple_New(n)) == NULL) |
+ # goto Fail_1; |
+ # |
+ # for (j = 0, sqp = seqs; j < n; ++j, ++sqp) { |
+ # if (sqp->saw_StopIteration) { |
+ # Py_INCREF(Py_None); |
+ # item = Py_None; |
+ # } |
+ # else { |
+ # item = PyIter_Next(sqp->it); |
+ # if (item) |
+ # ++numactive; |
+ # else { |
+ # if (PyErr_Occurred()) { |
+ # Py_XDECREF(alist); |
+ # goto Fail_1; |
+ # } |
+ # Py_INCREF(Py_None); |
+ # item = Py_None; |
+ # sqp->saw_StopIteration = 1; |
+ # } |
+ # } |
+ # if (alist) |
+ # PyTuple_SET_ITEM(alist, j, item); |
+ # else |
+ # break; |
+ # } |
+ # |
+ # if (!alist) |
+ # alist = item; |
+ # |
+ # if (numactive == 0) { |
+ # Py_DECREF(alist); |
+ # break; |
+ # } |
+ # |
+ # if (func == Py_None) |
+ # value = alist; |
+ # else { |
+ # value = PyEval_CallObject(func, alist); |
+ # Py_DECREF(alist); |
+ # if (value == NULL) |
+ # goto Fail_1; |
+ # } |
+ # if (i >= len) { |
+ # int status = PyList_Append(result, value); |
+ # Py_DECREF(value); |
+ # if (status < 0) |
+ # goto Fail_1; |
+ # } |
+ # else if (PyList_SetItem(result, i, value) < 0) |
+ # goto Fail_1; |
+ # } |
+ # |
+ # if (i < len && PyList_SetSlice(result, i, len, NULL) < 0) |
+ # goto Fail_1; |
+ # |
+ # goto Succeed; |
+ # |
+ # Fail_1: |
+ # Py_DECREF(result); |
+ # Fail_2: |
+ # result = NULL; |
+ # Succeed: |
+ # assert(seqs); |
+ # for (i = 0; i < n; ++i) |
+ # Py_XDECREF(seqs[i].it); |
+ # PyMem_DEL(seqs); |
+ # return result; |
+ # } |
+ |
+ def oldrange(*args, **kwargs): |
+ return list(builtins.range(*args, **kwargs)) |
+ |
+ def oldzip(*args, **kwargs): |
+ return list(builtins.zip(*args, **kwargs)) |
+ |
+ filter = oldfilter |
+ map = oldmap |
+ range = oldrange |
+ from functools import reduce |
+ zip = oldzip |
+ __all__ = ['filter', 'map', 'range', 'reduce', 'zip'] |
+ |
+else: |
+ import __builtin__ |
+ # Python 2-builtin ranges produce lists |
+ filter = __builtin__.filter |
+ map = __builtin__.map |
+ range = __builtin__.range |
+ reduce = __builtin__.reduce |
+ zip = __builtin__.zip |
+ __all__ = [] |
+ |