def test_ops(self): a = (b'01234567' b'456789ab' b'89abcdef') v = memoryview(a).cast('b', shape=[3, 8]) b = containers.StridedArrayView2D(v).transposed(0, 1).flipped(0) self.assertEqual(b.size, (8, 3)) self.assertEqual(b.stride, (-1, 8)) self.assertEqual(bytes(b), b'7bf6ae59d48c37b26a159048') c = containers.StridedArrayView2D(v).transposed(1, 0).flipped(1) self.assertEqual(c.size, (8, 3)) self.assertEqual(c.stride, (1, -8)) self.assertEqual(bytes(c), b'840951a62b73c84d95ea6fb7') d = containers.StridedArrayView2D(v).transposed(0, 1)[3:4].broadcasted(0, 5) self.assertEqual(d.size, (5, 3)) self.assertEqual(d.stride, (0, 8)) self.assertEqual(bytes(d), b'37b37b37b37b37b') d = containers.StridedArrayView2D(v)[:, 3:4].broadcasted(1, 2) self.assertEqual(d.size, (3, 2)) self.assertEqual(d.stride, (8, 0)) self.assertEqual(bytes(d), b'3377bb')
def test_slice_multidimensional(self): a = memoryview(b'01234567' b'456789ab' b'89abcdef').cast('b', shape=[3, 8]) a_refcount = sys.getrefcount(a) b = containers.StridedArrayView2D(a) b_refcount = sys.getrefcount(b) # memoryview's buffer protocol returns itself, not the underlying # bytes, as it manages the Py_buffer instance. So this is expected. self.assertIs(b.owner, a) self.assertEqual(sys.getrefcount(a), a_refcount + 1) # When slicing, b's refcount should not change but a's refcount should # increase c = b[1:3, 4:7] self.assertIsInstance(c, containers.StridedArrayView2D) self.assertEqual(c.size, (2, 3)) self.assertEqual(c.stride, (8, 1)) self.assertEqual(bytes(c[0]), b'89a') self.assertEqual(bytes(c[1]), b'cde') self.assertEqual(sys.getrefcount(b), b_refcount) self.assertEqual(sys.getrefcount(a), a_refcount + 2) # Deleting a slice should reduce a's refcount again, keep b's unchanged del c self.assertEqual(sys.getrefcount(b), b_refcount) self.assertEqual(sys.getrefcount(a), a_refcount + 1)
def test_init_buffer(self): a = (b'01234567' b'456789ab' b'89abcdef') a_refcount = sys.getrefcount(a) v = memoryview(a).cast('b', shape=[3, 8]) b = containers.StridedArrayView2D(v) self.assertEqual(len(b), 3) self.assertEqual(bytes(b), b'01234567' b'456789ab' b'89abcdef') self.assertEqual(b.size, (3, 8)) self.assertEqual(b.stride, (8, 1)) self.assertIsInstance(b[1], containers.StridedArrayView1D) self.assertEqual(bytes(b[1]), b'456789ab') self.assertEqual(b[1, 2], '6') self.assertEqual(b[1][2], '6') self.assertEqual(sys.getrefcount(a), a_refcount + 1) # Not mutable with self.assertRaisesRegex(TypeError, "object does not support item assignment"): b[1, 2] = '!' # b should keep a reference to a, so deleting the local reference # shouldn't affect it del a self.assertTrue(sys.getrefcount(b.owner), a_refcount) self.assertEqual(b[1][2], '6') # Now, if we delete b, a should not be referenced by anything anymore a = b.owner del b self.assertTrue(sys.getrefcount(a), a_refcount)
def test_slice_multidimensional_empty(self): a = memoryview(b'01234567' b'456789ab' b'89abcdef').cast('b', shape=[3, 8]) a_refcount = sys.getrefcount(a) b = containers.StridedArrayView2D(a)[1:1, 2:2] self.assertEqual(b.size, (0, 0)) # Empty view, original data not referenced at all self.assertIs(b.owner, None) self.assertEqual(sys.getrefcount(a), a_refcount)
def test_init_buffer_stride(self): a = memoryview(b'01234567' b'456789ab' b'89abcdef').cast('b', shape=[3, 8])[::2] self.assertEqual(bytes(a), b'0123456789abcdef') b = containers.StridedArrayView2D(a) self.assertEqual(len(b), 2) self.assertEqual(bytes(b), b'0123456789abcdef') self.assertEqual(b.size, (2, 8)) self.assertEqual(b.stride, (16, 1)) self.assertEqual(bytes(b[1]), b'89abcdef') self.assertEqual(b[1][3], 'b')
def test_init(self): a = containers.StridedArrayView2D() b = containers.MutableStridedArrayView2D() self.assertIs(a.owner, None) self.assertIs(b.owner, None) self.assertEqual(len(a), 0) self.assertEqual(len(b), 0) self.assertEqual(bytes(a), b'') self.assertEqual(bytes(b), b'') self.assertEqual(a.size, (0, 0)) self.assertEqual(b.size, (0, 0)) self.assertEqual(a.stride, (0, 0)) self.assertEqual(b.stride, (0, 0)) self.assertEqual(a.dimensions, 2) self.assertEqual(b.dimensions, 2)
def test_slice_stride(self): a = (b'01234567' b'456789ab' b'89abcdef') v = memoryview(a).cast('b', shape=[3, 8]) b = containers.StridedArrayView2D(v) # Check consistency with slices on memoryview c1 = v[0:3:2] c2 = b[0:3:2] self.assertEqual(len(c1), 2) self.assertEqual(len(c2), 2) self.assertIsInstance(c2, containers.StridedArrayView2D) self.assertEqual(bytes(c1), b'0123456789abcdef') self.assertEqual(bytes(c2), b'0123456789abcdef') self.assertEqual(c2.size, (2, 8)) self.assertEqual(c2.stride, (16, 1)) self.assertEqual(bytes(c2[1]), b'89abcdef')
def test_slice_stride_negative_multidimensional(self): a = (b'01234567' b'456789ab' b'89abcdef') v = memoryview(a).cast('b', shape=[3, 8]) b = containers.StridedArrayView2D(v) # Check consistency with slices on memoryview self.assertEqual(v.shape, (3, 8)) self.assertEqual(b.size, (3, 8)) self.assertEqual(v.strides, (8, 1)) self.assertEqual(b.stride, (8, 1)) with self.assertRaises(NotImplementedError): c1 = v[-1:None:-2, -2:2:-3] # HAH! c2 = b[-1:None:-2, -2:2:-3] self.assertEqual(len(c2), 2) self.assertEqual(bytes(c2), b'eb63') self.assertEqual(c2.size, (2, 2)) self.assertEqual(c2.stride, (-16, -3))
def test_convert_memoryview(self): a = memoryview(b'01234567' b'456789ab' b'89abcdef').cast('b', shape=[3, 8]) a_refcount = sys.getrefcount(a) b = containers.StridedArrayView2D(a) b_refcount = sys.getrefcount(b) # memoryview's buffer protocol returns itself, not the underlying # bytes, as it manages the Py_buffer instance. So this is expected. self.assertIs(b.owner, a) self.assertEqual(sys.getrefcount(a), a_refcount + 1) c = memoryview(b) self.assertEqual(c.ndim, 2) self.assertEqual(c.shape, (3, 8)) self.assertEqual(c.strides, (8, 1)) self.assertIs(c.obj, b) self.assertEqual(sys.getrefcount(a), a_refcount + 1) self.assertEqual(sys.getrefcount(b), b_refcount + 1)
def test_slice_stride_negative(self): a = (b'01234567' b'456789ab' b'89abcdef') v = memoryview(a).cast('b', shape=[3, 8]) b = containers.StridedArrayView2D(v) # Check consistency with slices on memoryview self.assertEqual(v.shape, (3, 8)) self.assertEqual(b.size, (3, 8)) self.assertEqual(v.strides, (8, 1)) self.assertEqual(b.stride, (8, 1)) c1 = v[-1:None:-2] # like [0:3:2] above, but reverted c2 = b[-1:None:-2] self.assertEqual(len(c1), 2) self.assertEqual(len(c2), 2) self.assertEqual(bytes(c1), b'89abcdef01234567') # like above but reverted self.assertEqual(bytes(c2), b'89abcdef01234567') self.assertEqual(c1.shape, (2, 8)) self.assertEqual(c2.size, (2, 8)) self.assertEqual(c1.strides, (-16, 1)) self.assertEqual(c2.stride, (-16, 1))
def test_init_buffer_unexpected_dimensions(self): a = b'123456' with self.assertRaisesRegex(BufferError, "expected 2 dimensions but got 1"): b = containers.StridedArrayView2D(a)