ยปCore Development>Code coverage>Lib/test/test_memoryview.py

Python code coverage for Lib/test/test_memoryview.py

#countcontent
1n/a"""Unit tests for the memoryview
2n/a
3n/a Some tests are in test_bytes. Many tests that require _testbuffer.ndarray
4n/a are in test_buffer.
5n/a"""
6n/a
7n/aimport unittest
8n/aimport test.support
9n/aimport sys
10n/aimport gc
11n/aimport weakref
12n/aimport array
13n/aimport io
14n/aimport copy
15n/aimport pickle
16n/a
17n/a
18n/aclass AbstractMemoryTests:
19n/a source_bytes = b"abcdef"
20n/a
21n/a @property
22n/a def _source(self):
23n/a return self.source_bytes
24n/a
25n/a @property
26n/a def _types(self):
27n/a return filter(None, [self.ro_type, self.rw_type])
28n/a
29n/a def check_getitem_with_type(self, tp):
30n/a b = tp(self._source)
31n/a oldrefcount = sys.getrefcount(b)
32n/a m = self._view(b)
33n/a self.assertEqual(m[0], ord(b"a"))
34n/a self.assertIsInstance(m[0], int)
35n/a self.assertEqual(m[5], ord(b"f"))
36n/a self.assertEqual(m[-1], ord(b"f"))
37n/a self.assertEqual(m[-6], ord(b"a"))
38n/a # Bounds checking
39n/a self.assertRaises(IndexError, lambda: m[6])
40n/a self.assertRaises(IndexError, lambda: m[-7])
41n/a self.assertRaises(IndexError, lambda: m[sys.maxsize])
42n/a self.assertRaises(IndexError, lambda: m[-sys.maxsize])
43n/a # Type checking
44n/a self.assertRaises(TypeError, lambda: m[None])
45n/a self.assertRaises(TypeError, lambda: m[0.0])
46n/a self.assertRaises(TypeError, lambda: m["a"])
47n/a m = None
48n/a self.assertEqual(sys.getrefcount(b), oldrefcount)
49n/a
50n/a def test_getitem(self):
51n/a for tp in self._types:
52n/a self.check_getitem_with_type(tp)
53n/a
54n/a def test_iter(self):
55n/a for tp in self._types:
56n/a b = tp(self._source)
57n/a m = self._view(b)
58n/a self.assertEqual(list(m), [m[i] for i in range(len(m))])
59n/a
60n/a def test_setitem_readonly(self):
61n/a if not self.ro_type:
62n/a self.skipTest("no read-only type to test")
63n/a b = self.ro_type(self._source)
64n/a oldrefcount = sys.getrefcount(b)
65n/a m = self._view(b)
66n/a def setitem(value):
67n/a m[0] = value
68n/a self.assertRaises(TypeError, setitem, b"a")
69n/a self.assertRaises(TypeError, setitem, 65)
70n/a self.assertRaises(TypeError, setitem, memoryview(b"a"))
71n/a m = None
72n/a self.assertEqual(sys.getrefcount(b), oldrefcount)
73n/a
74n/a def test_setitem_writable(self):
75n/a if not self.rw_type:
76n/a self.skipTest("no writable type to test")
77n/a tp = self.rw_type
78n/a b = self.rw_type(self._source)
79n/a oldrefcount = sys.getrefcount(b)
80n/a m = self._view(b)
81n/a m[0] = ord(b'1')
82n/a self._check_contents(tp, b, b"1bcdef")
83n/a m[0:1] = tp(b"0")
84n/a self._check_contents(tp, b, b"0bcdef")
85n/a m[1:3] = tp(b"12")
86n/a self._check_contents(tp, b, b"012def")
87n/a m[1:1] = tp(b"")
88n/a self._check_contents(tp, b, b"012def")
89n/a m[:] = tp(b"abcdef")
90n/a self._check_contents(tp, b, b"abcdef")
91n/a
92n/a # Overlapping copies of a view into itself
93n/a m[0:3] = m[2:5]
94n/a self._check_contents(tp, b, b"cdedef")
95n/a m[:] = tp(b"abcdef")
96n/a m[2:5] = m[0:3]
97n/a self._check_contents(tp, b, b"ababcf")
98n/a
99n/a def setitem(key, value):
100n/a m[key] = tp(value)
101n/a # Bounds checking
102n/a self.assertRaises(IndexError, setitem, 6, b"a")
103n/a self.assertRaises(IndexError, setitem, -7, b"a")
104n/a self.assertRaises(IndexError, setitem, sys.maxsize, b"a")
105n/a self.assertRaises(IndexError, setitem, -sys.maxsize, b"a")
106n/a # Wrong index/slice types
107n/a self.assertRaises(TypeError, setitem, 0.0, b"a")
108n/a self.assertRaises(TypeError, setitem, (0,), b"a")
109n/a self.assertRaises(TypeError, setitem, (slice(0,1,1), 0), b"a")
110n/a self.assertRaises(TypeError, setitem, (0, slice(0,1,1)), b"a")
111n/a self.assertRaises(TypeError, setitem, (0,), b"a")
112n/a self.assertRaises(TypeError, setitem, "a", b"a")
113n/a # Not implemented: multidimensional slices
114n/a slices = (slice(0,1,1), slice(0,1,2))
115n/a self.assertRaises(NotImplementedError, setitem, slices, b"a")
116n/a # Trying to resize the memory object
117n/a exc = ValueError if m.format == 'c' else TypeError
118n/a self.assertRaises(exc, setitem, 0, b"")
119n/a self.assertRaises(exc, setitem, 0, b"ab")
120n/a self.assertRaises(ValueError, setitem, slice(1,1), b"a")
121n/a self.assertRaises(ValueError, setitem, slice(0,2), b"a")
122n/a
123n/a m = None
124n/a self.assertEqual(sys.getrefcount(b), oldrefcount)
125n/a
126n/a def test_delitem(self):
127n/a for tp in self._types:
128n/a b = tp(self._source)
129n/a m = self._view(b)
130n/a with self.assertRaises(TypeError):
131n/a del m[1]
132n/a with self.assertRaises(TypeError):
133n/a del m[1:4]
134n/a
135n/a def test_tobytes(self):
136n/a for tp in self._types:
137n/a m = self._view(tp(self._source))
138n/a b = m.tobytes()
139n/a # This calls self.getitem_type() on each separate byte of b"abcdef"
140n/a expected = b"".join(
141n/a self.getitem_type(bytes([c])) for c in b"abcdef")
142n/a self.assertEqual(b, expected)
143n/a self.assertIsInstance(b, bytes)
144n/a
145n/a def test_tolist(self):
146n/a for tp in self._types:
147n/a m = self._view(tp(self._source))
148n/a l = m.tolist()
149n/a self.assertEqual(l, list(b"abcdef"))
150n/a
151n/a def test_compare(self):
152n/a # memoryviews can compare for equality with other objects
153n/a # having the buffer interface.
154n/a for tp in self._types:
155n/a m = self._view(tp(self._source))
156n/a for tp_comp in self._types:
157n/a self.assertTrue(m == tp_comp(b"abcdef"))
158n/a self.assertFalse(m != tp_comp(b"abcdef"))
159n/a self.assertFalse(m == tp_comp(b"abcde"))
160n/a self.assertTrue(m != tp_comp(b"abcde"))
161n/a self.assertFalse(m == tp_comp(b"abcde1"))
162n/a self.assertTrue(m != tp_comp(b"abcde1"))
163n/a self.assertTrue(m == m)
164n/a self.assertTrue(m == m[:])
165n/a self.assertTrue(m[0:6] == m[:])
166n/a self.assertFalse(m[0:5] == m)
167n/a
168n/a # Comparison with objects which don't support the buffer API
169n/a self.assertFalse(m == "abcdef")
170n/a self.assertTrue(m != "abcdef")
171n/a self.assertFalse("abcdef" == m)
172n/a self.assertTrue("abcdef" != m)
173n/a
174n/a # Unordered comparisons
175n/a for c in (m, b"abcdef"):
176n/a self.assertRaises(TypeError, lambda: m < c)
177n/a self.assertRaises(TypeError, lambda: c <= m)
178n/a self.assertRaises(TypeError, lambda: m >= c)
179n/a self.assertRaises(TypeError, lambda: c > m)
180n/a
181n/a def check_attributes_with_type(self, tp):
182n/a m = self._view(tp(self._source))
183n/a self.assertEqual(m.format, self.format)
184n/a self.assertEqual(m.itemsize, self.itemsize)
185n/a self.assertEqual(m.ndim, 1)
186n/a self.assertEqual(m.shape, (6,))
187n/a self.assertEqual(len(m), 6)
188n/a self.assertEqual(m.strides, (self.itemsize,))
189n/a self.assertEqual(m.suboffsets, ())
190n/a return m
191n/a
192n/a def test_attributes_readonly(self):
193n/a if not self.ro_type:
194n/a self.skipTest("no read-only type to test")
195n/a m = self.check_attributes_with_type(self.ro_type)
196n/a self.assertEqual(m.readonly, True)
197n/a
198n/a def test_attributes_writable(self):
199n/a if not self.rw_type:
200n/a self.skipTest("no writable type to test")
201n/a m = self.check_attributes_with_type(self.rw_type)
202n/a self.assertEqual(m.readonly, False)
203n/a
204n/a def test_getbuffer(self):
205n/a # Test PyObject_GetBuffer() on a memoryview object.
206n/a for tp in self._types:
207n/a b = tp(self._source)
208n/a oldrefcount = sys.getrefcount(b)
209n/a m = self._view(b)
210n/a oldviewrefcount = sys.getrefcount(m)
211n/a s = str(m, "utf-8")
212n/a self._check_contents(tp, b, s.encode("utf-8"))
213n/a self.assertEqual(sys.getrefcount(m), oldviewrefcount)
214n/a m = None
215n/a self.assertEqual(sys.getrefcount(b), oldrefcount)
216n/a
217n/a def test_gc(self):
218n/a for tp in self._types:
219n/a if not isinstance(tp, type):
220n/a # If tp is a factory rather than a plain type, skip
221n/a continue
222n/a
223n/a class MyView():
224n/a def __init__(self, base):
225n/a self.m = memoryview(base)
226n/a class MySource(tp):
227n/a pass
228n/a class MyObject:
229n/a pass
230n/a
231n/a # Create a reference cycle through a memoryview object.
232n/a # This exercises mbuf_clear().
233n/a b = MySource(tp(b'abc'))
234n/a m = self._view(b)
235n/a o = MyObject()
236n/a b.m = m
237n/a b.o = o
238n/a wr = weakref.ref(o)
239n/a b = m = o = None
240n/a # The cycle must be broken
241n/a gc.collect()
242n/a self.assertTrue(wr() is None, wr())
243n/a
244n/a # This exercises memory_clear().
245n/a m = MyView(tp(b'abc'))
246n/a o = MyObject()
247n/a m.x = m
248n/a m.o = o
249n/a wr = weakref.ref(o)
250n/a m = o = None
251n/a # The cycle must be broken
252n/a gc.collect()
253n/a self.assertTrue(wr() is None, wr())
254n/a
255n/a def _check_released(self, m, tp):
256n/a check = self.assertRaisesRegex(ValueError, "released")
257n/a with check: bytes(m)
258n/a with check: m.tobytes()
259n/a with check: m.tolist()
260n/a with check: m[0]
261n/a with check: m[0] = b'x'
262n/a with check: len(m)
263n/a with check: m.format
264n/a with check: m.itemsize
265n/a with check: m.ndim
266n/a with check: m.readonly
267n/a with check: m.shape
268n/a with check: m.strides
269n/a with check:
270n/a with m:
271n/a pass
272n/a # str() and repr() still function
273n/a self.assertIn("released memory", str(m))
274n/a self.assertIn("released memory", repr(m))
275n/a self.assertEqual(m, m)
276n/a self.assertNotEqual(m, memoryview(tp(self._source)))
277n/a self.assertNotEqual(m, tp(self._source))
278n/a
279n/a def test_contextmanager(self):
280n/a for tp in self._types:
281n/a b = tp(self._source)
282n/a m = self._view(b)
283n/a with m as cm:
284n/a self.assertIs(cm, m)
285n/a self._check_released(m, tp)
286n/a m = self._view(b)
287n/a # Can release explicitly inside the context manager
288n/a with m:
289n/a m.release()
290n/a
291n/a def test_release(self):
292n/a for tp in self._types:
293n/a b = tp(self._source)
294n/a m = self._view(b)
295n/a m.release()
296n/a self._check_released(m, tp)
297n/a # Can be called a second time (it's a no-op)
298n/a m.release()
299n/a self._check_released(m, tp)
300n/a
301n/a def test_writable_readonly(self):
302n/a # Issue #10451: memoryview incorrectly exposes a readonly
303n/a # buffer as writable causing a segfault if using mmap
304n/a tp = self.ro_type
305n/a if tp is None:
306n/a self.skipTest("no read-only type to test")
307n/a b = tp(self._source)
308n/a m = self._view(b)
309n/a i = io.BytesIO(b'ZZZZ')
310n/a self.assertRaises(TypeError, i.readinto, m)
311n/a
312n/a def test_getbuf_fail(self):
313n/a self.assertRaises(TypeError, self._view, {})
314n/a
315n/a def test_hash(self):
316n/a # Memoryviews of readonly (hashable) types are hashable, and they
317n/a # hash as hash(obj.tobytes()).
318n/a tp = self.ro_type
319n/a if tp is None:
320n/a self.skipTest("no read-only type to test")
321n/a b = tp(self._source)
322n/a m = self._view(b)
323n/a self.assertEqual(hash(m), hash(b"abcdef"))
324n/a # Releasing the memoryview keeps the stored hash value (as with weakrefs)
325n/a m.release()
326n/a self.assertEqual(hash(m), hash(b"abcdef"))
327n/a # Hashing a memoryview for the first time after it is released
328n/a # results in an error (as with weakrefs).
329n/a m = self._view(b)
330n/a m.release()
331n/a self.assertRaises(ValueError, hash, m)
332n/a
333n/a def test_hash_writable(self):
334n/a # Memoryviews of writable types are unhashable
335n/a tp = self.rw_type
336n/a if tp is None:
337n/a self.skipTest("no writable type to test")
338n/a b = tp(self._source)
339n/a m = self._view(b)
340n/a self.assertRaises(ValueError, hash, m)
341n/a
342n/a def test_weakref(self):
343n/a # Check memoryviews are weakrefable
344n/a for tp in self._types:
345n/a b = tp(self._source)
346n/a m = self._view(b)
347n/a L = []
348n/a def callback(wr, b=b):
349n/a L.append(b)
350n/a wr = weakref.ref(m, callback)
351n/a self.assertIs(wr(), m)
352n/a del m
353n/a test.support.gc_collect()
354n/a self.assertIs(wr(), None)
355n/a self.assertIs(L[0], b)
356n/a
357n/a def test_reversed(self):
358n/a for tp in self._types:
359n/a b = tp(self._source)
360n/a m = self._view(b)
361n/a aslist = list(reversed(m.tolist()))
362n/a self.assertEqual(list(reversed(m)), aslist)
363n/a self.assertEqual(list(reversed(m)), list(m[::-1]))
364n/a
365n/a def test_issue22668(self):
366n/a a = array.array('H', [256, 256, 256, 256])
367n/a x = memoryview(a)
368n/a m = x.cast('B')
369n/a b = m.cast('H')
370n/a c = b[0:2]
371n/a d = memoryview(b)
372n/a
373n/a del b
374n/a
375n/a self.assertEqual(c[0], 256)
376n/a self.assertEqual(d[0], 256)
377n/a self.assertEqual(c.format, "H")
378n/a self.assertEqual(d.format, "H")
379n/a
380n/a _ = m.cast('I')
381n/a self.assertEqual(c[0], 256)
382n/a self.assertEqual(d[0], 256)
383n/a self.assertEqual(c.format, "H")
384n/a self.assertEqual(d.format, "H")
385n/a
386n/a
387n/a# Variations on source objects for the buffer: bytes-like objects, then arrays
388n/a# with itemsize > 1.
389n/a# NOTE: support for multi-dimensional objects is unimplemented.
390n/a
391n/aclass BaseBytesMemoryTests(AbstractMemoryTests):
392n/a ro_type = bytes
393n/a rw_type = bytearray
394n/a getitem_type = bytes
395n/a itemsize = 1
396n/a format = 'B'
397n/a
398n/aclass BaseArrayMemoryTests(AbstractMemoryTests):
399n/a ro_type = None
400n/a rw_type = lambda self, b: array.array('i', list(b))
401n/a getitem_type = lambda self, b: array.array('i', list(b)).tobytes()
402n/a itemsize = array.array('i').itemsize
403n/a format = 'i'
404n/a
405n/a @unittest.skip('XXX test should be adapted for non-byte buffers')
406n/a def test_getbuffer(self):
407n/a pass
408n/a
409n/a @unittest.skip('XXX NotImplementedError: tolist() only supports byte views')
410n/a def test_tolist(self):
411n/a pass
412n/a
413n/a
414n/a# Variations on indirection levels: memoryview, slice of memoryview,
415n/a# slice of slice of memoryview.
416n/a# This is important to test allocation subtleties.
417n/a
418n/aclass BaseMemoryviewTests:
419n/a def _view(self, obj):
420n/a return memoryview(obj)
421n/a
422n/a def _check_contents(self, tp, obj, contents):
423n/a self.assertEqual(obj, tp(contents))
424n/a
425n/aclass BaseMemorySliceTests:
426n/a source_bytes = b"XabcdefY"
427n/a
428n/a def _view(self, obj):
429n/a m = memoryview(obj)
430n/a return m[1:7]
431n/a
432n/a def _check_contents(self, tp, obj, contents):
433n/a self.assertEqual(obj[1:7], tp(contents))
434n/a
435n/a def test_refs(self):
436n/a for tp in self._types:
437n/a m = memoryview(tp(self._source))
438n/a oldrefcount = sys.getrefcount(m)
439n/a m[1:2]
440n/a self.assertEqual(sys.getrefcount(m), oldrefcount)
441n/a
442n/aclass BaseMemorySliceSliceTests:
443n/a source_bytes = b"XabcdefY"
444n/a
445n/a def _view(self, obj):
446n/a m = memoryview(obj)
447n/a return m[:7][1:]
448n/a
449n/a def _check_contents(self, tp, obj, contents):
450n/a self.assertEqual(obj[1:7], tp(contents))
451n/a
452n/a
453n/a# Concrete test classes
454n/a
455n/aclass BytesMemoryviewTest(unittest.TestCase,
456n/a BaseMemoryviewTests, BaseBytesMemoryTests):
457n/a
458n/a def test_constructor(self):
459n/a for tp in self._types:
460n/a ob = tp(self._source)
461n/a self.assertTrue(memoryview(ob))
462n/a self.assertTrue(memoryview(object=ob))
463n/a self.assertRaises(TypeError, memoryview)
464n/a self.assertRaises(TypeError, memoryview, ob, ob)
465n/a self.assertRaises(TypeError, memoryview, argument=ob)
466n/a self.assertRaises(TypeError, memoryview, ob, argument=True)
467n/a
468n/aclass ArrayMemoryviewTest(unittest.TestCase,
469n/a BaseMemoryviewTests, BaseArrayMemoryTests):
470n/a
471n/a def test_array_assign(self):
472n/a # Issue #4569: segfault when mutating a memoryview with itemsize != 1
473n/a a = array.array('i', range(10))
474n/a m = memoryview(a)
475n/a new_a = array.array('i', range(9, -1, -1))
476n/a m[:] = new_a
477n/a self.assertEqual(a, new_a)
478n/a
479n/a
480n/aclass BytesMemorySliceTest(unittest.TestCase,
481n/a BaseMemorySliceTests, BaseBytesMemoryTests):
482n/a pass
483n/a
484n/aclass ArrayMemorySliceTest(unittest.TestCase,
485n/a BaseMemorySliceTests, BaseArrayMemoryTests):
486n/a pass
487n/a
488n/aclass BytesMemorySliceSliceTest(unittest.TestCase,
489n/a BaseMemorySliceSliceTests, BaseBytesMemoryTests):
490n/a pass
491n/a
492n/aclass ArrayMemorySliceSliceTest(unittest.TestCase,
493n/a BaseMemorySliceSliceTests, BaseArrayMemoryTests):
494n/a pass
495n/a
496n/a
497n/aclass OtherTest(unittest.TestCase):
498n/a def test_ctypes_cast(self):
499n/a # Issue 15944: Allow all source formats when casting to bytes.
500n/a ctypes = test.support.import_module("ctypes")
501n/a p6 = bytes(ctypes.c_double(0.6))
502n/a
503n/a d = ctypes.c_double()
504n/a m = memoryview(d).cast("B")
505n/a m[:2] = p6[:2]
506n/a m[2:] = p6[2:]
507n/a self.assertEqual(d.value, 0.6)
508n/a
509n/a for format in "Bbc":
510n/a with self.subTest(format):
511n/a d = ctypes.c_double()
512n/a m = memoryview(d).cast(format)
513n/a m[:2] = memoryview(p6).cast(format)[:2]
514n/a m[2:] = memoryview(p6).cast(format)[2:]
515n/a self.assertEqual(d.value, 0.6)
516n/a
517n/a def test_memoryview_hex(self):
518n/a # Issue #9951: memoryview.hex() segfaults with non-contiguous buffers.
519n/a x = b'0' * 200000
520n/a m1 = memoryview(x)
521n/a m2 = m1[::-1]
522n/a self.assertEqual(m2.hex(), '30' * 200000)
523n/a
524n/a def test_copy(self):
525n/a m = memoryview(b'abc')
526n/a with self.assertRaises(TypeError):
527n/a copy.copy(m)
528n/a
529n/a def test_pickle(self):
530n/a m = memoryview(b'abc')
531n/a for proto in range(pickle.HIGHEST_PROTOCOL + 1):
532n/a with self.assertRaises(TypeError):
533n/a pickle.dumps(m, proto)
534n/a
535n/a
536n/aif __name__ == "__main__":
537n/a unittest.main()