Back to index

python3.2  3.2.2
test_enumerate.py
Go to the documentation of this file.
00001 import unittest
00002 import sys
00003 
00004 from test import support
00005 
00006 class G:
00007     'Sequence using __getitem__'
00008     def __init__(self, seqn):
00009         self.seqn = seqn
00010     def __getitem__(self, i):
00011         return self.seqn[i]
00012 
00013 class I:
00014     'Sequence using iterator protocol'
00015     def __init__(self, seqn):
00016         self.seqn = seqn
00017         self.i = 0
00018     def __iter__(self):
00019         return self
00020     def __next__(self):
00021         if self.i >= len(self.seqn): raise StopIteration
00022         v = self.seqn[self.i]
00023         self.i += 1
00024         return v
00025 
00026 class Ig:
00027     'Sequence using iterator protocol defined with a generator'
00028     def __init__(self, seqn):
00029         self.seqn = seqn
00030         self.i = 0
00031     def __iter__(self):
00032         for val in self.seqn:
00033             yield val
00034 
00035 class X:
00036     'Missing __getitem__ and __iter__'
00037     def __init__(self, seqn):
00038         self.seqn = seqn
00039         self.i = 0
00040     def __next__(self):
00041         if self.i >= len(self.seqn): raise StopIteration
00042         v = self.seqn[self.i]
00043         self.i += 1
00044         return v
00045 
00046 class E:
00047     'Test propagation of exceptions'
00048     def __init__(self, seqn):
00049         self.seqn = seqn
00050         self.i = 0
00051     def __iter__(self):
00052         return self
00053     def __next__(self):
00054         3 // 0
00055 
00056 class N:
00057     'Iterator missing __next__()'
00058     def __init__(self, seqn):
00059         self.seqn = seqn
00060         self.i = 0
00061     def __iter__(self):
00062         return self
00063 
00064 class EnumerateTestCase(unittest.TestCase):
00065 
00066     enum = enumerate
00067     seq, res = 'abc', [(0,'a'), (1,'b'), (2,'c')]
00068 
00069     def test_basicfunction(self):
00070         self.assertEqual(type(self.enum(self.seq)), self.enum)
00071         e = self.enum(self.seq)
00072         self.assertEqual(iter(e), e)
00073         self.assertEqual(list(self.enum(self.seq)), self.res)
00074         self.enum.__doc__
00075 
00076     def test_getitemseqn(self):
00077         self.assertEqual(list(self.enum(G(self.seq))), self.res)
00078         e = self.enum(G(''))
00079         self.assertRaises(StopIteration, next, e)
00080 
00081     def test_iteratorseqn(self):
00082         self.assertEqual(list(self.enum(I(self.seq))), self.res)
00083         e = self.enum(I(''))
00084         self.assertRaises(StopIteration, next, e)
00085 
00086     def test_iteratorgenerator(self):
00087         self.assertEqual(list(self.enum(Ig(self.seq))), self.res)
00088         e = self.enum(Ig(''))
00089         self.assertRaises(StopIteration, next, e)
00090 
00091     def test_noniterable(self):
00092         self.assertRaises(TypeError, self.enum, X(self.seq))
00093 
00094     def test_illformediterable(self):
00095         self.assertRaises(TypeError, self.enum, N(self.seq))
00096 
00097     def test_exception_propagation(self):
00098         self.assertRaises(ZeroDivisionError, list, self.enum(E(self.seq)))
00099 
00100     def test_argumentcheck(self):
00101         self.assertRaises(TypeError, self.enum) # no arguments
00102         self.assertRaises(TypeError, self.enum, 1) # wrong type (not iterable)
00103         self.assertRaises(TypeError, self.enum, 'abc', 'a') # wrong type
00104         self.assertRaises(TypeError, self.enum, 'abc', 2, 3) # too many arguments
00105 
00106     @support.cpython_only
00107     def test_tuple_reuse(self):
00108         # Tests an implementation detail where tuple is reused
00109         # whenever nothing else holds a reference to it
00110         self.assertEqual(len(set(map(id, list(enumerate(self.seq))))), len(self.seq))
00111         self.assertEqual(len(set(map(id, enumerate(self.seq)))), min(1,len(self.seq)))
00112 
00113 class MyEnum(enumerate):
00114     pass
00115 
00116 class SubclassTestCase(EnumerateTestCase):
00117 
00118     enum = MyEnum
00119 
00120 class TestEmpty(EnumerateTestCase):
00121 
00122     seq, res = '', []
00123 
00124 class TestBig(EnumerateTestCase):
00125 
00126     seq = range(10,20000,2)
00127     res = list(zip(range(20000), seq))
00128 
00129 class TestReversed(unittest.TestCase):
00130 
00131     def test_simple(self):
00132         class A:
00133             def __getitem__(self, i):
00134                 if i < 5:
00135                     return str(i)
00136                 raise StopIteration
00137             def __len__(self):
00138                 return 5
00139         for data in 'abc', range(5), tuple(enumerate('abc')), A(), range(1,17,5):
00140             self.assertEqual(list(data)[::-1], list(reversed(data)))
00141         self.assertRaises(TypeError, reversed, {})
00142         # don't allow keyword arguments
00143         self.assertRaises(TypeError, reversed, [], a=1)
00144 
00145     def test_range_optimization(self):
00146         x = range(1)
00147         self.assertEqual(type(reversed(x)), type(iter(x)))
00148 
00149     @support.cpython_only
00150     def test_len(self):
00151         # This is an implementation detail, not an interface requirement
00152         from test.test_iterlen import len
00153         for s in ('hello', tuple('hello'), list('hello'), range(5)):
00154             self.assertEqual(len(reversed(s)), len(s))
00155             r = reversed(s)
00156             list(r)
00157             self.assertEqual(len(r), 0)
00158         class SeqWithWeirdLen:
00159             called = False
00160             def __len__(self):
00161                 if not self.called:
00162                     self.called = True
00163                     return 10
00164                 raise ZeroDivisionError
00165             def __getitem__(self, index):
00166                 return index
00167         r = reversed(SeqWithWeirdLen())
00168         self.assertRaises(ZeroDivisionError, len, r)
00169 
00170 
00171     def test_gc(self):
00172         class Seq:
00173             def __len__(self):
00174                 return 10
00175             def __getitem__(self, index):
00176                 return index
00177         s = Seq()
00178         r = reversed(s)
00179         s.r = r
00180 
00181     def test_args(self):
00182         self.assertRaises(TypeError, reversed)
00183         self.assertRaises(TypeError, reversed, [], 'extra')
00184 
00185     def test_bug1229429(self):
00186         # this bug was never in reversed, it was in
00187         # PyObject_CallMethod, and reversed_new calls that sometimes.
00188         if not hasattr(sys, "getrefcount"):
00189             return
00190         def f():
00191             pass
00192         r = f.__reversed__ = object()
00193         rc = sys.getrefcount(r)
00194         for i in range(10):
00195             try:
00196                 reversed(f)
00197             except TypeError:
00198                 pass
00199             else:
00200                 self.fail("non-callable __reversed__ didn't raise!")
00201         self.assertEqual(rc, sys.getrefcount(r))
00202 
00203     def test_objmethods(self):
00204         # Objects must have __len__() and __getitem__() implemented.
00205         class NoLen(object):
00206             def __getitem__(self): return 1
00207         nl = NoLen()
00208         self.assertRaises(TypeError, reversed, nl)
00209 
00210         class NoGetItem(object):
00211             def __len__(self): return 2
00212         ngi = NoGetItem()
00213         self.assertRaises(TypeError, reversed, ngi)
00214 
00215 
00216 class EnumerateStartTestCase(EnumerateTestCase):
00217 
00218     def test_basicfunction(self):
00219         e = self.enum(self.seq)
00220         self.assertEqual(iter(e), e)
00221         self.assertEqual(list(self.enum(self.seq)), self.res)
00222 
00223 
00224 class TestStart(EnumerateStartTestCase):
00225 
00226     enum = lambda self, i: enumerate(i, start=11)
00227     seq, res = 'abc', [(11, 'a'), (12, 'b'), (13, 'c')]
00228 
00229 
00230 class TestLongStart(EnumerateStartTestCase):
00231 
00232     enum = lambda self, i: enumerate(i, start=sys.maxsize+1)
00233     seq, res = 'abc', [(sys.maxsize+1,'a'), (sys.maxsize+2,'b'),
00234                        (sys.maxsize+3,'c')]
00235 
00236 
00237 def test_main(verbose=None):
00238     support.run_unittest(__name__)
00239 
00240     # verify reference counting
00241     if verbose and hasattr(sys, "gettotalrefcount"):
00242         counts = [None] * 5
00243         for i in range(len(counts)):
00244             support.run_unittest(__name__)
00245             counts[i] = sys.gettotalrefcount()
00246         print(counts)
00247 
00248 if __name__ == "__main__":
00249     test_main(verbose=True)