blob: 5785cb46492ef7c65a7281f24065ccae0454ae6e [file] [log] [blame]
Guido van Rossum7dab2422002-04-26 19:40:56 +00001import unittest
Armin Ronacheraa9a79d2012-10-06 14:03:24 +02002import operator
Michael W. Hudson0edc7a02005-07-12 10:21:19 +00003import sys
Kristján Valur Jónsson31668b82012-04-03 10:49:41 +00004import pickle
Guido van Rossum7dab2422002-04-26 19:40:56 +00005
Benjamin Petersonee8712c2008-05-20 21:35:26 +00006from test import support
Guido van Rossum7dab2422002-04-26 19:40:56 +00007
Guido van Rossum7dab2422002-04-26 19:40:56 +00008class G:
9 'Sequence using __getitem__'
10 def __init__(self, seqn):
11 self.seqn = seqn
12 def __getitem__(self, i):
13 return self.seqn[i]
14
15class I:
16 'Sequence using iterator protocol'
17 def __init__(self, seqn):
18 self.seqn = seqn
19 self.i = 0
20 def __iter__(self):
21 return self
Georg Brandla18af4e2007-04-21 15:47:16 +000022 def __next__(self):
Guido van Rossum7dab2422002-04-26 19:40:56 +000023 if self.i >= len(self.seqn): raise StopIteration
24 v = self.seqn[self.i]
25 self.i += 1
26 return v
27
28class Ig:
29 'Sequence using iterator protocol defined with a generator'
30 def __init__(self, seqn):
31 self.seqn = seqn
32 self.i = 0
33 def __iter__(self):
34 for val in self.seqn:
35 yield val
36
37class X:
38 'Missing __getitem__ and __iter__'
39 def __init__(self, seqn):
40 self.seqn = seqn
41 self.i = 0
Georg Brandla18af4e2007-04-21 15:47:16 +000042 def __next__(self):
Guido van Rossum7dab2422002-04-26 19:40:56 +000043 if self.i >= len(self.seqn): raise StopIteration
44 v = self.seqn[self.i]
45 self.i += 1
46 return v
47
48class E:
49 'Test propagation of exceptions'
50 def __init__(self, seqn):
51 self.seqn = seqn
52 self.i = 0
53 def __iter__(self):
54 return self
Georg Brandla18af4e2007-04-21 15:47:16 +000055 def __next__(self):
Raymond Hettingerffdb8bb2004-09-27 15:29:05 +000056 3 // 0
Guido van Rossum7dab2422002-04-26 19:40:56 +000057
58class N:
Georg Brandla18af4e2007-04-21 15:47:16 +000059 'Iterator missing __next__()'
Guido van Rossum7dab2422002-04-26 19:40:56 +000060 def __init__(self, seqn):
61 self.seqn = seqn
62 self.i = 0
63 def __iter__(self):
64 return self
65
Kristján Valur Jónsson31668b82012-04-03 10:49:41 +000066class PickleTest:
67 # Helper to check picklability
68 def check_pickle(self, itorg, seq):
Serhiy Storchakabad12572014-12-15 14:03:42 +020069 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
70 d = pickle.dumps(itorg, proto)
71 it = pickle.loads(d)
72 self.assertEqual(type(itorg), type(it))
73 self.assertEqual(list(it), seq)
Kristján Valur Jónsson31668b82012-04-03 10:49:41 +000074
Serhiy Storchakabad12572014-12-15 14:03:42 +020075 it = pickle.loads(d)
76 try:
77 next(it)
78 except StopIteration:
79 self.assertFalse(seq[1:])
80 continue
81 d = pickle.dumps(it, proto)
82 it = pickle.loads(d)
83 self.assertEqual(list(it), seq[1:])
Kristján Valur Jónsson31668b82012-04-03 10:49:41 +000084
85class EnumerateTestCase(unittest.TestCase, PickleTest):
Guido van Rossum7dab2422002-04-26 19:40:56 +000086
87 enum = enumerate
Raymond Hettingere8b0f042003-05-28 14:05:34 +000088 seq, res = 'abc', [(0,'a'), (1,'b'), (2,'c')]
Guido van Rossum7dab2422002-04-26 19:40:56 +000089
90 def test_basicfunction(self):
Raymond Hettingere8b0f042003-05-28 14:05:34 +000091 self.assertEqual(type(self.enum(self.seq)), self.enum)
92 e = self.enum(self.seq)
Guido van Rossum7dab2422002-04-26 19:40:56 +000093 self.assertEqual(iter(e), e)
Raymond Hettingere8b0f042003-05-28 14:05:34 +000094 self.assertEqual(list(self.enum(self.seq)), self.res)
Guido van Rossum7dab2422002-04-26 19:40:56 +000095 self.enum.__doc__
96
Kristján Valur Jónsson31668b82012-04-03 10:49:41 +000097 def test_pickle(self):
98 self.check_pickle(self.enum(self.seq), self.res)
99
Guido van Rossum7dab2422002-04-26 19:40:56 +0000100 def test_getitemseqn(self):
Raymond Hettingere8b0f042003-05-28 14:05:34 +0000101 self.assertEqual(list(self.enum(G(self.seq))), self.res)
Guido van Rossum7dab2422002-04-26 19:40:56 +0000102 e = self.enum(G(''))
Georg Brandla18af4e2007-04-21 15:47:16 +0000103 self.assertRaises(StopIteration, next, e)
Guido van Rossum7dab2422002-04-26 19:40:56 +0000104
105 def test_iteratorseqn(self):
Raymond Hettingere8b0f042003-05-28 14:05:34 +0000106 self.assertEqual(list(self.enum(I(self.seq))), self.res)
Guido van Rossum7dab2422002-04-26 19:40:56 +0000107 e = self.enum(I(''))
Georg Brandla18af4e2007-04-21 15:47:16 +0000108 self.assertRaises(StopIteration, next, e)
Guido van Rossum7dab2422002-04-26 19:40:56 +0000109
110 def test_iteratorgenerator(self):
Raymond Hettingere8b0f042003-05-28 14:05:34 +0000111 self.assertEqual(list(self.enum(Ig(self.seq))), self.res)
Guido van Rossum7dab2422002-04-26 19:40:56 +0000112 e = self.enum(Ig(''))
Georg Brandla18af4e2007-04-21 15:47:16 +0000113 self.assertRaises(StopIteration, next, e)
Guido van Rossum7dab2422002-04-26 19:40:56 +0000114
115 def test_noniterable(self):
Raymond Hettingere8b0f042003-05-28 14:05:34 +0000116 self.assertRaises(TypeError, self.enum, X(self.seq))
Guido van Rossum7dab2422002-04-26 19:40:56 +0000117
118 def test_illformediterable(self):
Thomas Wouters1034dad2006-04-15 09:16:16 +0000119 self.assertRaises(TypeError, self.enum, N(self.seq))
Guido van Rossum7dab2422002-04-26 19:40:56 +0000120
121 def test_exception_propagation(self):
Raymond Hettingere8b0f042003-05-28 14:05:34 +0000122 self.assertRaises(ZeroDivisionError, list, self.enum(E(self.seq)))
123
124 def test_argumentcheck(self):
125 self.assertRaises(TypeError, self.enum) # no arguments
126 self.assertRaises(TypeError, self.enum, 1) # wrong type (not iterable)
Alexandre Vassalottie9f305f2008-05-16 04:39:54 +0000127 self.assertRaises(TypeError, self.enum, 'abc', 'a') # wrong type
128 self.assertRaises(TypeError, self.enum, 'abc', 2, 3) # too many arguments
Raymond Hettingere8b0f042003-05-28 14:05:34 +0000129
Benjamin Peterson4fd283a2010-06-25 23:24:35 +0000130 @support.cpython_only
Raymond Hettingere8b0f042003-05-28 14:05:34 +0000131 def test_tuple_reuse(self):
132 # Tests an implementation detail where tuple is reused
133 # whenever nothing else holds a reference to it
Raymond Hettingera690a992003-11-16 16:17:49 +0000134 self.assertEqual(len(set(map(id, list(enumerate(self.seq))))), len(self.seq))
135 self.assertEqual(len(set(map(id, enumerate(self.seq)))), min(1,len(self.seq)))
Guido van Rossum7dab2422002-04-26 19:40:56 +0000136
137class MyEnum(enumerate):
138 pass
139
140class SubclassTestCase(EnumerateTestCase):
141
142 enum = MyEnum
143
Raymond Hettingere8b0f042003-05-28 14:05:34 +0000144class TestEmpty(EnumerateTestCase):
145
146 seq, res = '', []
147
148class TestBig(EnumerateTestCase):
149
150 seq = range(10,20000,2)
Guido van Rossum801f0d72006-08-24 19:48:10 +0000151 res = list(zip(range(20000), seq))
Raymond Hettingere8b0f042003-05-28 14:05:34 +0000152
Kristján Valur Jónsson31668b82012-04-03 10:49:41 +0000153class TestReversed(unittest.TestCase, PickleTest):
Raymond Hettinger85c20a42003-11-06 14:06:48 +0000154
155 def test_simple(self):
156 class A:
157 def __getitem__(self, i):
158 if i < 5:
159 return str(i)
160 raise StopIteration
161 def __len__(self):
162 return 5
Rémi Lapeyre6531bf62018-11-06 01:38:54 +0100163 for data in ('abc', range(5), tuple(enumerate('abc')), A(),
164 range(1,17,5), dict.fromkeys('abcde')):
Raymond Hettinger85c20a42003-11-06 14:06:48 +0000165 self.assertEqual(list(data)[::-1], list(reversed(data)))
Alexandre Vassalottibee32532008-05-16 18:15:12 +0000166 # don't allow keyword arguments
167 self.assertRaises(TypeError, reversed, [], a=1)
Raymond Hettinger85c20a42003-11-06 14:06:48 +0000168
Guido van Rossum805365e2007-05-07 22:24:25 +0000169 def test_range_optimization(self):
170 x = range(1)
Raymond Hettinger85c20a42003-11-06 14:06:48 +0000171 self.assertEqual(type(reversed(x)), type(iter(x)))
Raymond Hettingere8b0f042003-05-28 14:05:34 +0000172
Raymond Hettinger029dba52004-02-10 09:33:39 +0000173 def test_len(self):
Guido van Rossum805365e2007-05-07 22:24:25 +0000174 for s in ('hello', tuple('hello'), list('hello'), range(5)):
Armin Ronacheraa9a79d2012-10-06 14:03:24 +0200175 self.assertEqual(operator.length_hint(reversed(s)), len(s))
Raymond Hettingerff5dc0e2004-09-29 11:40:50 +0000176 r = reversed(s)
177 list(r)
Armin Ronacheraa9a79d2012-10-06 14:03:24 +0200178 self.assertEqual(operator.length_hint(r), 0)
Raymond Hettingerff5dc0e2004-09-29 11:40:50 +0000179 class SeqWithWeirdLen:
180 called = False
181 def __len__(self):
182 if not self.called:
183 self.called = True
184 return 10
185 raise ZeroDivisionError
186 def __getitem__(self, index):
187 return index
188 r = reversed(SeqWithWeirdLen())
Armin Ronacheraa9a79d2012-10-06 14:03:24 +0200189 self.assertRaises(ZeroDivisionError, operator.length_hint, r)
Raymond Hettingerff5dc0e2004-09-29 11:40:50 +0000190
191
192 def test_gc(self):
193 class Seq:
194 def __len__(self):
195 return 10
196 def __getitem__(self, index):
197 return index
198 s = Seq()
199 r = reversed(s)
200 s.r = r
201
202 def test_args(self):
203 self.assertRaises(TypeError, reversed)
204 self.assertRaises(TypeError, reversed, [], 'extra')
Raymond Hettinger029dba52004-02-10 09:33:39 +0000205
Serhiy Storchaka43767632013-11-03 21:31:38 +0200206 @unittest.skipUnless(hasattr(sys, 'getrefcount'), 'test needs sys.getrefcount()')
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.
Michael W. Hudson0edc7a02005-07-12 10:21:19 +0000210 def f():
211 pass
212 r = f.__reversed__ = object()
213 rc = sys.getrefcount(r)
214 for i in range(10):
215 try:
216 reversed(f)
217 except TypeError:
218 pass
219 else:
220 self.fail("non-callable __reversed__ didn't raise!")
221 self.assertEqual(rc, sys.getrefcount(r))
Tim Petersf5f32b42005-07-17 23:16:17 +0000222
Mark Dickinsonfb3dc942010-05-25 19:06:24 +0000223 def test_objmethods(self):
224 # Objects must have __len__() and __getitem__() implemented.
225 class NoLen(object):
Guido van Rossum97c1adf2016-08-18 09:22:23 -0700226 def __getitem__(self, i): return 1
Mark Dickinsonfb3dc942010-05-25 19:06:24 +0000227 nl = NoLen()
228 self.assertRaises(TypeError, reversed, nl)
229
230 class NoGetItem(object):
231 def __len__(self): return 2
232 ngi = NoGetItem()
233 self.assertRaises(TypeError, reversed, ngi)
234
Guido van Rossum97c1adf2016-08-18 09:22:23 -0700235 class Blocked(object):
236 def __getitem__(self, i): return 1
237 def __len__(self): return 2
238 __reversed__ = None
239 b = Blocked()
240 self.assertRaises(TypeError, reversed, b)
241
Kristján Valur Jónsson31668b82012-04-03 10:49:41 +0000242 def test_pickle(self):
243 for data in 'abc', range(5), tuple(enumerate('abc')), range(1,17,5):
244 self.check_pickle(reversed(data), list(data)[::-1])
245
Michael W. Hudson0edc7a02005-07-12 10:21:19 +0000246
Benjamin Peterson06507eb2010-05-08 16:51:16 +0000247class EnumerateStartTestCase(EnumerateTestCase):
Alexandre Vassalottie9f305f2008-05-16 04:39:54 +0000248
Benjamin Peterson06507eb2010-05-08 16:51:16 +0000249 def test_basicfunction(self):
250 e = self.enum(self.seq)
251 self.assertEqual(iter(e), e)
252 self.assertEqual(list(self.enum(self.seq)), self.res)
Alexandre Vassalottie9f305f2008-05-16 04:39:54 +0000253
254
Benjamin Peterson06507eb2010-05-08 16:51:16 +0000255class TestStart(EnumerateStartTestCase):
Alexandre Vassalottie9f305f2008-05-16 04:39:54 +0000256
Benjamin Peterson06507eb2010-05-08 16:51:16 +0000257 enum = lambda self, i: enumerate(i, start=11)
258 seq, res = 'abc', [(11, 'a'), (12, 'b'), (13, 'c')]
259
260
261class TestLongStart(EnumerateStartTestCase):
262
263 enum = lambda self, i: enumerate(i, start=sys.maxsize+1)
Alexandre Vassalottie9f305f2008-05-16 04:39:54 +0000264 seq, res = 'abc', [(sys.maxsize+1,'a'), (sys.maxsize+2,'b'),
265 (sys.maxsize+3,'c')]
266
267
Guido van Rossum7dab2422002-04-26 19:40:56 +0000268if __name__ == "__main__":
Zachary Ware38c707e2015-04-13 15:00:43 -0500269 unittest.main()