From 4c1438b15e59bf609b11f3b962423989a28bca25 Mon Sep 17 00:00:00 2001 From: ivanimanishi Date: Tue, 11 Jul 2023 10:32:02 -0700 Subject: [PATCH 1/7] FrameRange : Prevent creation of FrameRanges with negative steps Previously, you could create a FrameRange object with a negative step, but it would go into an infinite loop if you tried to get the frame list Given that we have the ReversedFrameList that achieves the same as a negative step, it felt like using that was the correct approach. Note that we still include the support for the negative step in the parse method, so that we can provide a more useful error message during init. --- Changes | 5 +++++ src/IECore/FrameRange.cpp | 8 ++++++++ test/IECore/FrameList.py | 19 ++++++++++++++++++- 3 files changed, 31 insertions(+), 1 deletion(-) diff --git a/Changes b/Changes index 415b73b1d9..8649fd791b 100644 --- a/Changes +++ b/Changes @@ -1,6 +1,11 @@ 10.4.x.x (relative to 10.4.10.0) ======== +Fixes +----- + +- FrameRange : Prevented creation of FrameRanges with negative steps + 10.4.10.0 (relative to 10.4.9.1) ======== diff --git a/src/IECore/FrameRange.cpp b/src/IECore/FrameRange.cpp index ef746faa76..8266abfaa2 100644 --- a/src/IECore/FrameRange.cpp +++ b/src/IECore/FrameRange.cpp @@ -58,6 +58,10 @@ FrameRange::FrameRange( Frame start, Frame end, Frame step ) : m_start( start ), { throw Exception( "FrameRange step cannot be zero" ); } + if ( step < 0 ) + { + throw Exception( "FrameRange step cannot be negative. Consider using the reverse suffix instead." ); + } } FrameRange::~FrameRange() @@ -102,6 +106,10 @@ void FrameRange::setStep( Frame step ) { throw Exception( "FrameRange step cannot be zero" ); } + if ( step < 0 ) + { + throw Exception( "FrameRange step cannot be negative. Consider using the reverse suffix instead." ); + } m_step = step; } diff --git a/test/IECore/FrameList.py b/test/IECore/FrameList.py index 8963a5f494..ed03fd4ae7 100644 --- a/test/IECore/FrameList.py +++ b/test/IECore/FrameList.py @@ -55,7 +55,24 @@ def testReverseConstruction( self ) : self.assertEqual( f.asList(), [ 5, 4, 3, 2, 1 ] ) self.assertEqual( IECore.frameListFromList( [ 5, 4, 3, 2, 1 ] ), f ) + def testFrameRange( self ) : + + f = IECore.FrameList.parse( "1-5" ) + self.assertTrue( isinstance( f, IECore.FrameRange ) ) + self.assertEqual( f.asList(), [ 1, 2, 3, 4, 5 ] ) + # test step + f = IECore.FrameList.parse( "10-20x5" ) + self.assertTrue( isinstance( f, IECore.FrameRange ) ) + self.assertEqual( f.asList(), [ 10, 15, 20 ] ) + # start must be smaller or equal to end + self.assertRaises( Exception, IECore.FrameList.parse, "5-1" ) + # step must be positive + self.assertRaises( Exception, IECore.FrameList.parse, "1-5x0" ) + self.assertRaises( Exception, IECore.FrameList.parse, "1-5x-1" ) + self.assertRaises( Exception, IECore.FrameList.parse, "5-1x-1" ) + + ## \todo: there should probably be a lot more tests in here... if __name__ == "__main__": - unittest.main() + unittest.main() From 2b7a2e3e8c0353c744964eeb21e13d46ba611b3a Mon Sep 17 00:00:00 2001 From: ivanimanishi Date: Tue, 11 Jul 2023 11:44:08 -0700 Subject: [PATCH 2/7] DataTraits.dataTypeFromElement : Fix errors when receiving a list `__dataTypesConversionDict` contains an item that returns a `None` value which would cause an error. --- python/IECore/DataTraits.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/python/IECore/DataTraits.py b/python/IECore/DataTraits.py index 88a0bb0689..d5c90e8f27 100644 --- a/python/IECore/DataTraits.py +++ b/python/IECore/DataTraits.py @@ -263,6 +263,8 @@ def dataTypeFromElement(element): # We have to check the list contents. elementValueType = type(element[0]) for (dataType, value) in __dataTypesConversionDict.items(): + if value is None: + continue if value[0] is list and len(value) >= 2 and value[2] is elementValueType: return dataType From 7e624c911f875504357aae8c65edf5b0b780450d Mon Sep 17 00:00:00 2001 From: ivanimanishi Date: Tue, 11 Jul 2023 13:42:54 -0700 Subject: [PATCH 3/7] DataTraits.dataTypeFromElement : Convert lists to preferred data type When converting a list, it was simply using the first match, which would often not be the desired one. Ex: converting `["abc", "b"]` to `IECore.CharVectorData( [ 97, 98 ] )`, instead of `IECore.StringVectorData( [ 'abc', 'b' ] )`. The solution here is to use, on lists, the already existing flag on the `__dataTypesConversionDict` entries that indicated the preferred IECore.Data type for a given source. The options selected here as the preferred one when there was ambiguity were the same ones as returned by the simple (non-vector) types. That required a small update to `dataTypeFromElementType()` in order to avoid returning a random return, now that `list` entries in `__dataTypesConversionDict` can have a preferred flag set to `True`. --- python/IECore/DataTraits.py | 55 +++++++++++++++++++------------------ 1 file changed, 29 insertions(+), 26 deletions(-) diff --git a/python/IECore/DataTraits.py b/python/IECore/DataTraits.py index d5c90e8f27..7ba138fa79 100644 --- a/python/IECore/DataTraits.py +++ b/python/IECore/DataTraits.py @@ -147,16 +147,16 @@ def isSequenceDataType(obj): IECore.M44fData: (imath.M44f, True), IECore.M44dData: (imath.M44d, True), - IECore.BoolVectorData: ( list, False, bool), + IECore.BoolVectorData: ( list, True, bool), IECore.CharVectorData: (list, False, str), IECore.UCharVectorData: (list, False, int), - IECore.IntVectorData: (list, False, int), + IECore.IntVectorData: (list, True, int), IECore.UIntVectorData: (list, False, int), IECore.HalfVectorData: (list, False, float), IECore.FloatVectorData: (list, False, float), - IECore.DoubleVectorData: (list, False, float), - IECore.StringVectorData: (list, False, str), - IECore.InternedStringVectorData: (list, False, IECore.InternedString), + IECore.DoubleVectorData: (list, True, float), + IECore.StringVectorData: (list, True, str), + IECore.InternedStringVectorData: (list, True, IECore.InternedString), IECore.ShortVectorData: (list, False, int), IECore.UShortVectorData: (list, False, int), IECore.Int64VectorData: (list, False, int), @@ -167,27 +167,27 @@ def isSequenceDataType(obj): IECore.V3fVectorDataBase: (list, False, imath.V3f), IECore.V3dVectorDataBase: (list, False, imath.V3d), IECore.V3iVectorDataBase: (list, False, imath.V3i), - IECore.V2fVectorData: (list, False, imath.V2f), - IECore.V2dVectorData: (list, False, imath.V2d), - IECore.V2iVectorData: (list, False, imath.V2i), - IECore.V3fVectorData: (list, False, imath.V3f), - IECore.V3dVectorData: (list, False, imath.V3d), - IECore.V3iVectorData: (list, False, imath.V3i), - IECore.QuatfVectorData: (list, False, imath.Quatf), - IECore.QuatdVectorData: (list, False, imath.Quatd), - IECore.Box2iVectorData: (list, False, imath.Box2i), - IECore.Box2fVectorData: (list, False, imath.Box2f), - IECore.Box2dVectorData: (list, False, imath.Box2d), - IECore.Box3iVectorData: (list, False, imath.Box3i), - IECore.Box3fVectorData: (list, False, imath.Box3f), - IECore.Box3dVectorData: (list, False, imath.Box3d), - IECore.M33fVectorData: (list, False, imath.M33f), - IECore.M33dVectorData: (list, False, imath.M33d), - IECore.M44fVectorData: (list, False, imath.M44f), - IECore.M44dVectorData: (list, False, imath.M44d), - IECore.Color3fVectorData: (list, False, imath.Color3f), + IECore.V2fVectorData: (list, True, imath.V2f), + IECore.V2dVectorData: (list, True, imath.V2d), + IECore.V2iVectorData: (list, True, imath.V2i), + IECore.V3fVectorData: (list, True, imath.V3f), + IECore.V3dVectorData: (list, True, imath.V3d), + IECore.V3iVectorData: (list, True, imath.V3i), + IECore.QuatfVectorData: (list, True, imath.Quatf), + IECore.QuatdVectorData: (list, True, imath.Quatd), + IECore.Box2iVectorData: (list, True, imath.Box2i), + IECore.Box2fVectorData: (list, True, imath.Box2f), + IECore.Box2dVectorData: (list, True, imath.Box2d), + IECore.Box3iVectorData: (list, True, imath.Box3i), + IECore.Box3fVectorData: (list, True, imath.Box3f), + IECore.Box3dVectorData: (list, True, imath.Box3d), + IECore.M33fVectorData: (list, True, imath.M33f), + IECore.M33dVectorData: (list, True, imath.M33d), + IECore.M44fVectorData: (list, True, imath.M44f), + IECore.M44dVectorData: (list, True, imath.M44d), + IECore.Color3fVectorData: (list, True, imath.Color3f), #IECore.Color3dVectorData: (list, False, IECore.Color3d), - IECore.Color4fVectorData: (list, False, imath.Color4f), + IECore.Color4fVectorData: (list, True, imath.Color4f), #IECore.Color4dVectorData: (list, False, IECore.Color4d), IECore.CompoundData: (dict, True, None), @@ -246,6 +246,9 @@ def valueTypeFromSequenceType(sequenceType): ## \ingroup python def dataTypeFromElementType(elementType): + if elementType is list: + raise TypeError( "`list` type is ambiguous and not a valid input to dataTypeFromElementType()" ) + for (dataType, value) in __dataTypesConversionDict.items(): if value is None: continue @@ -265,7 +268,7 @@ def dataTypeFromElement(element): for (dataType, value) in __dataTypesConversionDict.items(): if value is None: continue - if value[0] is list and len(value) >= 2 and value[2] is elementValueType: + if value[0] is list and len(value) >= 2 and value[1] and value[2] is elementValueType: return dataType return dataTypeFromElementType(type(element)) From eae39b5f3066a2275a01f8bd35c4cf9a41bc0f3f Mon Sep 17 00:00:00 2001 From: ivanimanishi Date: Tue, 11 Jul 2023 13:45:34 -0700 Subject: [PATCH 4/7] Changes : Updated with dataTypeFromElement fixes --- Changes | 1 + 1 file changed, 1 insertion(+) diff --git a/Changes b/Changes index 8649fd791b..a96e839a47 100644 --- a/Changes +++ b/Changes @@ -5,6 +5,7 @@ Fixes ----- - FrameRange : Prevented creation of FrameRanges with negative steps +- IECore.dataTypeFromElement : Fixed support for list to Vector conversions 10.4.10.0 (relative to 10.4.9.1) ======== From 2b0587512f84eec068e4a798994432c22f952f11 Mon Sep 17 00:00:00 2001 From: ivanimanishi Date: Fri, 14 Jul 2023 12:31:31 -0700 Subject: [PATCH 5/7] DataTraitsTest : Tests for `dataFromElement` --- test/IECore/DataTraitsTest.py | 67 ++++++++++++++++++++++++++++++++--- 1 file changed, 63 insertions(+), 4 deletions(-) diff --git a/test/IECore/DataTraitsTest.py b/test/IECore/DataTraitsTest.py index 6198e1115d..e860f04736 100644 --- a/test/IECore/DataTraitsTest.py +++ b/test/IECore/DataTraitsTest.py @@ -32,11 +32,11 @@ # ########################################################################## -import math import unittest import IECore -import random -import os +import datetime +import imath + class DataTraitsTest( unittest.TestCase ) : @@ -129,6 +129,65 @@ def testIsSequenceDataType( self ) : for data in falseData : self.assertFalse( IECore.DataTraits.isSequenceDataType( data ) ) + def testDataFromElement( self ) : + + dataMap = ( + ( True, IECore.BoolData, IECore.BoolVectorData ), + ( 10, IECore.IntData, IECore.IntVectorData ), + ( "abc", IECore.StringData, IECore.StringVectorData ), + ( IECore.InternedString( "abc" ), IECore.InternedStringData, IECore.InternedStringVectorData ), + ( 1.1, IECore.DoubleData, IECore.DoubleVectorData ), + ( imath.V2f( 1.0, 2.0 ), IECore.V2fData, IECore.V2fVectorData ), + ( imath.V2d( 1.0, 2.0 ), IECore.V2dData, IECore.V2dVectorData ), + ( imath.V2i( 1, 2 ), IECore.V2iData, IECore.V2iVectorData ), + ( imath.V3i( 1, 2, 3 ), IECore.V3iData, IECore.V3iVectorData ), + ( imath.V3f( 1.0, 2.0, 3.0 ), IECore.V3fData, IECore.V3fVectorData ), + ( imath.V3d( 1.0, 2.0, 3.0 ), IECore.V3dData, IECore.V3dVectorData ), + ( imath.Quatf(), IECore.QuatfData, IECore.QuatfVectorData ), + ( imath.Quatd(), IECore.QuatdData, IECore.QuatdVectorData ), + ( imath.Color3f(), IECore.Color3fData, IECore.Color3fVectorData ), + ( imath.Color4f(), IECore.Color4fData, IECore.Color4fVectorData ), + ( imath.Box2i(), IECore.Box2iData, IECore.Box2iVectorData ), + ( imath.Box3i(), IECore.Box3iData, IECore.Box3iVectorData ), + ( imath.Box2f(), IECore.Box2fData, IECore.Box2fVectorData ), + ( imath.Box2d(), IECore.Box2dData, IECore.Box2dVectorData ), + ( imath.Box3f(), IECore.Box3fData, IECore.Box3fVectorData ), + ( imath.Box3d(), IECore.Box3dData, IECore.Box3dVectorData ), + ( imath.M33f(), IECore.M33fData, IECore.M33fVectorData ), + ( imath.M33d(), IECore.M33dData, IECore.M33dVectorData ), + ( imath.M44f(), IECore.M44fData, IECore.M44fVectorData ), + ( imath.M44d(), IECore.M44dData, IECore.M44dVectorData ), + ( { "age" : 10 }, IECore.CompoundData, None ), + ( IECore.TransformationMatrixf(), IECore.TransformationMatrixfData, None ), + ( IECore.TransformationMatrixd(), IECore.TransformationMatrixdData, None ), + ( IECore.LineSegment3f( imath.V3f( 0 ), imath.V3f( 1 ) ), IECore.LineSegment3fData, None ), + ( IECore.LineSegment3d( imath.V3d( 0 ), imath.V3d( 1 ) ), IECore.LineSegment3dData, None ), + ( IECore.Splineff(), IECore.SplineffData, None ), + ( IECore.Splinedd(), IECore.SplineddData, None ), + ( IECore.SplinefColor3f(), IECore.SplinefColor3fData, None ), + ( IECore.SplinefColor4f(), IECore.SplinefColor4fData, None ), + ( datetime.datetime( 2023, 7, 14 ), IECore.DateTimeData, None ), + ( IECore.TimeCode(), IECore.TimeCodeData, None ), + ( IECore.PathMatcher(), IECore.PathMatcherData, None ), + ) + + for element, dataType, vectorType in dataMap : + # test single element conversion + self.assertEqual( IECore.dataFromElement( element ), dataType( element ) ) + if vectorType is None : + continue + + # test list of elements conversion to a vector data + self.assertEqual( + IECore.dataFromElement( [ element ] ), + vectorType( [ element ] ), + ) + + def testDataTypeFromElementType( self ) : + self.assertEqual( IECore.dataTypeFromElementType( int ) , IECore.IntData ) + self.assertRaises( TypeError, IECore.dataTypeFromElementType, list ) + + if __name__ == "__main__": - unittest.main() + unittest.main() From fd4018b859882e3dba8f6c055eeb96ea590b125f Mon Sep 17 00:00:00 2001 From: Ivan Imanishi Date: Mon, 17 Jul 2023 09:24:43 -0700 Subject: [PATCH 6/7] Changes : v10.4.10.1 --- Changes | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Changes b/Changes index a96e839a47..0eeb572c45 100644 --- a/Changes +++ b/Changes @@ -1,4 +1,7 @@ -10.4.x.x (relative to 10.4.10.0) +10.4.x.x (relative to 10.4.10.1) +======== + +10.4.10.1 (relative to 10.4.10.0) ======== Fixes From 43d779d35d5da45db5ac497c9c4ee9ed229874a4 Mon Sep 17 00:00:00 2001 From: Ivan Imanishi Date: Mon, 17 Jul 2023 09:25:47 -0700 Subject: [PATCH 7/7] SConstruct : Bumped to 10.4.10.1 --- SConstruct | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SConstruct b/SConstruct index c10ccb3991..bf15373977 100644 --- a/SConstruct +++ b/SConstruct @@ -57,7 +57,7 @@ SConsignFile() ieCoreMilestoneVersion = 10 # for announcing major milestones - may contain all of the below ieCoreMajorVersion = 4 # backwards-incompatible changes ieCoreMinorVersion = 10 # new backwards-compatible features -ieCorePatchVersion = 0 # bug fixes +ieCorePatchVersion = 1 # bug fixes ieCoreVersionSuffix = "" # used for alpha/beta releases. Example: "a1", "b2", etc. ###########################################################################################