Index: Include/iterobject.h =================================================================== --- Include/iterobject.h (revision 51572) +++ Include/iterobject.h (working copy) @@ -16,6 +16,9 @@ #define PyCallIter_Check(op) ((op)->ob_type == &PyCallIter_Type) PyAPI_FUNC(PyObject *) PyCallIter_New(PyObject *, PyObject *); + +PyObject* zip_create_iter(PyObject* args); + #ifdef __cplusplus } #endif Index: Objects/iterobject.c =================================================================== --- Objects/iterobject.c (revision 51572) +++ Objects/iterobject.c (working copy) @@ -230,3 +230,228 @@ (iternextfunc)calliter_iternext, /* tp_iternext */ 0, /* tp_methods */ }; + + +/*********************** Zip Iterator **************************/ + +static PyObject *zip_iter(PyObject *seq); + +typedef struct zipiterobject_t { + PyObject_HEAD + long it_index; + PyTupleObject *it_tuple; /* Set to NULL when iterator is exhausted */ + Py_ssize_t resultsize; + PyTupleObject *result; /* Reusable tuple for optimization */ +} zipiterobject; + +static void zipiter_dealloc(zipiterobject *); +static int zipiter_traverse(zipiterobject *, visitproc, void *); +static PyObject *zipiter_next(zipiterobject *); +static PyObject *zipiter_len(zipiterobject *); + +/*PyDoc_STRVAR(length_hint_doc, "Private method returning an estimate of len(zip(it)).");*/ + +static PyMethodDef zipiter_methods[] = { + {"__length_hint__", (PyCFunction)zipiter_len, METH_NOARGS, length_hint_doc}, + {NULL, NULL} /* sentinel */ +}; + +PyTypeObject PyZipIter_Type = { + PyObject_HEAD_INIT(&PyType_Type) + 0, /* ob_size */ + "zipiterator", /* tp_name */ + sizeof(zipiterobject), /* tp_basicsize */ + 0, /* tp_itemsize */ + /* methods */ + (destructor)zipiter_dealloc, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_compare */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + PyObject_GenericGetAttr, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */ + 0, /* tp_doc */ + (traverseproc)zipiter_traverse, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weakzipoffset */ + PyObject_SelfIter, /* tp_iter */ + (iternextfunc)zipiter_next, /* tp_iternext */ + zipiter_methods, /* tp_methods */ + 0, /* tp_members */ +}; + + +PyObject * +zip_create_iter(PyObject* args) +{ + Py_ssize_t i; + Py_ssize_t tuplesize = PySequence_Length((PyObject*) args); + PyObject* ziptuple; + PyObject* result; + struct zipiterobject_t* zipiter; + + assert(PyTuple_Check(args)); + + ziptuple = PyTuple_New(tuplesize); + if (ziptuple == NULL) + return NULL; + + for(i=0; i < tuplesize; i++) { + PyObject *o = PyTuple_GET_ITEM(args, i); + PyObject *it = PyObject_GetIter(o); + if (it == NULL) { + if (PyErr_ExceptionMatches(PyExc_TypeError)) + PyErr_Format(PyExc_TypeError, + "zip argument #%zd must support iteration", + i+1); + Py_DECREF(ziptuple); + return NULL; + } + PyTuple_SET_ITEM(ziptuple, i, it); + } + + /* create a reusable result holder */ + result = PyTuple_New(tuplesize); + if (result == NULL) { + Py_DECREF(ziptuple); + return NULL; + } + for (i=0 ; i < tuplesize ; i++) { + Py_INCREF(Py_None); + PyTuple_SET_ITEM(result, i, Py_None); + } + + zipiter = PyObject_GC_New(zipiterobject, &PyZipIter_Type); + if (zipiter == NULL) { + Py_DECREF(ziptuple); + Py_DECREF(result); + return NULL; + } + + zipiter->result = (PyTupleObject*) result; + zipiter->resultsize = tuplesize; + zipiter->it_index = 0; + Py_INCREF(ziptuple); + zipiter->it_tuple = (PyTupleObject *) ziptuple; + _PyObject_GC_TRACK(zipiter); + return (PyObject *)zipiter; +} + +static void +zipiter_dealloc(zipiterobject *it) +{ + _PyObject_GC_UNTRACK(it); + Py_XDECREF(it->it_tuple); + PyObject_GC_Del(it); +} + +static int +zipiter_traverse(zipiterobject *it, visitproc visit, void *arg) +{ + Py_VISIT(it->it_tuple); + return 0; +} + +static PyObject * +zipiter_next(zipiterobject *zit) +{ + Py_ssize_t i; + Py_ssize_t tuplesize = zit->resultsize; + PyObject *result = (PyObject*) zit->result; + PyObject *olditem; + + if (tuplesize == 0) + return NULL; + + if (result->ob_refcnt == 1) { + Py_INCREF(result); + for (i=0 ; i < tuplesize ; i++) { + PyObject *it = PyTuple_GET_ITEM(zit->it_tuple, i); + assert(PyIter_Check(it)); + PyObject *item = (*it->ob_type->tp_iternext)(it); + if (item == NULL) { + Py_DECREF(result); + return NULL; + } + olditem = PyTuple_GET_ITEM(result, i); + PyTuple_SET_ITEM(result, i, item); + Py_DECREF(olditem); + } + } else { + result = PyTuple_New(tuplesize); + if (result == NULL) + return NULL; + for (i=0 ; i < tuplesize ; i++) { + PyObject *it = PyTuple_GET_ITEM(zit->it_tuple, i); + assert(PyIter_Check(it)); + PyObject *item = (*it->ob_type->tp_iternext)(it); + if (item == NULL) { + Py_DECREF(result); + return NULL; + } + PyTuple_SET_ITEM(result, i, item); + } + } + return result; +} + +Py_ssize_t +zipiter_PyObject_LengthHintNoErr(PyObject *o) +{ + Py_ssize_t rv = _PyObject_LengthHint(o); + if (rv != -1) + return rv; + if (PyErr_ExceptionMatches(PyExc_TypeError) || + PyErr_ExceptionMatches(PyExc_AttributeError)) { + PyObject *err_type, *err_value, *err_tb, *ro; + + PyErr_Fetch(&err_type, &err_value, &err_tb); + Py_DECREF(ro); + Py_XDECREF(err_type); + Py_XDECREF(err_value); + Py_XDECREF(err_tb); + return 0; + } + return -1; +} + + +static PyObject * +zipiter_len(zipiterobject *zit) +{ + Py_ssize_t tuplesize = PySequence_Length((PyObject*) zit->it_tuple); + Py_ssize_t i; + Py_ssize_t len = -1; + + /* Take the shortest length from our iteratatosr. Ignore iterators + that don't support LengthHint */ + for(i = 0; i < tuplesize; i++) { + PyObject *it = PyTuple_GET_ITEM(zit->it_tuple, i); + Py_ssize_t hintlen; + assert(PyIter_Check(it)); + //fprintf(stderr, "before length check\n"); + hintlen = zipiter_PyObject_LengthHintNoErr(it); + //fprintf(stderr, "after length check\n"); + if (hintlen == -1) + continue; + else if (len == -1) + len = hintlen; + else if (len > hintlen) + len = hintlen; + } + + if (len == -1) + len = 0; + return PyInt_FromLong(len); +} + Index: Python/bltinmodule.c =================================================================== --- Python/bltinmodule.c (revision 51572) +++ Python/bltinmodule.c (working copy) @@ -1855,22 +1855,10 @@ static PyObject* builtin_zip(PyObject *self, PyObject *args) { - PyObject *itertools = NULL, *izip = NULL, *result = NULL; + /* args must be a tuple */ + assert(PyTuple_Check(args)); - itertools = PyImport_ImportModule("itertools"); - if (itertools == NULL) - return NULL; - - izip = PyObject_GetAttrString(itertools, "izip"); - if (izip == NULL) - goto done; - - result = PyObject_Call(izip, args, NULL); - - done: - Py_XDECREF(itertools); - Py_XDECREF(izip); - return result; + return zip_create_iter(args); } Index: Lib/test/test_zip.py =================================================================== --- Lib/test/test_zip.py (revision 0) +++ Lib/test/test_zip.py (revision 0) @@ -0,0 +1,676 @@ +# This test is a modified version of the original test_itertools.py +import unittest +from test import test_support +from weakref import proxy +import sys +import operator +import random + +bltin_iterzip = zip +listzip = lambda *args : list(bltin_iterzip(*args)) +iterzip = bltin_iterzip + +# Set the functions as test_itertools.py expected them + +def gen3(): + 'Non-restartable source sequence' + for i in (0, 1, 2): + yield i + +class StopNow: + 'Class emulating an empty iterable.' + def __iter__(self): + return self + def next(self): + raise StopIteration + +class TestBasicOps(unittest.TestCase): + + def test_zip(self): + ans = [(x,y) for x, y in zip('abc',gen3())] + self.assertEqual(ans, [('a', 0), ('b', 1), ('c', 2)]) + self.assertEqual(list(zip('abc', range(6))), listzip('abc', range(6))) + self.assertEqual(list(zip('abcdef', range(3))), listzip('abcdef', range(3))) + self.assertEqual(list(zip('abcdef')), listzip('abcdef')) + self.assertEqual(list(zip()), listzip()) + self.assertRaises(TypeError, zip, 3) + self.assertRaises(TypeError, zip, range(3), 3) + + # Check tuple re-use (implementation detail) + self.assertEqual([tuple(list(pair)) for pair in zip('abc', 'def')], + listzip('abc', 'def')) + self.assertEqual([pair for pair in zip('abc', 'def')], + listzip('abc', 'def')) + + + def test_StopIteration(self): + self.assertRaises(StopIteration, zip().next) + + for f in (zip, ): + self.assertRaises(StopIteration, f([]).next) + self.assertRaises(StopIteration, f(StopNow()).next) + + +class TestGC(unittest.TestCase): + + def makecycle(self, iterator, container): + container.append(iterator) + iterator.next() + del container, iterator + + + def test_zip(self): + a = [] + self.makecycle(zip([a]*2, [a]*3), a) + + +def R(seqn): + 'Regular generator' + for i in seqn: + yield i + +class G: + 'Sequence using __getitem__' + def __init__(self, seqn): + self.seqn = seqn + def __getitem__(self, i): + return self.seqn[i] + +class I: + 'Sequence using iterator protocol' + def __init__(self, seqn): + self.seqn = seqn + self.i = 0 + def __iter__(self): + return self + def next(self): + if self.i >= len(self.seqn): raise StopIteration + v = self.seqn[self.i] + self.i += 1 + return v + +class Ig: + 'Sequence using iterator protocol defined with a generator' + def __init__(self, seqn): + self.seqn = seqn + self.i = 0 + def __iter__(self): + for val in self.seqn: + yield val + +class X: + 'Missing __getitem__ and __iter__' + def __init__(self, seqn): + self.seqn = seqn + self.i = 0 + def next(self): + if self.i >= len(self.seqn): raise StopIteration + v = self.seqn[self.i] + self.i += 1 + return v + +class N: + 'Iterator missing next()' + def __init__(self, seqn): + self.seqn = seqn + self.i = 0 + def __iter__(self): + return self + +class E: + 'Test propagation of exceptions' + def __init__(self, seqn): + self.seqn = seqn + self.i = 0 + def __iter__(self): + return self + def next(self): + 3 // 0 + +class S: + 'Test immediate stop' + def __init__(self, seqn): + pass + def __iter__(self): + return self + def next(self): + raise StopIteration + + +class TestVariousIteratorArgs(unittest.TestCase): + + def test_zip(self): + for s in ("123", "", range(1000), ('do', 1.2), xrange(2000,2200,5)): + for g in (G, I, Ig, S, R): + self.assertEqual(list(zip(g(s))), listzip(g(s))) + self.assertEqual(list(zip(g(s), g(s))), listzip(g(s), g(s))) + self.assertRaises(TypeError, zip, X(s)) + self.assertRaises(TypeError, zip, N(s)) + self.assertRaises(ZeroDivisionError, list, zip(E(s))) + + +def test_main(verbose=None): + test_classes = (TestBasicOps, TestVariousIteratorArgs, TestGC,) + + test_support.run_unittest(*test_classes) + + # verify reference counting + if verbose and hasattr(sys, "gettotalrefcount"): + import gc + counts = [None] * 5 + for i in xrange(len(counts)): + test_support.run_unittest(*test_classes) + gc.collect() + counts[i] = sys.gettotalrefcount() + print counts + + +if __name__ == "__main__": + test_main(verbose=True) +# This test is a modified version of the original test_itertools.py +import unittest +from test import test_support +from weakref import proxy +import sys +import operator +import random + +bltin_iterzip = zip +listzip = lambda *args : list(bltin_iterzip(*args)) +iterzip = bltin_iterzip + +# Set the functions as test_itertools.py expected them + +def gen3(): + 'Non-restartable source sequence' + for i in (0, 1, 2): + yield i + +class StopNow: + 'Class emulating an empty iterable.' + def __iter__(self): + return self + def next(self): + raise StopIteration + +class TestBasicOps(unittest.TestCase): + + def test_zip(self): + ans = [(x,y) for x, y in zip('abc',gen3())] + self.assertEqual(ans, [('a', 0), ('b', 1), ('c', 2)]) + self.assertEqual(list(zip('abc', range(6))), listzip('abc', range(6))) + self.assertEqual(list(zip('abcdef', range(3))), listzip('abcdef', range(3))) + self.assertEqual(list(zip('abcdef')), listzip('abcdef')) + self.assertEqual(list(zip()), listzip()) + self.assertRaises(TypeError, zip, 3) + self.assertRaises(TypeError, zip, range(3), 3) + + # Check tuple re-use (implementation detail) + self.assertEqual([tuple(list(pair)) for pair in zip('abc', 'def')], + listzip('abc', 'def')) + self.assertEqual([pair for pair in zip('abc', 'def')], + listzip('abc', 'def')) + + + def test_StopIteration(self): + self.assertRaises(StopIteration, zip().next) + + for f in (zip, ): + self.assertRaises(StopIteration, f([]).next) + self.assertRaises(StopIteration, f(StopNow()).next) + + +class TestGC(unittest.TestCase): + + def makecycle(self, iterator, container): + container.append(iterator) + iterator.next() + del container, iterator + + + def test_zip(self): + a = [] + self.makecycle(zip([a]*2, [a]*3), a) + + +def R(seqn): + 'Regular generator' + for i in seqn: + yield i + +class G: + 'Sequence using __getitem__' + def __init__(self, seqn): + self.seqn = seqn + def __getitem__(self, i): + return self.seqn[i] + +class I: + 'Sequence using iterator protocol' + def __init__(self, seqn): + self.seqn = seqn + self.i = 0 + def __iter__(self): + return self + def next(self): + if self.i >= len(self.seqn): raise StopIteration + v = self.seqn[self.i] + self.i += 1 + return v + +class Ig: + 'Sequence using iterator protocol defined with a generator' + def __init__(self, seqn): + self.seqn = seqn + self.i = 0 + def __iter__(self): + for val in self.seqn: + yield val + +class X: + 'Missing __getitem__ and __iter__' + def __init__(self, seqn): + self.seqn = seqn + self.i = 0 + def next(self): + if self.i >= len(self.seqn): raise StopIteration + v = self.seqn[self.i] + self.i += 1 + return v + +class N: + 'Iterator missing next()' + def __init__(self, seqn): + self.seqn = seqn + self.i = 0 + def __iter__(self): + return self + +class E: + 'Test propagation of exceptions' + def __init__(self, seqn): + self.seqn = seqn + self.i = 0 + def __iter__(self): + return self + def next(self): + 3 // 0 + +class S: + 'Test immediate stop' + def __init__(self, seqn): + pass + def __iter__(self): + return self + def next(self): + raise StopIteration + + +class TestVariousIteratorArgs(unittest.TestCase): + + def test_zip(self): + for s in ("123", "", range(1000), ('do', 1.2), xrange(2000,2200,5)): + for g in (G, I, Ig, S, R): + self.assertEqual(list(zip(g(s))), listzip(g(s))) + self.assertEqual(list(zip(g(s), g(s))), listzip(g(s), g(s))) + self.assertRaises(TypeError, zip, X(s)) + self.assertRaises(TypeError, zip, N(s)) + self.assertRaises(ZeroDivisionError, list, zip(E(s))) + + +def test_main(verbose=None): + test_classes = (TestBasicOps, TestVariousIteratorArgs, TestGC,) + + test_support.run_unittest(*test_classes) + + # verify reference counting + if verbose and hasattr(sys, "gettotalrefcount"): + import gc + counts = [None] * 5 + for i in xrange(len(counts)): + test_support.run_unittest(*test_classes) + gc.collect() + counts[i] = sys.gettotalrefcount() + print counts + + +if __name__ == "__main__": + test_main(verbose=True) +# This test is a modified version of the original test_itertools.py +import unittest +from test import test_support +from weakref import proxy +import sys +import operator +import random + +bltin_iterzip = zip +listzip = lambda *args : list(bltin_iterzip(*args)) +iterzip = bltin_iterzip + +# Set the functions as test_itertools.py expected them + +def gen3(): + 'Non-restartable source sequence' + for i in (0, 1, 2): + yield i + +class StopNow: + 'Class emulating an empty iterable.' + def __iter__(self): + return self + def next(self): + raise StopIteration + +class TestBasicOps(unittest.TestCase): + + def test_zip(self): + ans = [(x,y) for x, y in zip('abc',gen3())] + self.assertEqual(ans, [('a', 0), ('b', 1), ('c', 2)]) + self.assertEqual(list(zip('abc', range(6))), listzip('abc', range(6))) + self.assertEqual(list(zip('abcdef', range(3))), listzip('abcdef', range(3))) + self.assertEqual(list(zip('abcdef')), listzip('abcdef')) + self.assertEqual(list(zip()), listzip()) + self.assertRaises(TypeError, zip, 3) + self.assertRaises(TypeError, zip, range(3), 3) + + # Check tuple re-use (implementation detail) + self.assertEqual([tuple(list(pair)) for pair in zip('abc', 'def')], + listzip('abc', 'def')) + self.assertEqual([pair for pair in zip('abc', 'def')], + listzip('abc', 'def')) + + + def test_StopIteration(self): + self.assertRaises(StopIteration, zip().next) + + for f in (zip, ): + self.assertRaises(StopIteration, f([]).next) + self.assertRaises(StopIteration, f(StopNow()).next) + + +class TestGC(unittest.TestCase): + + def makecycle(self, iterator, container): + container.append(iterator) + iterator.next() + del container, iterator + + + def test_zip(self): + a = [] + self.makecycle(zip([a]*2, [a]*3), a) + + +def R(seqn): + 'Regular generator' + for i in seqn: + yield i + +class G: + 'Sequence using __getitem__' + def __init__(self, seqn): + self.seqn = seqn + def __getitem__(self, i): + return self.seqn[i] + +class I: + 'Sequence using iterator protocol' + def __init__(self, seqn): + self.seqn = seqn + self.i = 0 + def __iter__(self): + return self + def next(self): + if self.i >= len(self.seqn): raise StopIteration + v = self.seqn[self.i] + self.i += 1 + return v + +class Ig: + 'Sequence using iterator protocol defined with a generator' + def __init__(self, seqn): + self.seqn = seqn + self.i = 0 + def __iter__(self): + for val in self.seqn: + yield val + +class X: + 'Missing __getitem__ and __iter__' + def __init__(self, seqn): + self.seqn = seqn + self.i = 0 + def next(self): + if self.i >= len(self.seqn): raise StopIteration + v = self.seqn[self.i] + self.i += 1 + return v + +class N: + 'Iterator missing next()' + def __init__(self, seqn): + self.seqn = seqn + self.i = 0 + def __iter__(self): + return self + +class E: + 'Test propagation of exceptions' + def __init__(self, seqn): + self.seqn = seqn + self.i = 0 + def __iter__(self): + return self + def next(self): + 3 // 0 + +class S: + 'Test immediate stop' + def __init__(self, seqn): + pass + def __iter__(self): + return self + def next(self): + raise StopIteration + + +class TestVariousIteratorArgs(unittest.TestCase): + + def test_zip(self): + for s in ("123", "", range(1000), ('do', 1.2), xrange(2000,2200,5)): + for g in (G, I, Ig, S, R): + self.assertEqual(list(zip(g(s))), listzip(g(s))) + self.assertEqual(list(zip(g(s), g(s))), listzip(g(s), g(s))) + self.assertRaises(TypeError, zip, X(s)) + self.assertRaises(TypeError, zip, N(s)) + self.assertRaises(ZeroDivisionError, list, zip(E(s))) + + +def test_main(verbose=None): + test_classes = (TestBasicOps, TestVariousIteratorArgs, TestGC,) + + test_support.run_unittest(*test_classes) + + # verify reference counting + if verbose and hasattr(sys, "gettotalrefcount"): + import gc + counts = [None] * 5 + for i in xrange(len(counts)): + test_support.run_unittest(*test_classes) + gc.collect() + counts[i] = sys.gettotalrefcount() + print counts + + +if __name__ == "__main__": + test_main(verbose=True) +# This test is a modified version of the original test_itertools.py +import unittest +from test import test_support +from weakref import proxy +import sys +import operator +import random + +bltin_iterzip = zip +listzip = lambda *args : list(bltin_iterzip(*args)) +iterzip = bltin_iterzip + +# Set the functions as test_itertools.py expected them + +def gen3(): + 'Non-restartable source sequence' + for i in (0, 1, 2): + yield i + +class StopNow: + 'Class emulating an empty iterable.' + def __iter__(self): + return self + def next(self): + raise StopIteration + +class TestBasicOps(unittest.TestCase): + + def test_zip(self): + ans = [(x,y) for x, y in zip('abc',gen3())] + self.assertEqual(ans, [('a', 0), ('b', 1), ('c', 2)]) + self.assertEqual(list(zip('abc', range(6))), listzip('abc', range(6))) + self.assertEqual(list(zip('abcdef', range(3))), listzip('abcdef', range(3))) + self.assertEqual(list(zip('abcdef')), listzip('abcdef')) + self.assertEqual(list(zip()), listzip()) + self.assertRaises(TypeError, zip, 3) + self.assertRaises(TypeError, zip, range(3), 3) + + # Check tuple re-use (implementation detail) + self.assertEqual([tuple(list(pair)) for pair in zip('abc', 'def')], + listzip('abc', 'def')) + self.assertEqual([pair for pair in zip('abc', 'def')], + listzip('abc', 'def')) + + + def test_StopIteration(self): + self.assertRaises(StopIteration, zip().next) + + for f in (zip, ): + self.assertRaises(StopIteration, f([]).next) + self.assertRaises(StopIteration, f(StopNow()).next) + + +class TestGC(unittest.TestCase): + + def makecycle(self, iterator, container): + container.append(iterator) + iterator.next() + del container, iterator + + + def test_zip(self): + a = [] + self.makecycle(zip([a]*2, [a]*3), a) + + +def R(seqn): + 'Regular generator' + for i in seqn: + yield i + +class G: + 'Sequence using __getitem__' + def __init__(self, seqn): + self.seqn = seqn + def __getitem__(self, i): + return self.seqn[i] + +class I: + 'Sequence using iterator protocol' + def __init__(self, seqn): + self.seqn = seqn + self.i = 0 + def __iter__(self): + return self + def next(self): + if self.i >= len(self.seqn): raise StopIteration + v = self.seqn[self.i] + self.i += 1 + return v + +class Ig: + 'Sequence using iterator protocol defined with a generator' + def __init__(self, seqn): + self.seqn = seqn + self.i = 0 + def __iter__(self): + for val in self.seqn: + yield val + +class X: + 'Missing __getitem__ and __iter__' + def __init__(self, seqn): + self.seqn = seqn + self.i = 0 + def next(self): + if self.i >= len(self.seqn): raise StopIteration + v = self.seqn[self.i] + self.i += 1 + return v + +class N: + 'Iterator missing next()' + def __init__(self, seqn): + self.seqn = seqn + self.i = 0 + def __iter__(self): + return self + +class E: + 'Test propagation of exceptions' + def __init__(self, seqn): + self.seqn = seqn + self.i = 0 + def __iter__(self): + return self + def next(self): + 3 // 0 + +class S: + 'Test immediate stop' + def __init__(self, seqn): + pass + def __iter__(self): + return self + def next(self): + raise StopIteration + + +class TestVariousIteratorArgs(unittest.TestCase): + + def test_zip(self): + for s in ("123", "", range(1000), ('do', 1.2), xrange(2000,2200,5)): + for g in (G, I, Ig, S, R): + self.assertEqual(list(zip(g(s))), listzip(g(s))) + self.assertEqual(list(zip(g(s), g(s))), listzip(g(s), g(s))) + self.assertRaises(TypeError, zip, X(s)) + self.assertRaises(TypeError, zip, N(s)) + self.assertRaises(ZeroDivisionError, list, zip(E(s))) + + +def test_main(verbose=None): + test_classes = (TestBasicOps, TestVariousIteratorArgs, TestGC,) + + test_support.run_unittest(*test_classes) + + # verify reference counting + if verbose and hasattr(sys, "gettotalrefcount"): + import gc + counts = [None] * 5 + for i in xrange(len(counts)): + test_support.run_unittest(*test_classes) + gc.collect() + counts[i] = sys.gettotalrefcount() + print counts + + +if __name__ == "__main__": + test_main(verbose=True) Property changes on: Lib/test/test_zip.py ___________________________________________________________________ Name: svn:keywords + Id Name: svn:eol-style + native