Copy reduce() to _functools so to have functools.reduce() not raise a warning
from usage under -3.
This commit is contained in:
parent
c1b76e4aaa
commit
83e818415a
|
@ -7,8 +7,7 @@
|
||||||
# Copyright (C) 2006 Python Software Foundation.
|
# Copyright (C) 2006 Python Software Foundation.
|
||||||
# See C source code for _functools credits/copyright
|
# See C source code for _functools credits/copyright
|
||||||
|
|
||||||
from _functools import partial
|
from _functools import partial, reduce
|
||||||
from __builtin__ import reduce
|
|
||||||
|
|
||||||
# update_wrapper() and wraps() are tools to help write
|
# update_wrapper() and wraps() are tools to help write
|
||||||
# wrapper functions that can handle naive introspection
|
# wrapper functions that can handle naive introspection
|
||||||
|
|
|
@ -267,6 +267,48 @@ class TestWraps(TestUpdateWrapper):
|
||||||
self.assertEqual(wrapper.dict_attr, f.dict_attr)
|
self.assertEqual(wrapper.dict_attr, f.dict_attr)
|
||||||
|
|
||||||
|
|
||||||
|
class TestReduce(unittest.TestCase):
|
||||||
|
|
||||||
|
def test_reduce(self):
|
||||||
|
class Squares:
|
||||||
|
|
||||||
|
def __init__(self, max):
|
||||||
|
self.max = max
|
||||||
|
self.sofar = []
|
||||||
|
|
||||||
|
def __len__(self): return len(self.sofar)
|
||||||
|
|
||||||
|
def __getitem__(self, i):
|
||||||
|
if not 0 <= i < self.max: raise IndexError
|
||||||
|
n = len(self.sofar)
|
||||||
|
while n <= i:
|
||||||
|
self.sofar.append(n*n)
|
||||||
|
n += 1
|
||||||
|
return self.sofar[i]
|
||||||
|
|
||||||
|
reduce = functools.reduce
|
||||||
|
self.assertEqual(reduce(lambda x, y: x+y, ['a', 'b', 'c'], ''), 'abc')
|
||||||
|
self.assertEqual(
|
||||||
|
reduce(lambda x, y: x+y, [['a', 'c'], [], ['d', 'w']], []),
|
||||||
|
['a','c','d','w']
|
||||||
|
)
|
||||||
|
self.assertEqual(reduce(lambda x, y: x*y, range(2,8), 1), 5040)
|
||||||
|
self.assertEqual(
|
||||||
|
reduce(lambda x, y: x*y, range(2,21), 1L),
|
||||||
|
2432902008176640000L
|
||||||
|
)
|
||||||
|
self.assertEqual(reduce(lambda x, y: x+y, Squares(10)), 285)
|
||||||
|
self.assertEqual(reduce(lambda x, y: x+y, Squares(10), 0), 285)
|
||||||
|
self.assertEqual(reduce(lambda x, y: x+y, Squares(0), 0), 0)
|
||||||
|
self.assertRaises(TypeError, reduce)
|
||||||
|
self.assertRaises(TypeError, reduce, 42, 42)
|
||||||
|
self.assertRaises(TypeError, reduce, 42, 42, 42)
|
||||||
|
self.assertEqual(reduce(42, "1"), "1") # func is never called with one item
|
||||||
|
self.assertEqual(reduce(42, "", "1"), "1") # func is never called with one item
|
||||||
|
self.assertRaises(TypeError, reduce, 42, (42, 42))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def test_main(verbose=None):
|
def test_main(verbose=None):
|
||||||
import sys
|
import sys
|
||||||
|
@ -275,7 +317,8 @@ def test_main(verbose=None):
|
||||||
TestPartialSubclass,
|
TestPartialSubclass,
|
||||||
TestPythonPartial,
|
TestPythonPartial,
|
||||||
TestUpdateWrapper,
|
TestUpdateWrapper,
|
||||||
TestWraps
|
TestWraps,
|
||||||
|
TestReduce,
|
||||||
)
|
)
|
||||||
test_support.run_unittest(*test_classes)
|
test_support.run_unittest(*test_classes)
|
||||||
|
|
||||||
|
|
|
@ -41,6 +41,9 @@ Core and Builtins
|
||||||
Library
|
Library
|
||||||
-------
|
-------
|
||||||
|
|
||||||
|
- Copied the implementation of reduce() to _functools.reduce() to have a
|
||||||
|
version that did not raise a DeprecationWarning under -3.
|
||||||
|
|
||||||
- Issue #3205: When iterating over a BZ2File fails allocating memory, raise
|
- Issue #3205: When iterating over a BZ2File fails allocating memory, raise
|
||||||
a MemoryError rather than silently stop the iteration.
|
a MemoryError rather than silently stop the iteration.
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,84 @@
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* reduce() *************************************************************/
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
functools_reduce(PyObject *self, PyObject *args)
|
||||||
|
{
|
||||||
|
PyObject *seq, *func, *result = NULL, *it;
|
||||||
|
|
||||||
|
if (!PyArg_UnpackTuple(args, "reduce", 2, 3, &func, &seq, &result))
|
||||||
|
return NULL;
|
||||||
|
if (result != NULL)
|
||||||
|
Py_INCREF(result);
|
||||||
|
|
||||||
|
it = PyObject_GetIter(seq);
|
||||||
|
if (it == NULL) {
|
||||||
|
PyErr_SetString(PyExc_TypeError,
|
||||||
|
"reduce() arg 2 must support iteration");
|
||||||
|
Py_XDECREF(result);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((args = PyTuple_New(2)) == NULL)
|
||||||
|
goto Fail;
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
PyObject *op2;
|
||||||
|
|
||||||
|
if (args->ob_refcnt > 1) {
|
||||||
|
Py_DECREF(args);
|
||||||
|
if ((args = PyTuple_New(2)) == NULL)
|
||||||
|
goto Fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
op2 = PyIter_Next(it);
|
||||||
|
if (op2 == NULL) {
|
||||||
|
if (PyErr_Occurred())
|
||||||
|
goto Fail;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result == NULL)
|
||||||
|
result = op2;
|
||||||
|
else {
|
||||||
|
PyTuple_SetItem(args, 0, result);
|
||||||
|
PyTuple_SetItem(args, 1, op2);
|
||||||
|
if ((result = PyEval_CallObject(func, args)) == NULL)
|
||||||
|
goto Fail;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Py_DECREF(args);
|
||||||
|
|
||||||
|
if (result == NULL)
|
||||||
|
PyErr_SetString(PyExc_TypeError,
|
||||||
|
"reduce() of empty sequence with no initial value");
|
||||||
|
|
||||||
|
Py_DECREF(it);
|
||||||
|
return result;
|
||||||
|
|
||||||
|
Fail:
|
||||||
|
Py_XDECREF(args);
|
||||||
|
Py_XDECREF(result);
|
||||||
|
Py_DECREF(it);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
PyDoc_STRVAR(reduce_doc,
|
||||||
|
"reduce(function, sequence[, initial]) -> value\n\
|
||||||
|
\n\
|
||||||
|
Apply a function of two arguments cumulatively to the items of a sequence,\n\
|
||||||
|
from left to right, so as to reduce the sequence to a single value.\n\
|
||||||
|
For example, reduce(lambda x, y: x+y, [1, 2, 3, 4, 5]) calculates\n\
|
||||||
|
((((1+2)+3)+4)+5). If initial is present, it is placed before the items\n\
|
||||||
|
of the sequence in the calculation, and serves as a default when the\n\
|
||||||
|
sequence is empty.");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* partial object **********************************************************/
|
/* partial object **********************************************************/
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
@ -247,6 +325,7 @@ PyDoc_STRVAR(module_doc,
|
||||||
"Tools that operate on functions.");
|
"Tools that operate on functions.");
|
||||||
|
|
||||||
static PyMethodDef module_methods[] = {
|
static PyMethodDef module_methods[] = {
|
||||||
|
{"reduce", functools_reduce, METH_VARARGS, reduce_doc},
|
||||||
{NULL, NULL} /* sentinel */
|
{NULL, NULL} /* sentinel */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue