mirror of
				https://github.com/python/cpython.git
				synced 2025-11-03 23:21:29 +00:00 
			
		
		
		
	
		
			
	
	
		
			154 lines
		
	
	
	
		
			5 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
		
		
			
		
	
	
			154 lines
		
	
	
	
		
			5 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| 
								 | 
							
								"""Unit tests for the PickleBuffer object.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Pickling tests themselves are in pickletester.py.
							 | 
						||
| 
								 | 
							
								"""
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								import gc
							 | 
						||
| 
								 | 
							
								from pickle import PickleBuffer
							 | 
						||
| 
								 | 
							
								import weakref
							 | 
						||
| 
								 | 
							
								import unittest
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								from test import support
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class B(bytes):
							 | 
						||
| 
								 | 
							
								    pass
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class PickleBufferTest(unittest.TestCase):
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def check_memoryview(self, pb, equiv):
							 | 
						||
| 
								 | 
							
								        with memoryview(pb) as m:
							 | 
						||
| 
								 | 
							
								            with memoryview(equiv) as expected:
							 | 
						||
| 
								 | 
							
								                self.assertEqual(m.nbytes, expected.nbytes)
							 | 
						||
| 
								 | 
							
								                self.assertEqual(m.readonly, expected.readonly)
							 | 
						||
| 
								 | 
							
								                self.assertEqual(m.itemsize, expected.itemsize)
							 | 
						||
| 
								 | 
							
								                self.assertEqual(m.shape, expected.shape)
							 | 
						||
| 
								 | 
							
								                self.assertEqual(m.strides, expected.strides)
							 | 
						||
| 
								 | 
							
								                self.assertEqual(m.c_contiguous, expected.c_contiguous)
							 | 
						||
| 
								 | 
							
								                self.assertEqual(m.f_contiguous, expected.f_contiguous)
							 | 
						||
| 
								 | 
							
								                self.assertEqual(m.format, expected.format)
							 | 
						||
| 
								 | 
							
								                self.assertEqual(m.tobytes(), expected.tobytes())
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def test_constructor_failure(self):
							 | 
						||
| 
								 | 
							
								        with self.assertRaises(TypeError):
							 | 
						||
| 
								 | 
							
								            PickleBuffer()
							 | 
						||
| 
								 | 
							
								        with self.assertRaises(TypeError):
							 | 
						||
| 
								 | 
							
								            PickleBuffer("foo")
							 | 
						||
| 
								 | 
							
								        # Released memoryview fails taking a buffer
							 | 
						||
| 
								 | 
							
								        m = memoryview(b"foo")
							 | 
						||
| 
								 | 
							
								        m.release()
							 | 
						||
| 
								 | 
							
								        with self.assertRaises(ValueError):
							 | 
						||
| 
								 | 
							
								            PickleBuffer(m)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def test_basics(self):
							 | 
						||
| 
								 | 
							
								        pb = PickleBuffer(b"foo")
							 | 
						||
| 
								 | 
							
								        self.assertEqual(b"foo", bytes(pb))
							 | 
						||
| 
								 | 
							
								        with memoryview(pb) as m:
							 | 
						||
| 
								 | 
							
								            self.assertTrue(m.readonly)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        pb = PickleBuffer(bytearray(b"foo"))
							 | 
						||
| 
								 | 
							
								        self.assertEqual(b"foo", bytes(pb))
							 | 
						||
| 
								 | 
							
								        with memoryview(pb) as m:
							 | 
						||
| 
								 | 
							
								            self.assertFalse(m.readonly)
							 | 
						||
| 
								 | 
							
								            m[0] = 48
							 | 
						||
| 
								 | 
							
								        self.assertEqual(b"0oo", bytes(pb))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def test_release(self):
							 | 
						||
| 
								 | 
							
								        pb = PickleBuffer(b"foo")
							 | 
						||
| 
								 | 
							
								        pb.release()
							 | 
						||
| 
								 | 
							
								        with self.assertRaises(ValueError) as raises:
							 | 
						||
| 
								 | 
							
								            memoryview(pb)
							 | 
						||
| 
								 | 
							
								        self.assertIn("operation forbidden on released PickleBuffer object",
							 | 
						||
| 
								 | 
							
								                      str(raises.exception))
							 | 
						||
| 
								 | 
							
								        # Idempotency
							 | 
						||
| 
								 | 
							
								        pb.release()
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def test_cycle(self):
							 | 
						||
| 
								 | 
							
								        b = B(b"foo")
							 | 
						||
| 
								 | 
							
								        pb = PickleBuffer(b)
							 | 
						||
| 
								 | 
							
								        b.cycle = pb
							 | 
						||
| 
								 | 
							
								        wpb = weakref.ref(pb)
							 | 
						||
| 
								 | 
							
								        del b, pb
							 | 
						||
| 
								 | 
							
								        gc.collect()
							 | 
						||
| 
								 | 
							
								        self.assertIsNone(wpb())
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def test_ndarray_2d(self):
							 | 
						||
| 
								 | 
							
								        # C-contiguous
							 | 
						||
| 
								 | 
							
								        ndarray = support.import_module("_testbuffer").ndarray
							 | 
						||
| 
								 | 
							
								        arr = ndarray(list(range(12)), shape=(4, 3), format='<i')
							 | 
						||
| 
								 | 
							
								        self.assertTrue(arr.c_contiguous)
							 | 
						||
| 
								 | 
							
								        self.assertFalse(arr.f_contiguous)
							 | 
						||
