| 
									
										
										
										
											2002-04-26 19:40:56 +00:00
										 |  |  | import unittest | 
					
						
							| 
									
										
										
										
											2005-07-12 10:21:19 +00:00
										 |  |  | import sys | 
					
						
							| 
									
										
										
										
											2002-04-26 19:40:56 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-23 19:04:11 +00:00
										 |  |  | from test import test_support | 
					
						
							| 
									
										
										
										
											2002-04-26 19:40:56 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 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 E: | 
					
						
							|  |  |  |     'Test propagation of exceptions' | 
					
						
							|  |  |  |     def __init__(self, seqn): | 
					
						
							|  |  |  |         self.seqn = seqn | 
					
						
							|  |  |  |         self.i = 0 | 
					
						
							|  |  |  |     def __iter__(self): | 
					
						
							|  |  |  |         return self | 
					
						
							|  |  |  |     def next(self): | 
					
						
							| 
									
										
										
										
											2004-09-27 15:29:05 +00:00
										 |  |  |         3 // 0 | 
					
						
							| 
									
										
										
										
											2002-04-26 19:40:56 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | class N: | 
					
						
							|  |  |  |     'Iterator missing next()' | 
					
						
							|  |  |  |     def __init__(self, seqn): | 
					
						
							|  |  |  |         self.seqn = seqn | 
					
						
							|  |  |  |         self.i = 0 | 
					
						
							|  |  |  |     def __iter__(self): | 
					
						
							|  |  |  |         return self | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class EnumerateTestCase(unittest.TestCase): | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     enum = enumerate | 
					
						
							| 
									
										
										
										
											2003-05-28 14:05:34 +00:00
										 |  |  |     seq, res = 'abc', [(0,'a'), (1,'b'), (2,'c')] | 
					
						
							| 
									
										
										
										
											2002-04-26 19:40:56 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def test_basicfunction(self): | 
					
						
							| 
									
										
										
										
											2003-05-28 14:05:34 +00:00
										 |  |  |         self.assertEqual(type(self.enum(self.seq)), self.enum) | 
					
						
							|  |  |  |         e = self.enum(self.seq) | 
					
						
							| 
									
										
										
										
											2002-04-26 19:40:56 +00:00
										 |  |  |         self.assertEqual(iter(e), e) | 
					
						
							| 
									
										
										
										
											2003-05-28 14:05:34 +00:00
										 |  |  |         self.assertEqual(list(self.enum(self.seq)), self.res) | 
					
						
							| 
									
										
										
										
											2002-04-26 19:40:56 +00:00
										 |  |  |         self.enum.__doc__ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_getitemseqn(self): | 
					
						
							| 
									
										
										
										
											2003-05-28 14:05:34 +00:00
										 |  |  |         self.assertEqual(list(self.enum(G(self.seq))), self.res) | 
					
						
							| 
									
										
										
										
											2002-04-26 19:40:56 +00:00
										 |  |  |         e = self.enum(G('')) | 
					
						
							|  |  |  |         self.assertRaises(StopIteration, e.next) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_iteratorseqn(self): | 
					
						
							| 
									
										
										
										
											2003-05-28 14:05:34 +00:00
										 |  |  |         self.assertEqual(list(self.enum(I(self.seq))), self.res) | 
					
						
							| 
									
										
										
										
											2002-04-26 19:40:56 +00:00
										 |  |  |         e = self.enum(I('')) | 
					
						
							|  |  |  |         self.assertRaises(StopIteration, e.next) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_iteratorgenerator(self): | 
					
						
							| 
									
										
										
										
											2003-05-28 14:05:34 +00:00
										 |  |  |         self.assertEqual(list(self.enum(Ig(self.seq))), self.res) | 
					
						
							| 
									
										
										
										
											2002-04-26 19:40:56 +00:00
										 |  |  |         e = self.enum(Ig('')) | 
					
						
							|  |  |  |         self.assertRaises(StopIteration, e.next) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_noniterable(self): | 
					
						
							| 
									
										
										
										
											2003-05-28 14:05:34 +00:00
										 |  |  |         self.assertRaises(TypeError, self.enum, X(self.seq)) | 
					
						
							| 
									
										
										
										
											2002-04-26 19:40:56 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def test_illformediterable(self): | 
					
						
							| 
									
										
										
										
											2003-05-28 14:05:34 +00:00
										 |  |  |         self.assertRaises(TypeError, list, self.enum(N(self.seq))) | 
					
						
							| 
									
										
										
										
											2002-04-26 19:40:56 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def test_exception_propagation(self): | 
					
						
							| 
									
										
										
										
											2003-05-28 14:05:34 +00:00
										 |  |  |         self.assertRaises(ZeroDivisionError, list, self.enum(E(self.seq))) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_argumentcheck(self): | 
					
						
							|  |  |  |         self.assertRaises(TypeError, self.enum) # no arguments | 
					
						
							|  |  |  |         self.assertRaises(TypeError, self.enum, 1) # wrong type (not iterable) | 
					
						
							| 
									
										
										
										
											2008-05-13 19:04:54 +00:00
										 |  |  |         self.assertRaises(TypeError, self.enum, 'abc', 'a') # wrong type | 
					
						
							|  |  |  |         self.assertRaises(TypeError, self.enum, 'abc', 2, 3) # too many arguments | 
					
						
							| 
									
										
										
										
											2003-05-28 14:05:34 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def test_tuple_reuse(self): | 
					
						
							|  |  |  |         # Tests an implementation detail where tuple is reused | 
					
						
							|  |  |  |         # whenever nothing else holds a reference to it | 
					
						
							| 
									
										
										
										
											2003-11-16 16:17:49 +00:00
										 |  |  |         self.assertEqual(len(set(map(id, list(enumerate(self.seq))))), len(self.seq)) | 
					
						
							|  |  |  |         self.assertEqual(len(set(map(id, enumerate(self.seq)))), min(1,len(self.seq))) | 
					
						
							| 
									
										
										
										
											2002-04-26 19:40:56 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | class MyEnum(enumerate): | 
					
						
							|  |  |  |     pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class SubclassTestCase(EnumerateTestCase): | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     enum = MyEnum | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-05-28 14:05:34 +00:00
										 |  |  | class TestEmpty(EnumerateTestCase): | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     seq, res = '', [] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class TestBig(EnumerateTestCase): | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     seq = range(10,20000,2) | 
					
						
							|  |  |  |     res = zip(range(20000), seq) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-11-06 14:06:48 +00:00
										 |  |  | class TestReversed(unittest.TestCase): | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_simple(self): | 
					
						
							|  |  |  |         class A: | 
					
						
							|  |  |  |             def __getitem__(self, i): | 
					
						
							|  |  |  |                 if i < 5: | 
					
						
							|  |  |  |                     return str(i) | 
					
						
							|  |  |  |                 raise StopIteration | 
					
						
							|  |  |  |             def __len__(self): | 
					
						
							|  |  |  |                 return 5 | 
					
						
							|  |  |  |         for data in 'abc', range(5), tuple(enumerate('abc')), A(), xrange(1,17,5): | 
					
						
							|  |  |  |             self.assertEqual(list(data)[::-1], list(reversed(data))) | 
					
						
							|  |  |  |         self.assertRaises(TypeError, reversed, {}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_xrange_optimization(self): | 
					
						
							|  |  |  |         x = xrange(1) | 
					
						
							|  |  |  |         self.assertEqual(type(reversed(x)), type(iter(x))) | 
					
						
							| 
									
										
										
										
											2003-05-28 14:05:34 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-02-10 09:33:39 +00:00
										 |  |  |     def test_len(self): | 
					
						
							| 
									
										
										
										
											2004-03-10 08:32:47 +00:00
										 |  |  |         # This is an implementation detail, not an interface requirement | 
					
						
							| 
									
										
										
										
											2005-09-24 21:23:05 +00:00
										 |  |  |         from test.test_iterlen import len | 
					
						
							| 
									
										
										
										
											2004-03-10 10:10:42 +00:00
										 |  |  |         for s in ('hello', tuple('hello'), list('hello'), xrange(5)): | 
					
						
							|  |  |  |             self.assertEqual(len(reversed(s)), len(s)) | 
					
						
							| 
									
										
										
										
											2004-09-29 11:40:50 +00:00
										 |  |  |             r = reversed(s) | 
					
						
							|  |  |  |             list(r) | 
					
						
							|  |  |  |             self.assertEqual(len(r), 0) | 
					
						
							|  |  |  |         class SeqWithWeirdLen: | 
					
						
							|  |  |  |             called = False | 
					
						
							|  |  |  |             def __len__(self): | 
					
						
							|  |  |  |                 if not self.called: | 
					
						
							|  |  |  |                     self.called = True | 
					
						
							|  |  |  |                     return 10 | 
					
						
							|  |  |  |                 raise ZeroDivisionError | 
					
						
							|  |  |  |             def __getitem__(self, index): | 
					
						
							|  |  |  |                 return index | 
					
						
							|  |  |  |         r = reversed(SeqWithWeirdLen()) | 
					
						
							|  |  |  |         self.assertRaises(ZeroDivisionError, len, r) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_gc(self): | 
					
						
							|  |  |  |         class Seq: | 
					
						
							|  |  |  |             def __len__(self): | 
					
						
							|  |  |  |                 return 10 | 
					
						
							|  |  |  |             def __getitem__(self, index): | 
					
						
							|  |  |  |                 return index | 
					
						
							|  |  |  |         s = Seq() | 
					
						
							|  |  |  |         r = reversed(s) | 
					
						
							|  |  |  |         s.r = r | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_args(self): | 
					
						
							|  |  |  |         self.assertRaises(TypeError, reversed) | 
					
						
							|  |  |  |         self.assertRaises(TypeError, reversed, [], 'extra') | 
					
						
							| 
									
										
										
										
											2004-02-10 09:33:39 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-07-12 10:21:19 +00:00
										 |  |  |     def test_bug1229429(self): | 
					
						
							|  |  |  |         # this bug was never in reversed, it was in | 
					
						
							|  |  |  |         # PyObject_CallMethod, and reversed_new calls that sometimes. | 
					
						
							|  |  |  |         if not hasattr(sys, "getrefcount"): | 
					
						
							|  |  |  |             return | 
					
						
							|  |  |  |         def f(): | 
					
						
							|  |  |  |             pass | 
					
						
							|  |  |  |         r = f.__reversed__ = object() | 
					
						
							|  |  |  |         rc = sys.getrefcount(r) | 
					
						
							|  |  |  |         for i in range(10): | 
					
						
							|  |  |  |             try: | 
					
						
							|  |  |  |                 reversed(f) | 
					
						
							|  |  |  |             except TypeError: | 
					
						
							|  |  |  |                 pass | 
					
						
							|  |  |  |             else: | 
					
						
							|  |  |  |                 self.fail("non-callable __reversed__ didn't raise!") | 
					
						
							|  |  |  |         self.assertEqual(rc, sys.getrefcount(r)) | 
					
						
							| 
									
										
										
										
											2005-07-17 23:16:17 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-07-12 10:21:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-13 19:04:54 +00:00
										 |  |  | class TestStart(EnumerateTestCase): | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     enum = lambda i: enumerate(i, start=11) | 
					
						
							|  |  |  |     seq, res = 'abc', [(1, 'a'), (2, 'b'), (3, 'c')] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class TestLongStart(EnumerateTestCase): | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     enum = lambda i: enumerate(i, start=sys.maxint+1) | 
					
						
							|  |  |  |     seq, res = 'abc', [(sys.maxint+1,'a'), (sys.maxint+2,'b'), | 
					
						
							|  |  |  |                        (sys.maxint+3,'c')] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-05-28 14:05:34 +00:00
										 |  |  | def test_main(verbose=None): | 
					
						
							| 
									
										
										
										
											2003-11-06 14:06:48 +00:00
										 |  |  |     testclasses = (EnumerateTestCase, SubclassTestCase, TestEmpty, TestBig, | 
					
						
							|  |  |  |                    TestReversed) | 
					
						
							| 
									
										
										
										
											2003-05-28 14:05:34 +00:00
										 |  |  |     test_support.run_unittest(*testclasses) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # verify reference counting | 
					
						
							|  |  |  |     import sys | 
					
						
							|  |  |  |     if verbose and hasattr(sys, "gettotalrefcount"): | 
					
						
							|  |  |  |         counts = [None] * 5 | 
					
						
							|  |  |  |         for i in xrange(len(counts)): | 
					
						
							|  |  |  |             test_support.run_unittest(*testclasses) | 
					
						
							|  |  |  |             counts[i] = sys.gettotalrefcount() | 
					
						
							|  |  |  |         print counts | 
					
						
							| 
									
										
										
										
											2002-04-26 19:40:56 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | if __name__ == "__main__": | 
					
						
							| 
									
										
										
										
											2003-05-28 14:05:34 +00:00
										 |  |  |     test_main(verbose=True) |