test_memoryview.py 21 KB

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