@@ -50,6 +50,15 @@ def invoke(self, context: InvocationContext) -> IntegerCollectionTestInvocationO
5050 return IntegerCollectionTestInvocationOutput (collection = [base , base + 1 ])
5151
5252
53+ class IntegerCollectionWithBranchingTestInvocation (BaseInvocation ):
54+ value : int = InputField (default = 0 )
55+ branch_count : int = InputField (default = 2 )
56+
57+ def invoke (self , context : InvocationContext ) -> IntegerCollectionTestInvocationOutput :
58+ base = self .value * 10
59+ return IntegerCollectionTestInvocationOutput (collection = [base + branch for branch in range (self .branch_count )])
60+
61+
5362class MaybeEmptyIntegerCollectionTestInvocation (BaseInvocation ):
5463 value : int = InputField (default = 0 )
5564 always_empty : bool = InputField (default = False )
@@ -1365,9 +1374,58 @@ def test_graph_chained_collectors_preserve_ragged_empty_scope():
13651374 execute_all_nodes (state )
13661375
13671376 top_collect_ids = state .source_prepared_mapping ["top_collect" ]
1368- assert sorted (state ._get_iteration_path (node_id ) for node_id in top_collect_ids ) == [()]
1369- top_collect_id = next (iter (top_collect_ids ))
1370- assert state .results [top_collect_id ].collection == [[], [0 , 1 ], [10 , 11 ]]
1377+ top_collect_results = {
1378+ state ._get_iteration_path (node_id ): state .results [node_id ].collection for node_id in top_collect_ids
1379+ }
1380+ assert top_collect_results == {(0 ,): [[]], (1 ,): [[0 , 1 ], [10 , 11 ]]}
1381+
1382+
1383+ @pytest .mark .parametrize (("levels" , "branch_count" ), [(3 , 2 ), (4 , 2 ), (5 , 1 ), (6 , 1 ), (7 , 1 )])
1384+ def test_graph_chained_collectors_preserve_all_iteration_scopes (levels : int , branch_count : int ):
1385+ graph = Graph ()
1386+ graph .add_node (RangeInvocation (id = "source" , start = 0 , stop = 2 , step = 1 ))
1387+ graph .add_node (IterateInvocation (id = "iter_0" ))
1388+ for level in range (1 , levels ):
1389+ graph .add_node (IntegerCollectionWithBranchingTestInvocation (id = f"map_{ level } " , branch_count = branch_count ))
1390+ graph .add_node (IterateInvocation (id = f"iter_{ level } " ))
1391+ graph .add_node (AddInvocation (id = "body" , b = 0 ))
1392+
1393+ graph .add_edge (create_edge ("source" , "collection" , "iter_0" , "collection" ))
1394+ for level in range (1 , levels ):
1395+ graph .add_edge (create_edge (f"iter_{ level - 1 } " , "item" , f"map_{ level } " , "value" ))
1396+ graph .add_edge (create_edge (f"map_{ level } " , "collection" , f"iter_{ level } " , "collection" ))
1397+ graph .add_edge (create_edge (f"iter_{ levels - 1 } " , "item" , "body" , "a" ))
1398+
1399+ previous_node_id = "body"
1400+ previous_field = "value"
1401+ for level in reversed (range (levels )):
1402+ collect_id = f"collect_{ level } "
1403+ graph .add_node (CollectInvocation (id = collect_id ))
1404+ graph .add_edge (create_edge (previous_node_id , previous_field , collect_id , "item" ))
1405+ previous_node_id = collect_id
1406+ previous_field = "collection"
1407+
1408+ state = GraphExecutionState (graph = graph )
1409+ execute_all_nodes (state )
1410+
1411+ def paths (depth : int ) -> list [tuple [int , ...]]:
1412+ if depth == 0 :
1413+ return [()]
1414+ branch_level = depth - 1
1415+ branch_options = range (2 ) if branch_level == 0 else range (branch_count )
1416+ return [prefix + (branch ,) for prefix in paths (depth - 1 ) for branch in branch_options ]
1417+
1418+ def expected_collection (level : int , prefix : tuple [int , ...]):
1419+ branch_options = range (2 ) if level == 0 else range (branch_count )
1420+ if level == levels - 1 :
1421+ return [int ("" .join (map (str , prefix + (branch ,)))) for branch in branch_options ]
1422+ return [expected_collection (level + 1 , prefix + (branch ,)) for branch in branch_options ]
1423+
1424+ for level in range (levels ):
1425+ prepared_ids = state .source_prepared_mapping [f"collect_{ level } " ]
1426+ actual = {state ._get_iteration_path (node_id ): state .results [node_id ].collection for node_id in prepared_ids }
1427+ expected = {prefix : expected_collection (level , prefix ) for prefix in paths (level )}
1428+ assert actual == expected
13711429
13721430
13731431def test_graph_collector_reuses_outer_collection_input_for_each_nested_iterator_group ():
0 commit comments