python (3.12.0)

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