Kaydet (Commit) f16baebf authored tarafından Christian Heimes's avatar Christian Heimes

Merged revisions…

Merged revisions 61038,61042-61045,61047,61050,61053,61055-61056,61061-61062,61066,61068,61070,61083,61085,61092-61097,61103-61104,61110-61112,61114-61115,61117-61125 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/trunk

........
  r61118 | raymond.hettinger | 2008-02-28 23:30:42 +0100 (Thu, 28 Feb 2008) | 1 line

  Have itertools.chain() consume its inputs lazily instead of building a tuple of iterators at the outset.
........
  r61119 | raymond.hettinger | 2008-02-28 23:46:41 +0100 (Thu, 28 Feb 2008) | 1 line

  Add alternate constructor for itertools.chain().
........
  r61123 | mark.dickinson | 2008-02-29 03:16:37 +0100 (Fri, 29 Feb 2008) | 2 lines

  Add __format__ method to Decimal, to support PEP 3101
........
  r61124 | raymond.hettinger | 2008-02-29 03:21:48 +0100 (Fri, 29 Feb 2008) | 1 line

  Handle the repeat keyword argument for itertools.product().
........
  r61125 | mark.dickinson | 2008-02-29 04:29:17 +0100 (Fri, 29 Feb 2008) | 2 lines

  Fix docstring typo.
