@@ -445,6 +445,68 @@ def addplusplus(a, b, c=0):
445445 assert results ['sum' ] == sum (named_inputs .values ())
446446
447447
448+ def test_optional_per_function_with_same_output ():
449+ # Test that the same need can be both optional and not on different operations.
450+ #
451+ ## ATTENTION, the selected function is NOT the one with more inputs
452+ # but the 1st satisfiable function added in the network.
453+
454+ add_op = operation (name = 'add' , needs = ['a' , 'b' ], provides = 'a+b' )(add )
455+ sub_op_optional = operation (
456+ name = 'sub_opt' , needs = ['a' , modifiers .optional ('b' )], provides = 'a+b'
457+ )(lambda a , b = 10 : a - b )
458+
459+ # Normal order
460+ #
461+ pipeline = compose (name = 'partial_optionals' )(add_op , sub_op_optional )
462+ #
463+ named_inputs = {'a' : 1 , 'b' : 2 }
464+ assert pipeline (named_inputs ) == {'a' : 1 , 'a+b' : 3 , 'b' : 2 }
465+ assert pipeline (named_inputs , ['a+b' ]) == {'a+b' : 3 }
466+ #
467+ named_inputs = {'a' : 1 }
468+ assert pipeline (named_inputs ) == {'a' : 1 , 'a+b' : - 9 }
469+ assert pipeline (named_inputs , ['a+b' ]) == {'a+b' : - 9 }
470+
471+ # Inverse op order
472+ #
473+ pipeline = compose (name = 'partial_optionals' )(sub_op_optional , add_op )
474+ #
475+ named_inputs = {'a' : 1 , 'b' : 2 }
476+ assert pipeline (named_inputs ) == {'a' : 1 , 'a+b' : - 1 , 'b' : 2 }
477+ assert pipeline (named_inputs , ['a+b' ]) == {'a+b' : - 1 }
478+ #
479+ named_inputs = {'a' : 1 }
480+ assert pipeline (named_inputs ) == {'a' : 1 , 'a+b' : - 9 }
481+ assert pipeline (named_inputs , ['a+b' ]) == {'a+b' : - 9 }
482+
483+ # PARALLEL + Normal order
484+ #
485+ pipeline = compose (name = 'partial_optionals' )(add_op , sub_op_optional )
486+ pipeline .set_execution_method ("parallel" )
487+ #
488+ named_inputs = {'a' : 1 , 'b' : 2 }
489+ assert pipeline (named_inputs ) == {'a' : 1 , 'a+b' : 3 , 'b' : 2 }
490+ assert pipeline (named_inputs , ['a+b' ]) == {'a+b' : 3 }
491+ #
492+ named_inputs = {'a' : 1 }
493+ assert pipeline (named_inputs ) == {'a' : 1 , 'a+b' : - 9 }
494+ assert pipeline (named_inputs , ['a+b' ]) == {'a+b' : - 9 }
495+
496+ # PARALLEL + Inverse op order
497+ #
498+ pipeline = compose (name = 'partial_optionals' )(sub_op_optional , add_op )
499+ pipeline .set_execution_method ("parallel" )
500+ #
501+ named_inputs = {'a' : 1 , 'b' : 2 }
502+ assert pipeline (named_inputs ) == {'a' : 1 , 'a+b' : - 1 , 'b' : 2 }
503+ assert pipeline (named_inputs , ['a+b' ]) == {'a+b' : - 1 }
504+ #
505+ named_inputs = {'a' : 1 }
506+ assert pipeline (named_inputs ) == {'a' : 1 , 'a+b' : - 9 }
507+ assert pipeline (named_inputs , ['a+b' ]) == {'a+b' : - 9 }
508+
509+
448510def test_deleted_optional ():
449511 # Test that DeleteInstructions included for optionals do not raise
450512 # exceptions when the corresponding input is not prodided.
0 commit comments