@@ -4579,6 +4579,176 @@ def test_c_buffer(self):
45794579 buf .__release_buffer__ (mv )
45804580 self .assertEqual (buf .references , 0 )
45814581
4582+ def test_inheritance (self ):
4583+ class A (bytearray ):
4584+ def __buffer__ (self , flags ):
4585+ return super ().__buffer__ (flags )
4586+
4587+ a = A (b"hello" )
4588+ mv = memoryview (a )
4589+ self .assertEqual (mv .tobytes (), b"hello" )
4590+
4591+ def test_inheritance_releasebuffer (self ):
4592+ rb_call_count = 0
4593+ class B (bytearray ):
4594+ def __buffer__ (self , flags ):
4595+ return super ().__buffer__ (flags )
4596+ def __release_buffer__ (self , view ):
4597+ nonlocal rb_call_count
4598+ rb_call_count += 1
4599+ super ().__release_buffer__ (view )
4600+
4601+ b = B (b"hello" )
4602+ with memoryview (b ) as mv :
4603+ self .assertEqual (mv .tobytes (), b"hello" )
4604+ self .assertEqual (rb_call_count , 0 )
4605+ self .assertEqual (rb_call_count , 1 )
4606+
4607+ def test_inherit_but_return_something_else (self ):
4608+ class A (bytearray ):
4609+ def __buffer__ (self , flags ):
4610+ return memoryview (b"hello" )
4611+
4612+ a = A (b"hello" )
4613+ with memoryview (a ) as mv :
4614+ self .assertEqual (mv .tobytes (), b"hello" )
4615+
4616+ rb_call_count = 0
4617+ rb_raised = False
4618+ class B (bytearray ):
4619+ def __buffer__ (self , flags ):
4620+ return memoryview (b"hello" )
4621+ def __release_buffer__ (self , view ):
4622+ nonlocal rb_call_count
4623+ rb_call_count += 1
4624+ try :
4625+ super ().__release_buffer__ (view )
4626+ except ValueError :
4627+ nonlocal rb_raised
4628+ rb_raised = True
4629+
4630+ b = B (b"hello" )
4631+ with memoryview (b ) as mv :
4632+ self .assertEqual (mv .tobytes (), b"hello" )
4633+ self .assertEqual (rb_call_count , 0 )
4634+ self .assertEqual (rb_call_count , 1 )
4635+ self .assertIs (rb_raised , True )
4636+
4637+ def test_override_only_release (self ):
4638+ class C (bytearray ):
4639+ def __release_buffer__ (self , buffer ):
4640+ super ().__release_buffer__ (buffer )
4641+
4642+ c = C (b"hello" )
4643+ with memoryview (c ) as mv :
4644+ self .assertEqual (mv .tobytes (), b"hello" )
4645+
4646+ def test_release_saves_reference (self ):
4647+ smuggled_buffer = None
4648+
4649+ class C (bytearray ):
4650+ def __release_buffer__ (s , buffer : memoryview ):
4651+ with self .assertRaises (ValueError ):
4652+ memoryview (buffer )
4653+ with self .assertRaises (ValueError ):
4654+ buffer .cast ("b" )
4655+ with self .assertRaises (ValueError ):
4656+ buffer .toreadonly ()
4657+ with self .assertRaises (ValueError ):
4658+ buffer [:1 ]
4659+ with self .assertRaises (ValueError ):
4660+ buffer .__buffer__ (0 )
4661+ nonlocal smuggled_buffer
4662+ smuggled_buffer = buffer
4663+ self .assertEqual (buffer .tobytes (), b"hello" )
4664+ super ().__release_buffer__ (buffer )
4665+
4666+ c = C (b"hello" )
4667+ with memoryview (c ) as mv :
4668+ self .assertEqual (mv .tobytes (), b"hello" )
4669+ c .clear ()
4670+ with self .assertRaises (ValueError ):
4671+ smuggled_buffer .tobytes ()
4672+
4673+ def test_release_saves_reference_no_subclassing (self ):
4674+ ba = bytearray (b"hello" )
4675+
4676+ class C :
4677+ def __buffer__ (self , flags ):
4678+ return memoryview (ba )
4679+
4680+ def __release_buffer__ (self , buffer ):
4681+ self .buffer = buffer
4682+
4683+ c = C ()
4684+ with memoryview (c ) as mv :
4685+ self .assertEqual (mv .tobytes (), b"hello" )
4686+ self .assertEqual (c .buffer .tobytes (), b"hello" )
4687+
4688+ with self .assertRaises (BufferError ):
4689+ ba .clear ()
4690+ c .buffer .release ()
4691+ ba .clear ()
4692+
4693+ def test_multiple_inheritance_buffer_last (self ):
4694+ class A :
4695+ def __buffer__ (self , flags ):
4696+ return memoryview (b"hello A" )
4697+
4698+ class B (A , bytearray ):
4699+ def __buffer__ (self , flags ):
4700+ return super ().__buffer__ (flags )
4701+
4702+ b = B (b"hello" )
4703+ with memoryview (b ) as mv :
4704+ self .assertEqual (mv .tobytes (), b"hello A" )
4705+
4706+ class Releaser :
4707+ def __release_buffer__ (self , buffer ):
4708+ self .buffer = buffer
4709+
4710+ class C (Releaser , bytearray ):
4711+ def __buffer__ (self , flags ):
4712+ return super ().__buffer__ (flags )
4713+
4714+ c = C (b"hello C" )
4715+ with memoryview (c ) as mv :
4716+ self .assertEqual (mv .tobytes (), b"hello C" )
4717+ c .clear ()
4718+ with self .assertRaises (ValueError ):
4719+ c .buffer .tobytes ()
4720+
4721+ def test_multiple_inheritance_buffer_last (self ):
4722+ class A :
4723+ def __buffer__ (self , flags ):
4724+ raise RuntimeError ("should not be called" )
4725+
4726+ def __release_buffer__ (self , buffer ):
4727+ raise RuntimeError ("should not be called" )
4728+
4729+ class B (bytearray , A ):
4730+ def __buffer__ (self , flags ):
4731+ return super ().__buffer__ (flags )
4732+
4733+ b = B (b"hello" )
4734+ with memoryview (b ) as mv :
4735+ self .assertEqual (mv .tobytes (), b"hello" )
4736+
4737+ class Releaser :
4738+ buffer = None
4739+ def __release_buffer__ (self , buffer ):
4740+ self .buffer = buffer
4741+
4742+ class C (bytearray , Releaser ):
4743+ def __buffer__ (self , flags ):
4744+ return super ().__buffer__ (flags )
4745+
4746+ c = C (b"hello" )
4747+ with memoryview (c ) as mv :
4748+ self .assertEqual (mv .tobytes (), b"hello" )
4749+ c .clear ()
4750+ self .assertIs (c .buffer , None )
4751+
45824752
45834753if __name__ == "__main__" :
45844754 unittest .main ()
0 commit comments