| OLD | NEW |
| 1 import unittest | 1 import unittest |
| 2 import sys | 2 import sys |
| 3 | 3 |
| 4 from test import test_support | 4 from test import test_support |
| 5 | 5 |
| 6 class G: | 6 class G: |
| 7 'Sequence using __getitem__' | 7 'Sequence using __getitem__' |
| 8 def __init__(self, seqn): | 8 def __init__(self, seqn): |
| 9 self.seqn = seqn | 9 self.seqn = seqn |
| 10 def __getitem__(self, i): | 10 def __getitem__(self, i): |
| 11 return self.seqn[i] | 11 return self.seqn[i] |
| 12 | 12 |
| 13 class I: | 13 class I: |
| 14 'Sequence using iterator protocol' | 14 'Sequence using iterator protocol' |
| 15 def __init__(self, seqn): | 15 def __init__(self, seqn): |
| 16 self.seqn = seqn | 16 self.seqn = seqn |
| 17 self.i = 0 | 17 self.i = 0 |
| 18 def __iter__(self): | 18 def __iter__(self): |
| 19 return self | 19 return self |
| 20 def __next__(self): | 20 def __next__(self): |
| 21 if self.i >= len(self.seqn): raise StopIteration | 21 if self.i >= len(self.seqn): raise StopIteration |
| 22 v = self.seqn[self.i] | 22 v = self.seqn[self.i] |
| 23 self.i += 1 | 23 self.i += 1 |
| 24 return v | 24 return v |
| 25 | 25 |
| 26 class Ig: | 26 class Ig: |
| 27 'Sequence using iterator protocol defined with a generator' | 27 'Sequence using iterator protocol defined with a generator' |
| 28 def __init__(self, seqn): | 28 def __init__(self, seqn): |
| 29 self.seqn = seqn | 29 self.seqn = seqn |
| 30 self.i = 0 | 30 self.i = 0 |
| 31 def __iter__(self): | 31 def __iter__(self): |
| 32 for val in self.seqn: | 32 for val in self.seqn: |
| 33 yield val | 33 yield val |
| 34 | 34 |
| 35 class X: | 35 class X: |
| 36 'Missing __getitem__ and __iter__' | 36 'Missing __getitem__ and __iter__' |
| 37 def __init__(self, seqn): | 37 def __init__(self, seqn): |
| 38 self.seqn = seqn | 38 self.seqn = seqn |
| 39 self.i = 0 | 39 self.i = 0 |
| 40 def __next__(self): | 40 def __next__(self): |
| 41 if self.i >= len(self.seqn): raise StopIteration | 41 if self.i >= len(self.seqn): raise StopIteration |
| 42 v = self.seqn[self.i] | 42 v = self.seqn[self.i] |
| 43 self.i += 1 | 43 self.i += 1 |
| 44 return v | 44 return v |
| 45 | 45 |
| 46 class E: | 46 class E: |
| 47 'Test propagation of exceptions' | 47 'Test propagation of exceptions' |
| 48 def __init__(self, seqn): | 48 def __init__(self, seqn): |
| 49 self.seqn = seqn | 49 self.seqn = seqn |
| 50 self.i = 0 | 50 self.i = 0 |
| 51 def __iter__(self): | 51 def __iter__(self): |
| 52 return self | 52 return self |
| 53 def __next__(self): | 53 def __next__(self): |
| 54 3 // 0 | 54 3 // 0 |
| 55 | 55 |
| 56 class N: | 56 class N: |
| 57 'Iterator missing __next__()' | 57 'Iterator missing __next__()' |
| 58 def __init__(self, seqn): | 58 def __init__(self, seqn): |
| 59 self.seqn = seqn | 59 self.seqn = seqn |
| 60 self.i = 0 | 60 self.i = 0 |
| 61 def __iter__(self): | 61 def __iter__(self): |
| 62 return self | 62 return self |
| 63 | 63 |
| 64 class EnumerateTestCase(unittest.TestCase): | 64 class EnumerateTestCase(unittest.TestCase): |
| 65 | 65 |
| 66 enum = enumerate | 66 enum = enumerate |
| 67 seq, res = 'abc', [(0,'a'), (1,'b'), (2,'c')] | 67 seq, res = 'abc', [(0,'a'), (1,'b'), (2,'c')] |
| 68 | 68 |
| 69 def test_basicfunction(self): | 69 def test_basicfunction(self): |
| 70 self.assertEqual(type(self.enum(self.seq)), self.enum) | 70 self.assertEqual(type(self.enum(self.seq)), self.enum) |
| 71 e = self.enum(self.seq) | 71 e = self.enum(self.seq) |
| 72 self.assertEqual(iter(e), e) | 72 self.assertEqual(iter(e), e) |
| 73 self.assertEqual(list(self.enum(self.seq)), self.res) | 73 self.assertEqual(list(self.enum(self.seq)), self.res) |
| 74 self.enum.__doc__ | 74 self.enum.__doc__ |
| 75 | 75 |
| 76 def test_getitemseqn(self): | 76 def test_getitemseqn(self): |
| 77 self.assertEqual(list(self.enum(G(self.seq))), self.res) | 77 self.assertEqual(list(self.enum(G(self.seq))), self.res) |
| 78 e = self.enum(G('')) | 78 e = self.enum(G('')) |
| 79 self.assertRaises(StopIteration, next, e) | 79 self.assertRaises(StopIteration, next, e) |
| 80 | 80 |
| 81 def test_iteratorseqn(self): | 81 def test_iteratorseqn(self): |
| 82 self.assertEqual(list(self.enum(I(self.seq))), self.res) | 82 self.assertEqual(list(self.enum(I(self.seq))), self.res) |
| 83 e = self.enum(I('')) | 83 e = self.enum(I('')) |
| 84 self.assertRaises(StopIteration, next, e) | 84 self.assertRaises(StopIteration, next, e) |
| 85 | 85 |
| 86 def test_iteratorgenerator(self): | 86 def test_iteratorgenerator(self): |
| 87 self.assertEqual(list(self.enum(Ig(self.seq))), self.res) | 87 self.assertEqual(list(self.enum(Ig(self.seq))), self.res) |
| 88 e = self.enum(Ig('')) | 88 e = self.enum(Ig('')) |
| 89 self.assertRaises(StopIteration, next, e) | 89 self.assertRaises(StopIteration, next, e) |
| 90 | 90 |
| 91 def test_noniterable(self): | 91 def test_noniterable(self): |
| 92 self.assertRaises(TypeError, self.enum, X(self.seq)) | 92 self.assertRaises(TypeError, self.enum, X(self.seq)) |
| 93 | 93 |
| 94 def test_illformediterable(self): | 94 def test_illformediterable(self): |
| 95 self.assertRaises(TypeError, self.enum, N(self.seq)) | 95 self.assertRaises(TypeError, self.enum, N(self.seq)) |
| 96 | 96 |
| 97 def test_exception_propagation(self): | 97 def test_exception_propagation(self): |
| 98 self.assertRaises(ZeroDivisionError, list, self.enum(E(self.seq))) | 98 self.assertRaises(ZeroDivisionError, list, self.enum(E(self.seq))) |
| 99 | 99 |
| 100 def test_argumentcheck(self): | 100 def test_argumentcheck(self): |
| 101 self.assertRaises(TypeError, self.enum) # no arguments | 101 self.assertRaises(TypeError, self.enum) # no arguments |
| 102 self.assertRaises(TypeError, self.enum, 1) # wrong type (not iterable) | 102 self.assertRaises(TypeError, self.enum, 1) # wrong type (not iterable) |
| 103 self.assertRaises(TypeError, self.enum, 'abc', 2) # too many arguments | 103 self.assertRaises(TypeError, self.enum, 'abc', 2) # too many arguments |
| 104 | 104 |
| 105 def test_tuple_reuse(self): | 105 def test_tuple_reuse(self): |
| 106 # Tests an implementation detail where tuple is reused | 106 # Tests an implementation detail where tuple is reused |
| 107 # whenever nothing else holds a reference to it | 107 # whenever nothing else holds a reference to it |
| 108 self.assertEqual(len(set(map(id, list(enumerate(self.seq))))), len(self.
seq)) | 108 self.assertEqual(len(set(map(id, list(enumerate(self.seq))))), len(self.
seq)) |
| 109 self.assertEqual(len(set(map(id, enumerate(self.seq)))), min(1,len(self.
seq))) | 109 self.assertEqual(len(set(map(id, enumerate(self.seq)))), min(1,len(self.
seq))) |
| 110 | 110 |
| 111 class MyEnum(enumerate): | 111 class MyEnum(enumerate): |
| 112 pass | 112 pass |
| 113 | 113 |
| 114 class SubclassTestCase(EnumerateTestCase): | 114 class SubclassTestCase(EnumerateTestCase): |
| 115 | 115 |
| 116 enum = MyEnum | 116 enum = MyEnum |
| 117 | 117 |
| 118 class TestEmpty(EnumerateTestCase): | 118 class TestEmpty(EnumerateTestCase): |
| 119 | 119 |
| 120 seq, res = '', [] | 120 seq, res = '', [] |
| 121 | 121 |
| 122 class TestBig(EnumerateTestCase): | 122 class TestBig(EnumerateTestCase): |
| 123 | 123 |
| 124 seq = range(10,20000,2) | 124 seq = list(range(10,20000,2)) |
| 125 res = list(zip(range(20000), seq)) | 125 res = list(zip(range(20000), seq)) |
| 126 | 126 |
| 127 class TestReversed(unittest.TestCase): | 127 class TestReversed(unittest.TestCase): |
| 128 | 128 |
| 129 def test_simple(self): | 129 def test_simple(self): |
| 130 class A: | 130 class A: |
| 131 def __getitem__(self, i): | 131 def __getitem__(self, i): |
| 132 if i < 5: | 132 if i < 5: |
| 133 return str(i) | 133 return str(i) |
| 134 raise StopIteration | 134 raise StopIteration |
| 135 def __len__(self): | 135 def __len__(self): |
| 136 return 5 | 136 return 5 |
| 137 for data in 'abc', range(5), tuple(enumerate('abc')), A(), range(1,17,5)
: | 137 for data in 'abc', range(5), tuple(enumerate('abc')), A(), range(1,17,5)
: |
| 138 self.assertEqual(list(data)[::-1], list(reversed(data))) | 138 self.assertEqual(list(data)[::-1], list(reversed(data))) |
| 139 self.assertRaises(TypeError, reversed, {}) | 139 self.assertRaises(TypeError, reversed, {}) |
| 140 | 140 |
| 141 def test_range_optimization(self): | 141 def test_range_optimization(self): |
| 142 x = range(1) | 142 x = range(1) |
| 143 self.assertEqual(type(reversed(x)), type(iter(x))) | 143 self.assertEqual(type(reversed(x)), type(iter(x))) |
| 144 | 144 |
| 145 def test_len(self): | 145 def test_len(self): |
| 146 # This is an implementation detail, not an interface requirement | 146 # This is an implementation detail, not an interface requirement |
| 147 from test.test_iterlen import len | 147 from test.test_iterlen import len |
| 148 for s in ('hello', tuple('hello'), list('hello'), range(5)): | 148 for s in ('hello', tuple('hello'), list('hello'), range(5)): |
| 149 self.assertEqual(len(reversed(s)), len(s)) | 149 self.assertEqual(len(reversed(s)), len(s)) |
| 150 r = reversed(s) | 150 r = reversed(s) |
| 151 list(r) | 151 list(r) |
| 152 self.assertEqual(len(r), 0) | 152 self.assertEqual(len(r), 0) |
| 153 class SeqWithWeirdLen: | 153 class SeqWithWeirdLen: |
| 154 called = False | 154 called = False |
| 155 def __len__(self): | 155 def __len__(self): |
| 156 if not self.called: | 156 if not self.called: |
| 157 self.called = True | 157 self.called = True |
| 158 return 10 | 158 return 10 |
| 159 raise ZeroDivisionError | 159 raise ZeroDivisionError |
| 160 def __getitem__(self, index): | 160 def __getitem__(self, index): |
| 161 return index | 161 return index |
| 162 r = reversed(SeqWithWeirdLen()) | 162 r = reversed(SeqWithWeirdLen()) |
| 163 self.assertRaises(ZeroDivisionError, len, r) | 163 self.assertRaises(ZeroDivisionError, len, r) |
| 164 | 164 |
| 165 | 165 |
| 166 def test_gc(self): | 166 def test_gc(self): |
| 167 class Seq: | 167 class Seq: |
| 168 def __len__(self): | 168 def __len__(self): |
| 169 return 10 | 169 return 10 |
| 170 def __getitem__(self, index): | 170 def __getitem__(self, index): |
| 171 return index | 171 return index |
| 172 s = Seq() | 172 s = Seq() |
| 173 r = reversed(s) | 173 r = reversed(s) |
| 174 s.r = r | 174 s.r = r |
| 175 | 175 |
| 176 def test_args(self): | 176 def test_args(self): |
| 177 self.assertRaises(TypeError, reversed) | 177 self.assertRaises(TypeError, reversed) |
| 178 self.assertRaises(TypeError, reversed, [], 'extra') | 178 self.assertRaises(TypeError, reversed, [], 'extra') |
| 179 | 179 |
| 180 def test_bug1229429(self): | 180 def test_bug1229429(self): |
| 181 # this bug was never in reversed, it was in | 181 # this bug was never in reversed, it was in |
| 182 # PyObject_CallMethod, and reversed_new calls that sometimes. | 182 # PyObject_CallMethod, and reversed_new calls that sometimes. |
| 183 if not hasattr(sys, "getrefcount"): | 183 if not hasattr(sys, "getrefcount"): |
| 184 return | 184 return |
| 185 def f(): | 185 def f(): |
| 186 pass | 186 pass |
| 187 r = f.__reversed__ = object() | 187 r = f.__reversed__ = object() |
| 188 rc = sys.getrefcount(r) | 188 rc = sys.getrefcount(r) |
| 189 for i in range(10): | 189 for i in range(10): |
| 190 try: | 190 try: |
| 191 reversed(f) | 191 reversed(f) |
| 192 except TypeError: | 192 except TypeError: |
| 193 pass | 193 pass |
| 194 else: | 194 else: |
| 195 self.fail("non-callable __reversed__ didn't raise!") | 195 self.fail("non-callable __reversed__ didn't raise!") |
| 196 self.assertEqual(rc, sys.getrefcount(r)) | 196 self.assertEqual(rc, sys.getrefcount(r)) |
| 197 | 197 |
| 198 | 198 |
| 199 def test_main(verbose=None): | 199 def test_main(verbose=None): |
| 200 testclasses = (EnumerateTestCase, SubclassTestCase, TestEmpty, TestBig, | 200 testclasses = (EnumerateTestCase, SubclassTestCase, TestEmpty, TestBig, |
| 201 TestReversed) | 201 TestReversed) |
| 202 test_support.run_unittest(*testclasses) | 202 test_support.run_unittest(*testclasses) |
| 203 | 203 |
| 204 # verify reference counting | 204 # verify reference counting |
| 205 import sys | 205 import sys |
| 206 if verbose and hasattr(sys, "gettotalrefcount"): | 206 if verbose and hasattr(sys, "gettotalrefcount"): |
| 207 counts = [None] * 5 | 207 counts = [None] * 5 |
| 208 for i in range(len(counts)): | 208 for i in range(len(counts)): |
| 209 test_support.run_unittest(*testclasses) | 209 test_support.run_unittest(*testclasses) |
| 210 counts[i] = sys.gettotalrefcount() | 210 counts[i] = sys.gettotalrefcount() |
| 211 print(counts) | 211 print(counts) |
| 212 | 212 |
| 213 if __name__ == "__main__": | 213 if __name__ == "__main__": |
| 214 test_main(verbose=True) | 214 test_main(verbose=True) |
| OLD | NEW |