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

« back to all changes in this revision

Viewing changes to Lib/test/test_memoryview.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
"""Unit tests for the memoryview
 
2
 
 
3
XXX We need more tests! Some tests are in test_bytes
 
4
"""
 
5
 
 
6
import unittest
 
7
import test.support
 
8
import sys
 
9
import gc
 
10
import weakref
 
11
import array
 
12
 
 
13
 
 
14
class AbstractMemoryTests:
 
15
    source_bytes = b"abcdef"
 
16
 
 
17
    @property
 
18
    def _source(self):
 
19
        return self.source_bytes
 
20
 
 
21
    @property
 
22
    def _types(self):
 
23
        return filter(None, [self.ro_type, self.rw_type])
 
24
 
 
25
    def check_getitem_with_type(self, tp):
 
26
        item = self.getitem_type
 
27
        b = tp(self._source)
 
28
        oldrefcount = sys.getrefcount(b)
 
29
        m = self._view(b)
 
30
        self.assertEquals(m[0], item(b"a"))
 
31
        self.assert_(isinstance(m[0], bytes), type(m[0]))
 
32
        self.assertEquals(m[5], item(b"f"))
 
33
        self.assertEquals(m[-1], item(b"f"))
 
34
        self.assertEquals(m[-6], item(b"a"))
 
35
        # Bounds checking
 
36
        self.assertRaises(IndexError, lambda: m[6])
 
37
        self.assertRaises(IndexError, lambda: m[-7])
 
38
        self.assertRaises(IndexError, lambda: m[sys.maxsize])
 
39
        self.assertRaises(IndexError, lambda: m[-sys.maxsize])
 
40
        # Type checking
 
41
        self.assertRaises(TypeError, lambda: m[None])
 
42
        self.assertRaises(TypeError, lambda: m[0.0])
 
43
        self.assertRaises(TypeError, lambda: m["a"])
 
44
        m = None
 
45
        self.assertEquals(sys.getrefcount(b), oldrefcount)
 
46
 
 
47
    def test_getitem(self):
 
48
        for tp in self._types:
 
49
            self.check_getitem_with_type(tp)
 
50
 
 
51
    def test_setitem_readonly(self):
 
52
        if not self.ro_type:
 
53
            return
 
54
        b = self.ro_type(self._source)
 
55
        oldrefcount = sys.getrefcount(b)
 
56
        m = self._view(b)
 
57
        def setitem(value):
 
58
            m[0] = value
 
59
        self.assertRaises(TypeError, setitem, b"a")
 
60
        self.assertRaises(TypeError, setitem, 65)
 
61
        self.assertRaises(TypeError, setitem, memoryview(b"a"))
 
62
        m = None
 
63
        self.assertEquals(sys.getrefcount(b), oldrefcount)
 
64
 
 
65
    def test_setitem_writable(self):
 
66
        if not self.rw_type:
 
67
            return
 
68
        tp = self.rw_type
 
69
        b = self.rw_type(self._source)
 
70
        oldrefcount = sys.getrefcount(b)
 
71
        m = self._view(b)
 
72
        m[0] = tp(b"0")
 
73
        self._check_contents(tp, b, b"0bcdef")
 
74
        m[1:3] = tp(b"12")
 
75
        self._check_contents(tp, b, b"012def")
 
76
        m[1:1] = tp(b"")
 
77
        self._check_contents(tp, b, b"012def")
 
78
        m[:] = tp(b"abcdef")
 
79
        self._check_contents(tp, b, b"abcdef")
 
80
 
 
81
        # Overlapping copies of a view into itself
 
82
        m[0:3] = m[2:5]
 
83
        self._check_contents(tp, b, b"cdedef")
 
84
        m[:] = tp(b"abcdef")
 
85
        m[2:5] = m[0:3]
 
86
        self._check_contents(tp, b, b"ababcf")
 
87
 
 
88
        def setitem(key, value):
 
89
            m[key] = tp(value)
 
90
        # Bounds checking
 
91
        self.assertRaises(IndexError, setitem, 6, b"a")
 
92
        self.assertRaises(IndexError, setitem, -7, b"a")
 
93
        self.assertRaises(IndexError, setitem, sys.maxsize, b"a")
 
94
        self.assertRaises(IndexError, setitem, -sys.maxsize, b"a")
 
95
        # Wrong index/slice types
 
96
        self.assertRaises(TypeError, setitem, 0.0, b"a")
 
97
        self.assertRaises(TypeError, setitem, (0,), b"a")
 
98
        self.assertRaises(TypeError, setitem, "a", b"a")
 
99
        # Trying to resize the memory object
 
100
        self.assertRaises(ValueError, setitem, 0, b"")
 
101
        self.assertRaises(ValueError, setitem, 0, b"ab")
 
102
        self.assertRaises(ValueError, setitem, slice(1,1), b"a")
 
103
        self.assertRaises(ValueError, setitem, slice(0,2), b"a")
 