........
üst 5524089f
This diff is collapsed.
...@@ -610,6 +610,98 @@ class DecimalImplicitConstructionTest(unittest.TestCase): ...@@ -610,6 +610,98 @@ class DecimalImplicitConstructionTest(unittest.TestCase):
self.assertEqual(eval('Decimal(10)' + sym + 'E()'), self.assertEqual(eval('Decimal(10)' + sym + 'E()'),
'10' + rop + 'str') '10' + rop + 'str')
class DecimalFormatTest(unittest.TestCase):
'''Unit tests for the format function.'''
def test_formatting(self):
# triples giving a format, a Decimal, and the expected result
test_values = [
('e', '0E-15', '0e-15'),
('e', '2.3E-15', '2.3e-15'),
('e', '2.30E+2', '2.30e+2'), # preserve significant zeros
('e', '2.30000E-15', '2.30000e-15'),
('e', '1.23456789123456789e40', '1.23456789123456789e+40'),
('e', '1.5', '1.5e+0'),
('e', '0.15', '1.5e-1'),
('e', '0.015', '1.5e-2'),
('e', '0.0000000000015', '1.5e-12'),
('e', '15.0', '1.50e+1'),
('e', '-15', '-1.5e+1'),
('e', '0', '0e+0'),
('e', '0E1', '0e+1'),
('e', '0.0', '0e-1'),
('e', '0.00', '0e-2'),
('.6e', '0E-15', '0.000000e-9'),
('.6e', '0', '0.000000e+6'),
('.6e', '9.999999', '9.999999e+0'),
('.6e', '9.9999999', '1.000000e+1'),
('.6e', '-1.23e5', '-1.230000e+5'),
('.6e', '1.23456789e-3', '1.234568e-3'),
('f', '0', '0'),
('f', '0.0', '0.0'),
('f', '0E-2', '0.00'),
('f', '0.00E-8', '0.0000000000'),
('f', '0E1', '0'), # loses exponent information
('f', '3.2E1', '32'),
('f', '3.2E2', '320'),
('f', '3.20E2', '320'),
('f', '3.200E2', '320.0'),
('f', '3.2E-6', '0.0000032'),
('.6f', '0E-15', '0.000000'), # all zeros treated equally
('.6f', '0E1', '0.000000'),
('.6f', '0', '0.000000'),
('.0f', '0', '0'), # no decimal point
('.0f', '0e-2', '0'),
('.0f', '3.14159265', '3'),
('.1f', '3.14159265', '3.1'),
('.4f', '3.14159265', '3.1416'),
('.6f', '3.14159265', '3.141593'),
('.7f', '3.14159265', '3.1415926'), # round-half-even!
('.8f', '3.14159265', '3.14159265'),
('.9f', '3.14159265', '3.141592650'),
('g', '0', '0'),
('g', '0.0', '0.0'),
('g', '0E1', '0e+1'),
('G', '0E1', '0E+1'),
('g', '0E-5', '0.00000'),
('g', '0E-6', '0.000000'),
('g', '0E-7', '0e-7'),
('g', '-0E2', '-0e+2'),
('.0g', '3.14159265', '3'), # 0 sig fig -> 1 sig fig
('.1g', '3.14159265', '3'),
('.2g', '3.14159265', '3.1'),
('.5g', '3.14159265', '3.1416'),
('.7g', '3.14159265', '3.141593'),
('.8g', '3.14159265', '3.1415926'), # round-half-even!
('.9g', '3.14159265', '3.14159265'),
('.10g', '3.14159265', '3.14159265'), # don't pad
('%', '0E1', '0%'),
('%', '0E0', '0%'),
('%', '0E-1', '0%'),
('%', '0E-2', '0%'),
('%', '0E-3', '0.0%'),
('%', '0E-4', '0.00%'),
('.3%', '0', '0.000%'), # all zeros treated equally
('.3%', '0E10', '0.000%'),
('.3%', '0E-10', '0.000%'),
('.3%', '2.34', '234.000%'),
('.3%', '1.234567', '123.457%'),
('.0%', '1.23', '123%'),
('e', 'NaN', 'NaN'),
('f', '-NaN123', '-NaN123'),
('+g', 'NaN456', '+NaN456'),
('.3e', 'Inf', 'Infinity'),
('.16f', '-Inf', '-Infinity'),
('.0g', '-sNaN', '-sNaN'),
('', '1.00', '1.00'),
]
for fmt, d, result in test_values:
self.assertEqual(format(Decimal(d), fmt), result)
class DecimalArithmeticOperatorsTest(unittest.TestCase): class DecimalArithmeticOperatorsTest(unittest.TestCase):
'''Unit tests for all arithmetic operators, binary and unary.''' '''Unit tests for all arithmetic operators, binary and unary.'''
...@@ -1351,6 +1443,7 @@ def test_main(arith=False, verbose=None, todo_tests=None, debug=None): ...@@ -1351,6 +1443,7 @@ def test_main(arith=False, verbose=None, todo_tests=None, debug=None):
DecimalExplicitConstructionTest, DecimalExplicitConstructionTest,
DecimalImplicitConstructionTest, DecimalImplicitConstructionTest,
DecimalArithmeticOperatorsTest, DecimalArithmeticOperatorsTest,
DecimalFormatTest,
DecimalUseOfContextTest, DecimalUseOfContextTest,
DecimalUsabilityTest, DecimalUsabilityTest,
DecimalPythonAPItests, DecimalPythonAPItests,
......
...@@ -54,7 +54,14 @@ class TestBasicOps(unittest.TestCase): ...@@ -54,7 +54,14 @@ class TestBasicOps(unittest.TestCase):
self.assertEqual(list(chain('abc')), list('abc')) self.assertEqual(list(chain('abc')), list('abc'))
self.assertEqual(list(chain('')), []) self.assertEqual(list(chain('')), [])
self.assertEqual(take(4, chain('abc', 'def')), list('abcd')) self.assertEqual(take(4, chain('abc', 'def')), list('abcd'))
self.assertRaises(TypeError, chain, 2, 3) self.assertRaises(TypeError, list,chain(2, 3))
def test_chain_from_iterable(self):
self.assertEqual(list(chain.from_iterable(['abc', 'def'])), list('abcdef'))
self.assertEqual(list(chain.from_iterable(['abc'])), list('abc'))
self.assertEqual(list(chain.from_iterable([''])), [])
self.assertEqual(take(4, chain.from_iterable(['abc', 'def'])), list('abcd'))
self.assertRaises(TypeError, list, chain.from_iterable([2, 3]))
def test_combinations(self): def test_combinations(self):
self.assertRaises(TypeError, combinations, 'abc') # missing r argument self.assertRaises(TypeError, combinations, 'abc') # missing r argument
...@@ -298,6 +305,9 @@ class TestBasicOps(unittest.TestCase): ...@@ -298,6 +305,9 @@ class TestBasicOps(unittest.TestCase):
([range(2), range(3), range(0)], []), # last iterable with zero length ([range(2), range(3), range(0)], []), # last iterable with zero length
]: ]:
self.assertEqual(list(product(*args)), result) self.assertEqual(list(product(*args)), result)
for r in range(4):
self.assertEqual(list(product(*(args*r))),
list(product(*args, **dict(repeat=r))))
self.assertEqual(len(list(product(*[range(7)]*6))), 7**6) self.assertEqual(len(list(product(*[range(7)]*6))), 7**6)
self.assertRaises(TypeError, product, range(6), None) self.assertRaises(TypeError, product, range(6), None)
argtypes = ['', 'abc', '', range(0), range(4), dict(a=1, b=2, c=3), argtypes = ['', 'abc', '', range(0), range(4), dict(a=1, b=2, c=3),
...@@ -684,7 +694,7 @@ class TestVariousIteratorArgs(unittest.TestCase): ...@@ -684,7 +694,7 @@ class TestVariousIteratorArgs(unittest.TestCase):
for g in (G, I, Ig, S, L, R): for g in (G, I, Ig, S, L, R):
self.assertEqual(list(chain(g(s))), list(g(s))) self.assertEqual(list(chain(g(s))), list(g(s)))
self.assertEqual(list(chain(g(s), g(s))), list(g(s))+list(g(s))) self.assertEqual(list(chain(g(s), g(s))), list(g(s))+list(g(s)))
self.assertRaises(TypeError, chain, X(s)) self.assertRaises(TypeError, list, chain(X(s)))
self.assertRaises(TypeError, chain, N(s)) self.assertRaises(TypeError, chain, N(s))
self.assertRaises(ZeroDivisionError, list, chain(E(s))) self.assertRaises(ZeroDivisionError, list, chain(E(s)))
......
...@@ -1571,92 +1571,104 @@ static PyTypeObject imap_type = { ...@@ -1571,92 +1571,104 @@ static PyTypeObject imap_type = {
typedef struct { typedef struct {
PyObject_HEAD PyObject_HEAD
Py_ssize_t tuplesize; PyObject *source; /* Iterator over input iterables */
Py_ssize_t iternum; /* which iterator is active */ PyObject *active; /* Currently running input iterator */
PyObject *ittuple; /* tuple of iterators */
} chainobject; } chainobject;
static PyTypeObject chain_type; static PyTypeObject chain_type;
static PyObject *
chain_new_internal(PyTypeObject *type, PyObject *source)
{
chainobject *lz;
lz = (chainobject *)type->tp_alloc(type, 0);
if (lz == NULL) {
Py_DECREF(source);
return NULL;
}
lz->source = source;
lz->active = NULL;
return (PyObject *)lz;
}
static PyObject * static PyObject *
chain_new(PyTypeObject *type, PyObject *args, PyObject *kwds) chain_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{ {
chainobject *lz; PyObject *source;
Py_ssize_t tuplesize = PySequence_Length(args);
Py_ssize_t i;
PyObject *ittuple;
if (type == &chain_type && !_PyArg_NoKeywords("chain()", kwds)) if (type == &chain_type && !_PyArg_NoKeywords("chain()", kwds))
return NULL; return NULL;
/* obtain iterators */ source = PyObject_GetIter(args);
assert(PyTuple_Check(args)); if (source == NULL)
ittuple = PyTuple_New(tuplesize);
if (ittuple == NULL)
return NULL; return NULL;
for (i=0; i < tuplesize; ++i) {
PyObject *item = PyTuple_GET_ITEM(args, i);
PyObject *it = PyObject_GetIter(item);
if (it == NULL) {
if (PyErr_ExceptionMatches(PyExc_TypeError))
PyErr_Format(PyExc_TypeError,
"chain argument #%zd must support iteration",
i+1);
Py_DECREF(ittuple);
return NULL;
}
PyTuple_SET_ITEM(ittuple, i, it);
}
/* create chainobject structure */ return chain_new_internal(type, source);
lz = (chainobject *)type->tp_alloc(type, 0); }
if (lz == NULL) {
Py_DECREF(ittuple);
return NULL;
}
lz->ittuple = ittuple; static PyObject *
lz->iternum = 0; chain_new_from_iterable(PyTypeObject *type, PyObject *arg)
lz->tuplesize = tuplesize; {
PyObject *source;
source = PyObject_GetIter(arg);
if (source == NULL)
return NULL;
return (PyObject *)lz; return chain_new_internal(type, source);
} }
static void static void
chain_dealloc(chainobject *lz) chain_dealloc(chainobject *lz)
{ {
PyObject_GC_UnTrack(lz); PyObject_GC_UnTrack(lz);
Py_XDECREF(lz->ittuple); Py_XDECREF(lz->active);
Py_XDECREF(lz->source);
Py_TYPE(lz)->tp_free(lz); Py_TYPE(lz)->tp_free(lz);
} }
static int static int
chain_traverse(chainobject *lz, visitproc visit, void *arg) chain_traverse(chainobject *lz, visitproc visit, void *arg)
{ {
Py_VISIT(lz->ittuple); Py_VISIT(lz->source);
Py_VISIT(lz->active);
return 0; return 0;
} }
static PyObject * static PyObject *
chain_next(chainobject *lz) chain_next(chainobject *lz)
{ {
PyObject *it;
PyObject *item; PyObject *item;
while (lz->iternum < lz->tuplesize) { if (lz->source == NULL)
it = PyTuple_GET_ITEM(lz->ittuple, lz->iternum); return NULL; /* already stopped */
item = PyIter_Next(it);
if (item != NULL) if (lz->active == NULL) {
return item; PyObject *iterable = PyIter_Next(lz->source);
if (PyErr_Occurred()) { if (iterable == NULL) {
if (PyErr_ExceptionMatches(PyExc_StopIteration)) Py_CLEAR(lz->source);
PyErr_Clear(); return NULL; /* no more input sources */
else }
return NULL; lz->active = PyObject_GetIter(iterable);
if (lz->active == NULL) {
Py_DECREF(iterable);
Py_CLEAR(lz->source);
return NULL; /* input not iterable */
} }
lz->iternum++;
} }
return NULL; item = PyIter_Next(lz->active);
if (item != NULL)
return item;
if (PyErr_Occurred()) {
if (PyErr_ExceptionMatches(PyExc_StopIteration))
PyErr_Clear();
else
return NULL; /* input raised an exception */
}
Py_CLEAR(lz->active);
return chain_next(lz); /* recurse and use next active */
} }
PyDoc_STRVAR(chain_doc, PyDoc_STRVAR(chain_doc,
...@@ -1666,6 +1678,18 @@ Return a chain object whose .__next__() method returns elements from the\n\ ...@@ -1666,6 +1678,18 @@ Return a chain object whose .__next__() method returns elements from the\n\
first iterable until it is exhausted, then elements from the next\n\ first iterable until it is exhausted, then elements from the next\n\
iterable, until all of the iterables are exhausted."); iterable, until all of the iterables are exhausted.");
PyDoc_STRVAR(chain_from_iterable_doc,
"chain.from_iterable(iterable) --> chain object\n\
\n\
Alternate chain() contructor taking a single iterable argument\n\
that evaluates lazily.");
static PyMethodDef chain_methods[] = {
{"from_iterable", (PyCFunction) chain_new_from_iterable, METH_O | METH_CLASS,
chain_from_iterable_doc},
{NULL, NULL} /* sentinel */
};
static PyTypeObject chain_type = { static PyTypeObject chain_type = {
PyVarObject_HEAD_INIT(NULL, 0) PyVarObject_HEAD_INIT(NULL, 0)
"itertools.chain", /* tp_name */ "itertools.chain", /* tp_name */
...@@ -1696,7 +1720,7 @@ static PyTypeObject chain_type = { ...@@ -1696,7 +1720,7 @@ static PyTypeObject chain_type = {
0, /* tp_weaklistoffset */ 0, /* tp_weaklistoffset */
PyObject_SelfIter, /* tp_iter */ PyObject_SelfIter, /* tp_iter */
(iternextfunc)chain_next, /* tp_iternext */ (iternextfunc)chain_next, /* tp_iternext */
0, /* tp_methods */ chain_methods, /* tp_methods */
0, /* tp_members */ 0, /* tp_members */
0, /* tp_getset */ 0, /* tp_getset */
0, /* tp_base */ 0, /* tp_base */
...@@ -1728,17 +1752,32 @@ static PyObject * ...@@ -1728,17 +1752,32 @@ static PyObject *
product_new(PyTypeObject *type, PyObject *args, PyObject *kwds) product_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{ {
productobject *lz; productobject *lz;
Py_ssize_t npools; Py_ssize_t nargs, npools, repeat=1;
PyObject *pools = NULL; PyObject *pools = NULL;
Py_ssize_t *maxvec = NULL; Py_ssize_t *maxvec = NULL;
Py_ssize_t *indices = NULL; Py_ssize_t *indices = NULL;
Py_ssize_t i; Py_ssize_t i;
if (type == &product_type && !_PyArg_NoKeywords("product()", kwds)) if (kwds != NULL) {
return NULL; char *kwlist[] = {"repeat", 0};
PyObject *tmpargs = PyTuple_New(0);
if (tmpargs == NULL)
return NULL;
if (!PyArg_ParseTupleAndKeywords(tmpargs, kwds, "|n:product", kwlist, &repeat)) {
Py_DECREF(tmpargs);
return NULL;
}
Py_DECREF(tmpargs);
if (repeat < 0) {
PyErr_SetString(PyExc_ValueError,
"repeat argument cannot be negative");
return NULL;
}
}
assert(PyTuple_Check(args)); assert(PyTuple_Check(args));
npools = PyTuple_GET_SIZE(args); nargs = (repeat == 0) ? 0 : PyTuple_GET_SIZE(args);
npools = nargs * repeat;
maxvec = PyMem_Malloc(npools * sizeof(Py_ssize_t)); maxvec = PyMem_Malloc(npools * sizeof(Py_ssize_t));
indices = PyMem_Malloc(npools * sizeof(Py_ssize_t)); indices = PyMem_Malloc(npools * sizeof(Py_ssize_t));
...@@ -1751,7 +1790,7 @@ product_new(PyTypeObject *type, PyObject *args, PyObject *kwds) ...@@ -1751,7 +1790,7 @@ product_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
if (pools == NULL) if (pools == NULL)
goto error; goto error;
for (i=0; i < npools; ++i) { for (i=0; i < nargs ; ++i) {
PyObject *item = PyTuple_GET_ITEM(args, i); PyObject *item = PyTuple_GET_ITEM(args, i);
PyObject *pool = PySequence_Tuple(item); PyObject *pool = PySequence_Tuple(item);
if (pool == NULL) if (pool == NULL)
...@@ -1761,6 +1800,13 @@ product_new(PyTypeObject *type, PyObject *args, PyObject *kwds) ...@@ -1761,6 +1800,13 @@ product_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
maxvec[i] = PyTuple_GET_SIZE(pool); maxvec[i] = PyTuple_GET_SIZE(pool);
indices[i] = 0; indices[i] = 0;
} }
for ( ; i < npools; ++i) {
PyObject *pool = PyTuple_GET_ITEM(pools, i - nargs);
Py_INCREF(pool);
PyTuple_SET_ITEM(pools, i, pool);
maxvec[i] = maxvec[i - nargs];
indices[i] = 0;
}
/* create productobject structure */ /* create productobject structure */
lz = (productobject *)type->tp_alloc(type, 0); lz = (productobject *)type->tp_alloc(type, 0);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment