Skip to content

Commit

Permalink
IECoreBinding : repr infinity for eval
Browse files Browse the repository at this point in the history
  • Loading branch information
ericmehl committed Dec 6, 2024
1 parent 55eed97 commit dc0c599
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 4 deletions.
4 changes: 4 additions & 0 deletions Changes
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
10.5.x.x (relative to 10.5.11.0)
========

Fixes
-----

- IECore : Fixed bug that was causing imath vectors and colors with values of `inf` / `std::numeric_limits<float>::infinity()` to be serialised in a way that could not be evaluated with `eval()`.


10.5.11.0 (relative to 10.5.10.0)
Expand Down
60 changes: 56 additions & 4 deletions src/IECorePython/IECoreBinding.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,14 @@ IECORE_POP_DEFAULT_VISIBILITY
using namespace std;
using namespace Imath;

namespace
{

static std::string g_positiveInfString = "float( 'inf' )";
static std::string g_negativeInfString = "-float( 'inf' )";

}

namespace IECorePython
{

Expand All @@ -70,7 +78,18 @@ std::string repr<VEC>( VEC &x )\
s << "imath." << #VEC << "( ";\
for( unsigned i=0; i<VEC::dimensions(); i++ )\
{\
s << boost::lexical_cast<string>( x[i] );\
if constexpr( std::numeric_limits<VEC::BaseType>::has_infinity )\
{\
s << (\
x[i] == std::numeric_limits<VEC::BaseType>::infinity() ? g_positiveInfString :\
( x[i] == -std::numeric_limits<VEC::BaseType>::infinity() ? g_negativeInfString :\
boost::lexical_cast<std::string>( x[i] ) ) \
);\
}\
else\
{\
s << boost::lexical_cast<string>( x[i] );\
}\
if( i!=VEC::dimensions()-1 )\
{\
s << ", ";\
Expand All @@ -86,7 +105,18 @@ std::string str<VEC>( VEC &x )\
std::stringstream s;\
for( unsigned i=0; i<VEC::dimensions(); i++ )\
{\
s << boost::lexical_cast<string>( x[i] );\
if constexpr( std::numeric_limits<VEC::BaseType>::has_infinity )\
{\
s << (\
x[i] == std::numeric_limits<VEC::BaseType>::infinity() ? g_positiveInfString :\
( x[i] == -std::numeric_limits<VEC::BaseType>::infinity() ? g_negativeInfString :\
boost::lexical_cast<std::string>( x[i] ) ) \
);\
}\
else\
{\
s << boost::lexical_cast<string>( x[i] );\
}\
if( i!=VEC::dimensions()-1 )\
{\
s << " ";\
Expand Down Expand Up @@ -142,7 +172,18 @@ std::string repr<COL>( COL &x )\
s << "imath." << #COL << "( ";\
for( unsigned i=0; i<COL::dimensions(); i++ )\
{\
s << boost::lexical_cast<std::string>( x[i] );\
if constexpr( std::numeric_limits<COL::BaseType>::has_infinity )\
{\
s << (\
x[i] == std::numeric_limits<COL::BaseType>::infinity() ? g_positiveInfString :\
( x[i] == -std::numeric_limits<COL::BaseType>::infinity() ? g_negativeInfString :\
boost::lexical_cast<std::string>( x[i] ) ) \
);\
}\
else\
{\
s << boost::lexical_cast<string>( x[i] );\
}\
if( i!=COL::dimensions()-1 )\
{\
s << ", ";\
Expand All @@ -158,7 +199,18 @@ std::string str<COL>( COL &x )\
std::stringstream s;\
for( unsigned i=0; i<COL::dimensions(); i++ )\
{\
s << boost::lexical_cast<std::string>( x[i] );\
if constexpr( std::numeric_limits<COL::BaseType>::has_infinity )\
{\
s << (\
x[i] == std::numeric_limits<COL::BaseType>::infinity() ? g_positiveInfString :\
( x[i] == -std::numeric_limits<COL::BaseType>::infinity() ? g_negativeInfString :\
boost::lexical_cast<std::string>( x[i] ) ) \
);\
}\
else\
{\
s << boost::lexical_cast<string>( x[i] );\
}\
if( i!=COL::dimensions()-1 )\
{\
s << " ";\
Expand Down
19 changes: 19 additions & 0 deletions test/IECore/ReprTest.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,25 @@ def test( self ) :
] :
self.assertTrue( type( v ) is type( eval( IECore.repr( v ) ) ) )
self.assertEqual( v, eval( IECore.repr( v ) ) )

def testInfinity( self ) :

for v in [
# Python raises "OverflowError : bad numeric conversion : positive overflow"
# when passing `float( "inf" )` to `V2f``
imath.V2d( float( "inf" ), float( "inf" ) ),
imath.V3f( float( "inf" ), float( "inf" ), float( "inf" ) ),
imath.V3d( float( "inf" ), float( "inf" ), float( "inf" ) ),
imath.Color3f( float( "inf" ), float( "inf" ), float( "inf" ) ),
imath.Color4f( float( "inf" ), float( "inf" ), float( "inf" ), float( "inf" ) ),
] :
with self.subTest( v = v ) :
self.assertTrue( type( v ) is type( eval( IECore.repr( v ) ) ) )
self.assertEqual( v, eval( IECore.repr( v ) ) )

self.assertTrue( type( -v ) is type( eval( IECore.repr( -v ) ) ) )
self.assertEqual( -v, eval( IECore.repr( -v ) ) )


if __name__ == "__main__":
unittest.main()
Expand Down

0 comments on commit dc0c599

Please sign in to comment.