blob: 2e904cf8789f07c52efffa5d075907a3d9e1e738 [file] [log] [blame]
Guido van Rossum7dab2422002-04-26 19:40:56 +00001import unittest
Michael W. Hudson0edc7a02005-07-12 10:21:19 +00002import sys
Kristján Valur Jónsson31668b82012-04-03 10:49:41 +00003import pickle
Guido van Rossum7dab2422002-04-26 19:40:56 +00004
Benjamin Petersonee8712c2008-05-20 21:35:26 +00005from test import support
Guido van Rossum7dab2422002-04-26 19:40:56 +00006
Guido van Rossum7dab2422002-04-26 19:40:56 +00007class G:
8 'Sequence using __getitem__'
9 def __init__(self, seqn):
10 self.seqn = seqn
11 def __getitem__(self, i):
12 return self.seqn[i]
13
14class I:
15 'Sequence using iterator protocol'
16 def __init__(self, seqn):
17 self.seqn = seqn
18 self.i = 0
19 def __iter__(self):
20 return self
Georg Brandla18af4e2007-04-21 15:47:16 +000021 def __next__(self):
Guido van Rossum7dab2422002-04-26 19:40:56 +000022 if self.i >= len(self.seqn): raise StopIteration
23 v = self.seqn[self.i]
24 self.i += 1
25 return v
26
27class Ig:
28 'Sequence using iterator protocol defined with a generator'
29 def __init__(self, seqn):
30 self.seqn = seqn
31 self.i = 0
32 def __iter__(self):
33 for val in self.seqn:
34 yield val
35
36class X:
37 'Missing __getitem__ and __iter__'
38 def __init__(self, seqn):
39 self.seqn = seqn
40 self.i = 0
Georg Brandla18af4e2007-04-21 15:47:16 +000041 def __next__(self):
Guido van Rossum7dab2422002-04-26 19:40:56 +000042 if self.i >= len(self.seqn): raise StopIteration
43 v = self.seqn[self.i]
44 self.i += 1
45 return v
46
47class E:
48 'Test propagation of exceptions'
49 def __init__(self, seqn):
50 self.seqn = seqn
51 self.i = 0
52 def __iter__(self):
53 return self
Georg Brandla18af4e2007-04-21 15:47:16 +000054 def __next__(self):
Raymond Hettingerffdb8bb2004-09-27 15:29:05 +000055 3 // 0
Guido van Rossum7dab2422002-04-26 19:40:56 +000056
57class N:
Georg Brandla18af4e2007-04-21 15:47:16 +000058 'Iterator missing __next__()'
Guido van Rossum7dab2422002-04-26 19:40:56 +000059 def __init__(self, seqn):
60 self.seqn = seqn
61 self.i = 0
62 def __iter__(self):
63 return self
64
Kristján Valur Jónsson31668b82012-04-03 10:49:41 +000065class PickleTest:
66 # Helper to check picklability
67 def check_pickle(self, itorg, seq):
68 d = pickle.dumps(itorg)
69 it = pickle.loads(d)
70 self.assertEqual(type(itorg), type(it))
71 self.assertEqual(list(it), seq)
72
73 it = pickle.loads(d)
74 try:
75 next(it)
76 except StopIteration:
77 self.assertFalse(seq[1:])
78 return
79 d = pickle.dumps(it)
80 it = pickle.loads(d)
81 self.assertEqual(list(it), seq[1:])
82
83class EnumerateTestCase(unittest.TestCase, PickleTest):
Guido van Rossum7dab2422002-04-26 19:40:56 +000084
85 enum = enumerate
Raymond Hettingere8b0f042003-05-28 14:05:34 +000086 seq, res = 'abc', [(0,'a'), (1,'b'), (2,'c')]
Guido van Rossum7dab2422002-04-26 19:40:56 +000087
88 def test_basicfunction(self):
Raymond Hettingere8b0f042003-05-28 14:05:34 +000089 self.assertEqual(type(self.enum(self.seq)), self.enum)
90 e = self.enum(self.seq)
Guido van Rossum7dab2422002-04-26 19:40:56 +000091 self.assertEqual(iter(e), e)
Raymond Hettingere8b0f042003-05-28 14:05:34 +000092 self.assertEqual(list(self.enum(self.seq)), self.res)
Guido van Rossum7dab2422002-04-26 19:40:56 +000093 self.enum.__doc__
94
Kristján Valur Jónsson31668b82012-04-03 10:49:41 +000095 def test_pickle(self):
96 self.check_pickle(self.enum(self.seq), self.res)
97
Guido van Rossum7dab2422002-04-26 19:40:56 +000098 def test_getitemseqn(self):
Raymond Hettingere8b0f042003-05-28 14:05:34 +000099 self.assertEqual(list(self.enum(G(self.seq))), self.res)
Guido van Rossum7dab2422002-04-26 19:40:56 +0000100 e = self.enum(G(''))
Georg Brandla18af4e2007-04-21 15:47:16 +0000101 self.assertRaises(StopIteration, next, e)
Guido van Rossum7dab2422002-04-26 19:40:56 +0000102
103 def test_iteratorseqn(self):
Raymond Hettingere8b0f042003-05-28 14:05:34 +0000104 self.assertEqual(list(self.enum(I(self.seq))), self.res)
Guido van Rossum7dab2422002-04-26 19:40:56 +0000105 e = self.enum(I(''))
Georg Brandla18af4e2007-04-21 15:47:16 +0000106 self.assertRaises(StopIteration, next, e)
Guido van Rossum7dab2422002-04-26 19:40:56 +0000107
108 def test_iteratorgenerator(self):
Raymond Hettingere8b0f042003-05-28 14:05:34 +0000109 self.assertEqual(list(self.enum(Ig(self.seq))), self.res)
Guido van Rossum7dab2422002-04-26 19:40:56 +0000110 e = self.enum(Ig(''))
Georg Brandla18af4e2007-04-21 15:47:16 +0000111 self.assertRaises(StopIteration, next, e)
Guido van Rossum7dab2422002-04-26 19:40:56 +0000112
113 def test_noniterable(self):
Raymond Hettingere8b0f042003-05-28 14:05:34 +0000114 self.assertRaises(TypeError, self.enum, X(self.seq))
Guido van Rossum7dab2422002-04-26 19:40:56 +0000115
116 def test_illformediterable(self):
Thomas Wouters1034dad2006-04-15 09:16:16 +0000117 self.assertRaises(TypeError, self.enum, N(self.seq))
Guido van Rossum7dab2422002-04-26 19:40:56 +0000118
119 def test_exception_propagation(self):
Raymond Hettingere8b0f042003-05-28 14:05:34 +0000120 self.assertRaises(ZeroDivisionError, list, self.enum(E(self.seq)))
121
122 def test_argumentcheck(self):
123 self.assertRaises(TypeError, self.enum) # no arguments
124 self.assertRaises(TypeError, self.enum, 1) # wrong type (not iterable)
Alexandre Vassalottie9f305f2008-05-16 04:39:54 +0000125 self.assertRaises(TypeError, self.enum, 'abc', 'a') # wrong type
126 self.assertRaises(TypeError, self.enum, 'abc', 2, 3) # too many arguments
Raymond Hettingere8b0f042003-05-28 14:05:34 +0000127
Benjamin Peterson4fd283a2010-06-25 23:24:35 +0000128 @support.cpython_only
Raymond Hettingere8b0f042003-05-28 14:05:34 +0000129 def test_tuple_reuse(self):
130 # Tests an implementation detail where tuple is reused
131 # whenever nothing else holds a reference to it
Raymond Hettingera690a992003-11-16 16:17:49 +0000132 self.assertEqual(len(set(map(id, list(enumerate(self.seq))))), len(self.seq))
133 self.assertEqual(len(set(map(id, enumerate(self.seq)))), min(1,len(self.seq)))
Guido van Rossum7dab2422002-04-26 19:40:56 +0000134
135class MyEnum(enumerate):
136 pass
137
138class SubclassTestCase(EnumerateTestCase):
139
140 enum = MyEnum
141
Raymond Hettingere8b0f042003-05-28 14:05:34 +0000142class TestEmpty(EnumerateTestCase):
143
144 seq, res = '', []
145
146class TestBig(EnumerateTestCase):
147
148 seq = range(10,20000,2)
Guido van Rossum801f0d72006-08-24 19:48:10 +0000149 res = list(zip(range(20000), seq))
Raymond Hettingere8b0f042003-05-28 14:05:34 +0000150
Kristján Valur Jónsson31668b82012-04-03 10:49:41 +0000151class TestReversed(unittest.TestCase, PickleTest):
Raymond Hettinger85c20a42003-11-06 14:06:48 +0000152
153 def test_simple(self):
154 class A:
155 def __getitem__(self, i):
156 if i < 5:
157 return str(i)
158 raise StopIteration
159 def __len__(self):
160 return 5
Guido van Rossum805365e2007-05-07 22:24:25 +0000161 for data in 'abc', range(5), tuple(enumerate('abc')), A(), range(1,17,5):
Raymond Hettinger85c20a42003-11-06 14:06:48 +0000162 self.assertEqual(list(data)[::-1], list(reversed(data)))
163 self.assertRaises(TypeError, reversed, {})
Alexandre Vassalottibee32532008-05-16 18:15:12 +0000164 # don't allow keyword arguments
165 self.assertRaises(TypeError, reversed, [], a=1)
Raymond Hettinger85c20a42003-11-06 14:06:48 +0000166
Guido van Rossum805365e2007-05-07 22:24:25 +0000167 def test_range_optimization(self):
168 x = range(1)
Raymond Hettinger85c20a42003-11-06 14:06:48 +0000169 self.assertEqual(type(reversed(x)), type(iter(x)))
Raymond Hettingere8b0f042003-05-28 14:05:34 +0000170
Benjamin Peterson4fd283a2010-06-25 23:24:35 +0000171 @support.cpython_only
Raymond Hettinger029dba52004-02-10 09:33:39 +0000172 def test_len(self):
Raymond Hettingerd2c36262004-03-10 08:32:47 +0000173 # This is an implementation detail, not an interface requirement
Raymond Hettinger6b27cda2005-09-24 21:23:05 +0000174 from test.test_iterlen import len
Guido van Rossum805365e2007-05-07 22:24:25 +0000175 for s in ('hello', tuple('hello'), list('hello'), range(5)):
Raymond Hettingeref9bf402004-03-10 10:10:42 +0000176 self.assertEqual(len(reversed(s)), len(s))
Raymond Hettingerff5dc0e2004-09-29 11:40:50 +0000177 r = reversed(s)
178 list(r)
179 self.assertEqual(len(r), 0)
180 class SeqWithWeirdLen:
181 called = False
182 def __len__(self):
183 if not self.called:
184 self.called = True
185 return 10
186 raise ZeroDivisionError
187 def __getitem__(self, index):
188 return index
189 r = reversed(SeqWithWeirdLen())
190 self.assertRaises(ZeroDivisionError, len, r)
191
192
193 def test_gc(self):
194 class Seq:
195 def __len__(self):
196 return 10
197 def __getitem__(self, index):
198 return index
199 s = Seq()
200 r = reversed(s)
201 s.r = r
202
203 def test_args(self):
204 self.assertRaises(TypeError, reversed)
205 self.assertRaises(TypeError, reversed, [], 'extra')
Raymond Hettinger029dba52004-02-10 09:33:39 +0000206
Michael W. Hudson0edc7a02005-07-12 10:21:19 +0000207 def test_bug1229429(self):
208 # this bug was never in reversed, it was in
209 # PyObject_CallMethod, and reversed_new calls that sometimes.
210 if not hasattr(sys, "getrefcount"):
211 return
212 def f():
213 pass
214 r = f.__reversed__ = object()
215 rc = sys.getrefcount(r)
216 for i in range(10):
217 try:
218 reversed(f)
219 except TypeError:
220 pass
221 else:
222 self.fail("non-callable __reversed__ didn't raise!")
223 self.assertEqual(rc, sys.getrefcount(r))
Tim Petersf5f32b42005-07-17 23:16:17 +0000224
Mark Dickinsonfb3dc942010-05-25 19:06:24 +0000225 def test_objmethods(self):
226 # Objects must have __len__() and __getitem__() implemented.
227 class NoLen(object):
228 def __getitem__(self): return 1
229 nl = NoLen()
230 self.assertRaises(TypeError, reversed, nl)
231
232 class NoGetItem(object):
233 def __len__(self): return 2
234 ngi = NoGetItem()
235 self.assertRaises(TypeError, reversed, ngi)
236
Kristján Valur Jónsson31668b82012-04-03 10:49:41 +0000237 def test_pickle(self):
238 for data in 'abc', range(5), tuple(enumerate('abc')), range(1,17,5):
239 self.check_pickle(reversed(data), list(data)[::-1])
240
Michael W. Hudson0edc7a02005-07-12 10:21:19 +0000241
Benjamin Peterson06507eb2010-05-08 16:51:16 +0000242class EnumerateStartTestCase(EnumerateTestCase):
Alexandre Vassalottie9f305f2008-05-16 04:39:54 +0000243
Benjamin Peterson06507eb2010-05-08 16:51:16 +0000244 def test_basicfunction(self):
245 e = self.enum(self.seq)
246 self.assertEqual(iter(e), e)
247 self.assertEqual(list(self.enum(self.seq)), self.res)
Alexandre Vassalottie9f305f2008-05-16 04:39:54 +0000248
249
Benjamin Peterson06507eb2010-05-08 16:51:16 +0000250class TestStart(EnumerateStartTestCase):
Alexandre Vassalottie9f305f2008-05-16 04:39:54 +0000251
Benjamin Peterson06507eb2010-05-08 16:51:16 +0000252 enum = lambda self, i: enumerate(i, start=11)
253 seq, res = 'abc', [(11, 'a'), (12, 'b'), (13, 'c')]
254
255
256class TestLongStart(EnumerateStartTestCase):
257
258 enum = lambda self, i: enumerate(i, start=sys.maxsize+1)
Alexandre Vassalottie9f305f2008-05-16 04:39:54 +0000259 seq, res = 'abc', [(sys.maxsize+1,'a'), (sys.maxsize+2,'b'),
260 (sys.maxsize+3,'c')]
261
262
Raymond Hettingere8b0f042003-05-28 14:05:34 +0000263def test_main(verbose=None):
Benjamin Peterson06507eb2010-05-08 16:51:16 +0000264 support.run_unittest(__name__)
Raymond Hettingere8b0f042003-05-28 14:05:34 +0000265
266 # verify reference counting
Raymond Hettingere8b0f042003-05-28 14:05:34 +0000267 if verbose and hasattr(sys, "gettotalrefcount"):
268 counts = [None] * 5
Guido van Rossum805365e2007-05-07 22:24:25 +0000269 for i in range(len(counts)):
Mark Dickinsonf43c3d32010-05-25 19:46:20 +0000270 support.run_unittest(__name__)
Raymond Hettingere8b0f042003-05-28 14:05:34 +0000271 counts[i] = sys.gettotalrefcount()
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000272 print(counts)
Guido van Rossum7dab2422002-04-26 19:40:56 +0000273
274if __name__ == "__main__":
Raymond Hettingere8b0f042003-05-28 14:05:34 +0000275 test_main(verbose=True)