~ubuntu-branches/ubuntu/maverick/python3.1/maverick

« back to all changes in this revision

Viewing changes to Lib/test/test_enumerate.py

  • Committer: Bazaar Package Importer
  • Author(s): Matthias Klose
  • Date: 2009-03-23 00:01:27 UTC
  • Revision ID: james.westby@ubuntu.com-20090323000127-5fstfxju4ufrhthq
Tags: upstream-3.1~a1+20090322
ImportĀ upstreamĀ versionĀ 3.1~a1+20090322

Show diffs side-by-side

added added

removed removed

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