104
 
 
105
        m = None
 
106
        self.assertEquals(sys.getrefcount(b), oldrefcount)
 
107
 
 
108
    def test_tobytes(self):
 
109
        for tp in self._types:
 
110
            m = self._view(tp(self._source))
 
111
            b = m.tobytes()
 
112
            # This calls self.getitem_type() on each separate byte of b"abcdef"
 
113
            expected = b"".join(
 
114
                self.getitem_type(bytes([c])) for c in b"abcdef")
 
115
            self.assertEquals(b, expected)
 
116
            self.assert_(isinstance(b, bytes), type(b))
 
117
 
 
118
    def test_tolist(self):
 
119
        for tp in self._types:
 
120
            m = self._view(tp(self._source))
 
121
            l = m.tolist()
 
122
            self.assertEquals(l, list(b"abcdef"))
 
123
 
 
124
    def test_compare(self):
 
125
        # memoryviews can compare for equality with other objects
 
126
        # having the buffer interface.
 
127
        for tp in self._types:
 
128
            m = self._view(tp(self._source))
 
129
            for tp_comp in self._types:
 
130
                self.assertTrue(m == tp_comp(b"abcdef"))
 
131
                self.assertFalse(m != tp_comp(b"abcdef"))
 
132
                self.assertFalse(m == tp_comp(b"abcde"))
 
133
                self.assertTrue(m != tp_comp(b"abcde"))
 
134
                self.assertFalse(m == tp_comp(b"abcde1"))
 
135
                self.assertTrue(m != tp_comp(b"abcde1"))
 
136
            self.assertTrue(m == m)
 
137
            self.assertTrue(m == m[:])
 
138
            self.assertTrue(m[0:6] == m[:])
 
139
            self.assertFalse(m[0:5] == m)
 
140
 
 
141
            # Comparison with objects which don't support the buffer API
 
142
            self.assertFalse(m == "abcdef")
 
143
            self.assertTrue(m != "abcdef")
 
144
            self.assertFalse("abcdef" == m)
 
145
            self.assertTrue("abcdef" != m)
 
146
 
 
147
            # Unordered comparisons
 
148
            for c in (m, b"abcdef"):
 
149
                self.assertRaises(TypeError, lambda: m < c)
 
150
                self.assertRaises(TypeError, lambda: c <= m)
 
151
                self.assertRaises(TypeError, lambda: m >= c)
 
152
                self.assertRaises(TypeError, lambda: c > m)
 
153
 
 
154
    def check_attributes_with_type(self, tp):
 
155
        m = self._view(tp(self._source))
 
156
        self.assertEquals(m.format, self.format)
 
157
        self.assertEquals(m.itemsize, self.itemsize)
 
158
        self.assertEquals(m.ndim, 1)
 
159
        self.assertEquals(m.shape, (6,))
 
160
        self.assertEquals(len(m), 6)
 
161
        self.assertEquals(m.strides, (self.itemsize,))
 
162
        self.assertEquals(m.suboffsets, None)
 
163
        return m
 
164
 
 
165
    def test_attributes_readonly(self):
 
166
        if not self.ro_type:
 
167
            return
 
168
        m = self.check_attributes_with_type(self.ro_type)
 
169
        self.assertEquals(m.readonly, True)
 
170
 
 
171
    def test_attributes_writable(self):
 
172
        if not self.rw_type:
 
173
            return
 
174
        m = self.check_attributes_with_type(self.rw_type)
 
175
        self.assertEquals(m.readonly, False)
 
176
 
 
177
    def test_getbuffer(self):
 
178
        # Test PyObject_GetBuffer() on a memoryview object.
 
179
        for tp in self._types:
 
180
            b = tp(self._source)
 
181
            oldrefcount = sys.getrefcount(b)
 
182
            m = self._view(b)
 
183
            oldviewrefcount = sys.getrefcount(m)
 
184
            s = str(m, "utf-8")
 
185
            self._check_contents(tp, b, s.encode("utf-8"))
 
186
            self.assertEquals(sys.getrefcount(m), oldviewrefcount)
 
187
            m = None
 
188
            self.assertEquals(sys.getrefcount(b), oldrefcount)
 
189
 
 
190
    def test_gc(self):
 
191
        for tp in self._types:
 
192
            if not isinstance(tp, type):
 
193
                # If tp is a factory rather than a plain type, skip
 
194
                continue
 
195
 
 
196
            class MySource(tp):
 
197
                pass
 
198
            class MyObject:
 
199
                pass
 
200
 
 
201
            # Create a reference cycle through a memoryview object
 
202
            b = MySource(tp(b'abc'))
 
203
            m = self._view(b)
 
204
            o = MyObject()
 
205
            b.m = m
 
206
            b.o = o
 
207
            wr = weakref.ref(o)
 
208
            b = m = o = None
 
209
            # The cycle must be broken
 
210
            gc.collect()
 
211
            self.assert_(wr() is None, wr())
 
