fix an operation cache bug

when testing two operations for equality, need to check that both had an
optional arg set before testing the value
This commit is contained in:
John Cupitt 2015-01-29 13:47:14 +00:00
parent 2a1a371e5c
commit 57196ee702
4 changed files with 48 additions and 27 deletions

View File

@ -395,29 +395,41 @@ vips_object_equal_arg( VipsObject *object,
{
VipsObject *other = (VipsObject *) a;
if( (argument_class->flags & VIPS_ARGUMENT_CONSTRUCT) &&
(argument_class->flags & VIPS_ARGUMENT_INPUT) &&
argument_instance->assigned ) {
const char *name = g_param_spec_get_name( pspec );
GType type = G_PARAM_SPEC_VALUE_TYPE( pspec );
GValue v1 = { 0, };
GValue v2 = { 0, };
const char *name = g_param_spec_get_name( pspec );
GType type = G_PARAM_SPEC_VALUE_TYPE( pspec );
GValue v1 = { 0, };
GValue v2 = { 0, };
gboolean equal;
gboolean equal;
g_value_init( &v1, type );
g_value_init( &v2, type );
g_object_get_property( G_OBJECT( object ), name, &v1 );
g_object_get_property( G_OBJECT( other ), name, &v2 );
equal = vips_value_equal( pspec, &v1, &v2 );
g_value_unset( &v1 );
g_value_unset( &v2 );
/* Only test assigned input constructor args.
*/
if( !(argument_class->flags & VIPS_ARGUMENT_CONSTRUCT) ||
!(argument_class->flags & VIPS_ARGUMENT_INPUT) ||
!argument_instance->assigned )
return( NULL );
if( !equal )
return( object );
}
/* If this is an optional arg, we need to check that this was
* assigned on @other as well.
*/
if( !(argument_class->flags & VIPS_ARGUMENT_REQUIRED) &&
!vips_object_argument_isset( other, name ) )
/* Optional and was not set on other ... can't be
* equal.
*/
return( NULL );
return( NULL );
g_value_init( &v1, type );
g_value_init( &v2, type );
g_object_get_property( G_OBJECT( object ), name, &v1 );
g_object_get_property( G_OBJECT( other ), name, &v2 );
equal = vips_value_equal( pspec, &v1, &v2 );
g_value_unset( &v1 );
g_value_unset( &v2 );
/* Stop (return non-NULL) if we've found a difference.
*/
return( !equal ? object : NULL );
}
/* Are two objects equal, ie. have the same inputs.

View File

@ -167,6 +167,12 @@ static void
vips_similarity_init( VipsSimilarity *similarity )
{
similarity->scale = 1;
similarity->angle = 0;
similarity->interpolate = NULL;
similarity->odx = 0;
similarity->ody = 0;
similarity->idx = 0;
similarity->idy = 0;
}
/**

View File

@ -305,17 +305,21 @@ def _call_base(name, required, optional, self = None, option_string = None):
'Operator %s has no argument %s.' % (name, key))
# call
logging.debug('_call_base checking cache for op %s' % op)
op2 = Vips.cache_operation_build(op)
logging.debug('_call_base got op2 %s' % op2)
if op2 == None:
raise Error('Error calling operator %s.' % name)
# rescan args if op2 is different from op
if op2 != op:
logging.debug('_call_base rescanning args')
args = op2.get_args()
optional_output = {x.name: x for x in args if x.flags & enm.OUTPUT and
not x.flags & enm.REQUIRED}
# gather output args
logging.debug('_call_base fetching required output args')
out = []
for x in args:
@ -328,6 +332,7 @@ def _call_base(name, required, optional, self = None, option_string = None):
if x.flags & enm.INPUT and x.flags & enm.MODIFY:
out.append(x.get_value())
logging.debug('_call_base fetching optional output args')
out_dict = {}
for x in list(optional.keys()):
if x in optional_output:

View File

@ -64,16 +64,14 @@ class TestResample(unittest.TestCase):
im3 = im.affine([0, -1, 1, 0])
im2.write_to_file("im2.v")
im3.write_to_file("im3.v")
# not equal ?!?!?!
self.assertEqual((im2 - im3).abs().max(), 0)
im = Vips.Image.new_from_file("images/IMG_4618.jpg")
# attempt to read unset angle prop
im2 = im.similarity(scale = 2)
im3 = im.affine([2, 0, 0, 2])
im2.write_to_file("im2.v")
im3.write_to_file("im3.v")
self.assertEqual((im2 - im3).abs().max(), 0)
#im = Vips.Image.new_from_file("images/IMG_4618.jpg")
#im2 = im.similarity(scale = 2)
#im3 = im.affine([2, 0, 0, 2])
#im2.write_to_file("im2.v")
#im3.write_to_file("im3.v")
#self.assertEqual((im2 - im3).abs().max(), 0)
if __name__ == '__main__':
unittest.main()