|
37 | 37 | import math |
38 | 38 | import os |
39 | 39 | import unittest |
| 40 | +import struct |
40 | 41 | import imath |
41 | 42 |
|
42 | 43 | import IECore |
@@ -1366,6 +1367,91 @@ def test( self ) : |
1366 | 1367 | self.assertFalse( a._dataSourceEqual( ca2 ) ) |
1367 | 1368 | self.assertTrue(ca2._dataSourceEqual( ca3 ) ) |
1368 | 1369 |
|
| 1370 | +class TestBufferProtocol( unittest.TestCase ) : |
| 1371 | + |
| 1372 | + def testSimpleTypes( self ) : |
| 1373 | + |
| 1374 | + for elementType, vectorType, elementFormat in [ |
| 1375 | + # It would be nice to test for `IECore.HalfVectorData: "e"` |
| 1376 | + # but that is not supported in our Python. |
| 1377 | + ( float, IECore.FloatVectorData, "f" ), |
| 1378 | + ( float, IECore.DoubleVectorData, "d" ), |
| 1379 | + ( int, IECore.IntVectorData, "i" ), |
| 1380 | + ( int, IECore.UIntVectorData, "I" ), |
| 1381 | + ( chr, IECore.CharVectorData, "b" ), |
| 1382 | + ( int, IECore.UCharVectorData, "B" ), |
| 1383 | + ( int, IECore.ShortVectorData, "h" ), |
| 1384 | + ( int, IECore.UShortVectorData, "H" ), |
| 1385 | + ( int, IECore.Int64VectorData, "q" ), |
| 1386 | + ( int, IECore.UInt64VectorData, "Q" ), |
| 1387 | + ] : |
| 1388 | + with self.subTest( elementType = elementType, vectorType = vectorType ) : |
| 1389 | + v = vectorType( [ elementType( 1 ), elementType( 2 ), elementType( 3 ) ] ) |
| 1390 | + |
| 1391 | + b = v.asReadOnlyBuffer() |
| 1392 | + m = memoryview( b ) |
| 1393 | + |
| 1394 | + # `memoryview` returns `int` for C `char` / Python `chr` types. Cast to `chr` |
| 1395 | + self.assertEqual( list( m ) if elementType != chr else [ chr(i) for i in m ], list( v ) ) |
| 1396 | + self.assertIs( m.obj, b ) |
| 1397 | + self.assertTrue( m.readonly ) |
| 1398 | + self.assertEqual( m.format, elementFormat ) |
| 1399 | + self.assertEqual( m.ndim, 1 ) |
| 1400 | + self.assertEqual( m.shape, ( len( v ), ) ) |
| 1401 | + self.assertEqual( m.itemsize, struct.calcsize( elementFormat ) ) |
| 1402 | + self.assertEqual( m.strides, ( m.itemsize, ) ) |
| 1403 | + self.assertTrue( m.c_contiguous ) |
| 1404 | + self.assertTrue( m.contiguous ) |
| 1405 | + |
| 1406 | + def testReadOnlyBuffer( self ) : |
| 1407 | + |
| 1408 | + v = IECore.FloatVectorData( [ 1, 2, 3 ] ) |
| 1409 | + buffer = v.asReadOnlyBuffer() |
| 1410 | + bufferData = buffer.asData() |
| 1411 | + self.assertFalse( buffer.isWritable() ) |
| 1412 | + self.assertTrue( v._dataSourceEqual( bufferData ) ) |
| 1413 | + self.assertTrue( bufferData._dataSourceEqual( buffer.asData() ) ) |
| 1414 | + |
| 1415 | + m = memoryview( buffer ) |
| 1416 | + |
| 1417 | + self.assertTrue( m.readonly ) |
| 1418 | + self.assertTrue( v._dataSourceEqual( bufferData ) ) |
| 1419 | + self.assertTrue( bufferData._dataSourceEqual( buffer.asData() ) ) |
| 1420 | + |
| 1421 | + # We can modify `v` without affecting our buffer. |
| 1422 | + v.append( 99 ) |
| 1423 | + self.assertEqual( list( m ), [ 1, 2, 3 ] ) |
| 1424 | + self.assertFalse( v._dataSourceEqual( bufferData ) ) |
| 1425 | + self.assertTrue( bufferData._dataSourceEqual( buffer.asData() ) ) |
| 1426 | + |
| 1427 | + # We can modify `bufferData`. It's a copy so writing to it results |
| 1428 | + # in a deep copy of the source data. |
| 1429 | + bufferData[0] = 42 |
| 1430 | + self.assertEqual( list( bufferData ), [ 42, 2, 3 ] ) |
| 1431 | + self.assertFalse( bufferData._dataSourceEqual( buffer.asData() ) ) |
| 1432 | + self.assertEqual( list( buffer.asData() ), [ 1, 2, 3 ] ) |
| 1433 | + |
| 1434 | + def testReadWriteBuffer( self ) : |
| 1435 | + |
| 1436 | + v = IECore.FloatVectorData( [ 1, 2, 3 ] ) |
| 1437 | + buffer = v.asReadWriteBuffer() |
| 1438 | + bufferData = buffer.asData() |
| 1439 | + self.assertTrue( buffer.isWritable() ) |
| 1440 | + self.assertTrue( v._dataSourceEqual( bufferData ) ) |
| 1441 | + self.assertTrue( bufferData._dataSourceEqual( buffer.asData() ) ) |
| 1442 | + |
| 1443 | + # Creating a writable `memoryview` makes `bufferData` unique. |
| 1444 | + m = memoryview( buffer ) |
| 1445 | + self.assertFalse( m.readonly ) |
| 1446 | + self.assertFalse( v._dataSourceEqual( buffer.asData() ) ) |
| 1447 | + self.assertFalse( bufferData._dataSourceEqual( buffer.asData() ) ) |
| 1448 | + |
| 1449 | + # Modify the memoryview, which is reflected in the buffer. |
| 1450 | + m[0] = 42 |
| 1451 | + self.assertEqual( list( m ), [ 42, 2, 3 ] ) |
| 1452 | + self.assertEqual( list( buffer.asData() ), list( m ) ) |
| 1453 | + |
| 1454 | + |
1369 | 1455 | if __name__ == "__main__": |
1370 | 1456 | unittest.main() |
1371 | 1457 |
|
|
0 commit comments