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):
self.assertEqual(eval('Decimal(10)' + sym + 'E()'),
'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):
'''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):
DecimalExplicitConstructionTest,
DecimalImplicitConstructionTest,
DecimalArithmeticOperatorsTest,
DecimalFormatTest,
DecimalUseOfContextTest,
DecimalUsabilityTest,
DecimalPythonAPItests,
......
......@@ -54,7 +54,14 @@ class TestBasicOps(unittest.TestCase):
self.assertEqual(list(chain('abc')), list('abc'))
self.assertEqual(list(chain('')), [])
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):
self.assertRaises(TypeError, combinations, 'abc') # missing r argument
......@@ -298,6 +305,9 @@ class TestBasicOps(unittest.TestCase):
([range(2), range(3), range(0)], []), # last iterable with zero length
]:
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.assertRaises(TypeError, product, range(6), None)
argtypes = ['', 'abc', '', range(0), range(4), dict(a=1, b=2, c=3),
......@@ -684,7 +694,7 @@ class TestVariousIteratorArgs(unittest.TestCase):
for g in (G, I, Ig, S, L, R):
self.assertEqual(list(chain(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(ZeroDivisionError, list, chain(E(s)))
......
......@@ -1571,92 +1571,104 @@ static PyTypeObject imap_type = {
typedef struct {
PyObject_HEAD
Py_ssize_t tuplesize;
Py_ssize_t iternum; /* which iterator is active */
PyObject *ittuple; /* tuple of iterators */
PyObject *source; /* Iterator over input iterables */
PyObject *active; /* Currently running input iterator */
} chainobject;
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 *
chain_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
chainobject *lz;
Py_ssize_t tuplesize = PySequence_Length(args);
Py_ssize_t i;
PyObject *ittuple;
PyObject *source;
if (type == &chain_type && !_PyArg_NoKeywords("chain()", kwds))
return NULL;
/* obtain iterators */
assert(PyTuple_Check(args));
ittuple = PyTuple_New(tuplesize);
if (ittuple == NULL)
source = PyObject_GetIter(args);
if (source == 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 */
lz = (chainobject *)type->tp_alloc(type, 0);
if (lz == NULL) {
Py_DECREF(ittuple);
return NULL;
}
return chain_new_internal(type, source);
}
lz->ittuple = ittuple;
lz->iternum = 0;
lz->tuplesize = tuplesize;
static PyObject *
chain_new_from_iterable(PyTypeObject *type, PyObject *arg)
{
PyObject *source;
source = PyObject_GetIter(arg);
if (source == NULL)
return NULL;
return (PyObject *)lz;
return chain_new_internal(type, source);
}
static void
chain_dealloc(chainobject *lz)
{
PyObject_GC_UnTrack(lz);
Py_XDECREF(lz->ittuple);
Py_XDECREF(lz->active);
Py_XDECREF(lz->source);
Py_TYPE(lz)->tp_free(lz);
}
static int
chain_traverse(chainobject *lz, visitproc visit, void *arg)
{
Py_VISIT(lz->ittuple);
Py_VISIT(lz->source);
Py_VISIT(lz->active);
return 0;
}
static PyObject *
chain_next(chainobject *lz)
{
PyObject *it;
PyObject *item;
while (lz->iternum < lz->tuplesize) {
it = PyTuple_GET_ITEM(lz->ittuple, lz->iternum);
item = PyIter_Next(it);
if (item != NULL)
return item;
if (PyErr_Occurred()) {
if (PyErr_ExceptionMatches(PyExc_StopIteration))
PyErr_Clear();
else
return NULL;
if (lz->source == NULL)
return NULL; /* already stopped */
if (lz->active == NULL) {
PyObject *iterable = PyIter_Next(lz->source);
if (iterable == NULL) {
Py_CLEAR(lz->source);
return NULL; /* no more input sources */
}
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,
......@@ -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\
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 = {
PyVarObject_HEAD_INIT(NULL, 0)
"itertools.chain", /* tp_name */
......@@ -1696,7 +1720,7 @@ static PyTypeObject chain_type = {
0, /* tp_weaklistoffset */
PyObject_SelfIter, /* tp_iter */
(iternextfunc)chain_next, /* tp_iternext */
0, /* tp_methods */
chain_methods, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
......@@ -1728,17 +1752,32 @@ static PyObject *
product_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
productobject *lz;
Py_ssize_t npools;
Py_ssize_t nargs, npools, repeat=1;
PyObject *pools = NULL;
Py_ssize_t *maxvec = NULL;
Py_ssize_t *indices = NULL;
Py_ssize_t i;
if (type == &product_type && !_PyArg_NoKeywords("product()", kwds))
return NULL;
if (kwds != 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));
npools = PyTuple_GET_SIZE(args);
nargs = (repeat == 0) ? 0 : PyTuple_GET_SIZE(args);
npools = nargs * repeat;
maxvec = 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)
if (pools == NULL)
goto error;
for (i=0; i < npools; ++i) {
for (i=0; i < nargs ; ++i) {
PyObject *item = PyTuple_GET_ITEM(args, i);
PyObject *pool = PySequence_Tuple(item);
if (pool == NULL)
......@@ -1761,6 +1800,13 @@ product_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
maxvec[i] = PyTuple_GET_SIZE(pool);
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 */
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