| 
								 | 
							
								        pb = PickleBuffer(arr)
							 | 
						||
| 
								 | 
							
								        self.check_memoryview(pb, arr)
							 | 
						||
| 
								 | 
							
								        # Non-contiguous
							 | 
						||
| 
								 | 
							
								        arr = arr[::2]
							 | 
						||
| 
								 | 
							
								        self.assertFalse(arr.c_contiguous)
							 | 
						||
| 
								 | 
							
								        self.assertFalse(arr.f_contiguous)
							 | 
						||
| 
								 | 
							
								        pb = PickleBuffer(arr)
							 | 
						||
| 
								 | 
							
								        self.check_memoryview(pb, arr)
							 | 
						||
| 
								 | 
							
								        # F-contiguous
							 | 
						||
| 
								 | 
							
								        arr = ndarray(list(range(12)), shape=(3, 4), strides=(4, 12), format='<i')
							 | 
						||
| 
								 | 
							
								        self.assertTrue(arr.f_contiguous)
							 | 
						||
| 
								 | 
							
								        self.assertFalse(arr.c_contiguous)
							 | 
						||
| 
								 | 
							
								        pb = PickleBuffer(arr)
							 | 
						||
| 
								 | 
							
								        self.check_memoryview(pb, arr)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    # Tests for PickleBuffer.raw()
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def check_raw(self, obj, equiv):
							 | 
						||
| 
								 | 
							
								        pb = PickleBuffer(obj)
							 | 
						||
| 
								 | 
							
								        with pb.raw() as m:
							 | 
						||
| 
								 | 
							
								            self.assertIsInstance(m, memoryview)
							 | 
						||
| 
								 | 
							
								            self.check_memoryview(m, equiv)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def test_raw(self):
							 | 
						||
| 
								 | 
							
								        for obj in (b"foo", bytearray(b"foo")):
							 | 
						||
| 
								 | 
							
								            with self.subTest(obj=obj):
							 | 
						||
| 
								 | 
							
								                self.check_raw(obj, obj)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def test_raw_ndarray(self):
							 | 
						||
| 
								 | 
							
								        # 1-D, contiguous
							 | 
						||
| 
								 | 
							
								        ndarray = support.import_module("_testbuffer").ndarray
							 | 
						||
| 
								 | 
							
								        arr = ndarray(list(range(3)), shape=(3,), format='<h')
							 | 
						||
| 
								 | 
							
								        equiv = b"\x00\x00\x01\x00\x02\x00"
							 | 
						||
| 
								 | 
							
								        self.check_raw(arr, equiv)
							 | 
						||
| 
								 | 
							
								        # 2-D, C-contiguous
							 | 
						||
| 
								 | 
							
								        arr = ndarray(list(range(6)), shape=(2, 3), format='<h')
							 | 
						||
| 
								 | 
							
								        equiv = b"\x00\x00\x01\x00\x02\x00\x03\x00\x04\x00\x05\x00"
							 | 
						||
| 
								 | 
							
								        self.check_raw(arr, equiv)
							 | 
						||
| 
								 | 
							
								        # 2-D, F-contiguous
							 | 
						||
| 
								 | 
							
								        arr = ndarray(list(range(6)), shape=(2, 3), strides=(2, 4),
							 | 
						||
| 
								 | 
							
								                      format='<h')
							 | 
						||
| 
								 | 
							
								        # Note this is different from arr.tobytes()
							 | 
						||
| 
								 | 
							
								        equiv = b"\x00\x00\x01\x00\x02\x00\x03\x00\x04\x00\x05\x00"
							 | 
						||
| 
								 | 
							
								        self.check_raw(arr, equiv)
							 | 
						||
| 
								 | 
							
								        # 0-D
							 | 
						||
| 
								 | 
							
								        arr = ndarray(456, shape=(), format='<i')
							 | 
						||
| 
								 | 
							
								        equiv = b'\xc8\x01\x00\x00'
							 | 
						||
| 
								 | 
							
								        self.check_raw(arr, equiv)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def check_raw_non_contiguous(self, obj):
							 | 
						||
| 
								 | 
							
								        pb = PickleBuffer(obj)
							 | 
						||
| 
								 | 
							
								        with self.assertRaisesRegex(BufferError, "non-contiguous"):
							 | 
						||
| 
								 | 
							
								            pb.raw()
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def test_raw_non_contiguous(self):
							 | 
						||
| 
								 | 
							
								        # 1-D
							 | 
						||
| 
								 | 
							
								        ndarray = support.import_module("_testbuffer").ndarray
							 | 
						||
| 
								 | 
							
								        arr = ndarray(list(range(6)), shape=(6,), format='<i')[::2]
							 | 
						||
| 
								 | 
							
								        self.check_raw_non_contiguous(arr)
							 | 
						||
| 
								 | 
							
								        # 2-D
							 | 
						||
| 
								 | 
							
								        arr = ndarray(list(range(12)), shape=(4, 3), format='<i')[::2]
							 | 
						||
| 
								 | 
							
								        self.check_raw_non_contiguous(arr)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def test_raw_released(self):
							 | 
						||
| 
								 | 
							
								        pb = PickleBuffer(b"foo")
							 | 
						||
| 
								 | 
							
								        pb.release()
							 | 
						||
| 
								 | 
							
								        with self.assertRaises(ValueError) as raises:
							 | 
						||
| 
								 | 
							
								            pb.raw()
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								if __name__ == "__main__":
							 | 
						||
| 
								 | 
							
								    unittest.main()
							 |