212
 
 
213
 
 
214
# Variations on source objects for the buffer: bytes-like objects, then arrays
 
215
# with itemsize > 1.
 
216
# NOTE: support for multi-dimensional objects is unimplemented.
 
217
 
 
218
class BaseBytesMemoryTests(AbstractMemoryTests):
 
219
    ro_type = bytes
 
220
    rw_type = bytearray
 
221
    getitem_type = bytes
 
222
    itemsize = 1
 
223
    format = 'B'
 
224
 
 
225
class BaseArrayMemoryTests(AbstractMemoryTests):
 
226
    ro_type = None
 
227
    rw_type = lambda self, b: array.array('i', list(b))
 
228
    getitem_type = lambda self, b: array.array('i', list(b)).tostring()
 
229
    itemsize = array.array('i').itemsize
 
230
    format = 'i'
 
231
 
 
232
    def test_getbuffer(self):
 
233
        # XXX Test should be adapted for non-byte buffers
 
234
        pass
 
235
 
 
236
    def test_tolist(self):
 
237
        # XXX NotImplementedError: tolist() only supports byte views
 
238
        pass
 
239
 
 
240
 
 
241
# Variations on indirection levels: memoryview, slice of memoryview,
 
242
# slice of slice of memoryview.
 
243
# This is important to test allocation subtleties.
 
244
 
 
245
class BaseMemoryviewTests:
 
246
    def _view(self, obj):
 
247
        return memoryview(obj)
 
248
 
 
249
    def _check_contents(self, tp, obj, contents):
 
250
        self.assertEquals(obj, tp(contents))
 
251
 
 
252
class BaseMemorySliceTests:
 
253
    source_bytes = b"XabcdefY"
 
254
 
 
255
    def _view(self, obj):
 
256
        m = memoryview(obj)
 
257
        return m[1:7]
 
258
 
 
259
    def _check_contents(self, tp, obj, contents):
 
260
        self.assertEquals(obj[1:7], tp(contents))
 
261
 
 
262
    def test_refs(self):
 
263
        for tp in self._types:
 
264
            m = memoryview(tp(self._source))
 
265
            oldrefcount = sys.getrefcount(m)
 
266
            m[1:2]
 
267
            self.assertEquals(sys.getrefcount(m), oldrefcount)
 
268
 
 
269
class BaseMemorySliceSliceTests:
 
270
    source_bytes = b"XabcdefY"
 
271
 
 
272
    def _view(self, obj):
 
273
        m = memoryview(obj)
 
274
        return m[:7][1:]
 
275
 
 
276
    def _check_contents(self, tp, obj, contents):
 
277
        self.assertEquals(obj[1:7], tp(contents))
 
278
 
 
279
 
 
280
# Concrete test classes
 
281
 
 
282
class BytesMemoryviewTest(unittest.TestCase,
 
283
    BaseMemoryviewTests, BaseBytesMemoryTests):
 
284
 
 
285
    def test_constructor(self):
 
286
        for tp in self._types:
 
287
            ob = tp(self._source)
 
288
            self.assert_(memoryview(ob))
 
289
            self.assert_(memoryview(object=ob))
 
290
            self.assertRaises(TypeError, memoryview)
 
291
            self.assertRaises(TypeError, memoryview, ob, ob)
 
292
            self.assertRaises(TypeError, memoryview, argument=ob)
 
293
            self.assertRaises(TypeError, memoryview, ob, argument=True)
 
294
 
 
295
class ArrayMemoryviewTest(unittest.TestCase,
 
296
    BaseMemoryviewTests, BaseArrayMemoryTests):
 
297
 
 
298
    def test_array_assign(self):
 
299
        # Issue #4569: segfault when mutating a memoryview with itemsize != 1
 
300
        a = array.array('i', range(10))
 
301
        m = memoryview(a)
 
302
        new_a = array.array('i', range(9, -1, -1))
 
303
        m[:] = new_a
 
304
        self.assertEquals(a, new_a)
 
305
 
 
306
 
 
307
class BytesMemorySliceTest(unittest.TestCase,
 
308
    BaseMemorySliceTests, BaseBytesMemoryTests):
 
309
    pass
 
310
 
 
311
class ArrayMemorySliceTest(unittest.TestCase,
 
312
    BaseMemorySliceTests, BaseArrayMemoryTests):
 
313
    pass
 
314
 
 
315
class BytesMemorySliceSliceTest(unittest.TestCase,
 
316
    BaseMemorySliceSliceTests, BaseBytesMemoryTests):
 
317
    pass
 
318
 
 
319
class ArrayMemorySliceSliceTest(unittest.TestCase,
 
320
    BaseMemorySliceSliceTests, BaseArrayMemoryTests):
 
321
    pass
 
322
 
 
323
 
 
324
def test_main():
 
325
    test.support.run_unittest(__name__)
 
326
 
 
327
if __name__ == "__main__":
 
328
    test_main()