1- import argparse
21import copy
32import json
43import os
1110import networkx as nx
1211import yaml
1312
14-
1513from . import input_output as io
1614from . import inference , utils , utils_cwl , utils_graphs
1715from .wic_types import (CompilerInfo , EnvData , ExplicitEdgeCalls ,
2422
2523
2624def compile_workflow (yaml_tree_ast : YamlTree ,
27- args : argparse .Namespace ,
25+ compiler_options : Dict [str , bool ],
26+ graph_settings : Dict [str , Any ],
27+ yaml_tag_paths : Dict [str , str ],
2828 namespaces : Namespaces ,
2929 subgraphs_ : List [GraphReps ],
3030 explicit_edge_defs : ExplicitEdgeDefs ,
@@ -40,7 +40,9 @@ def compile_workflow(yaml_tree_ast: YamlTree,
4040
4141 Args:
4242 yaml_tree_ast (YamlTree): A tuple of name and yml AST
43- args (Any): all of the other positional arguments for compile_workflow_once
43+ compiler_options (Dict[str, bool]): The core flags needed for compilation and transformation into CWL
44+ graph_settings (Dict[str, Any]): The settings dict for graphpviz graphs
45+ yaml_tag_paths (Dict[str,str]): The paths that need to be included in (generated) yaml tags
4446 kwargs (Any): all of the other keyword arguments for compile_workflow_once
4547
4648 Returns:
@@ -58,8 +60,8 @@ def compile_workflow(yaml_tree_ast: YamlTree,
5860 i = 0
5961 while ast_modified and i < max_iters :
6062 subgraphs = copy .deepcopy (subgraphs_ ) # See comment below!
61- compiler_info = compile_workflow_once (yaml_tree , args , namespaces , subgraphs ,
62- explicit_edge_defs , explicit_edge_calls ,
63+ compiler_info = compile_workflow_once (yaml_tree , compiler_options , graph_settings , yaml_tag_paths ,
64+ namespaces , subgraphs , explicit_edge_defs , explicit_edge_calls ,
6365 input_mapping , output_mapping ,
6466 tools , is_root , relative_run_path , testing )
6567 node_data : NodeData = compiler_info .rose .data
@@ -95,14 +97,15 @@ def compile_workflow(yaml_tree_ast: YamlTree,
9597 subgraph_ .networkx .update (subgraphs [i ].networkx .edges , subgraphs [i ].networkx .nodes )
9698
9799 if i == max_iters :
98- import yaml
99100 print (yaml .dump (node_data .yml ))
100101 raise Exception (f'Error! Maximum number of iterations ({ max_iters } ) reached in compile_workflow!' )
101102 return compiler_info
102103
103104
104105def compile_workflow_once (yaml_tree_ast : YamlTree ,
105- args : argparse .Namespace ,
106+ compiler_options : Dict [str , bool ],
107+ graph_settings : Dict [str , Any ],
108+ yaml_tag_paths : Dict [str , str ],
106109 namespaces : Namespaces ,
107110 subgraphs : List [GraphReps ],
108111 explicit_edge_defs : ExplicitEdgeDefs ,
@@ -118,7 +121,9 @@ def compile_workflow_once(yaml_tree_ast: YamlTree,
118121
119122 Args:
120123 yaml_tree_ast (YamlTree): A tuple of name and yml AST
121- args (argparse.Namespace): The command line arguments
124+ graph_settings (Dict[str, Any]): The settings dict for graphpviz graphs
125+ yaml_tag_paths (Dict[str,str]): The paths that need to be included in (generated) yaml tags
126+ compiler_options (Dict[str, bool]): The core flags needed for compilation and transformation into CWL
122127 namespaces (Namespaces): Specifies the path in the yml AST to the current subworkflow
123128 subgraphs (List[Graph]): The graphs associated with the parent workflows of the current subworkflow
124129 explicit_edge_defs (ExplicitEdgeDefs): Stores the (path, value) of the explicit edge definition sites
@@ -209,19 +214,6 @@ def compile_workflow_once(yaml_tree_ast: YamlTree,
209214
210215 tools_lst : List [Tool ] = []
211216
212- # to be given to graph util functions
213- graph_settings = {}
214- graph_settings ['graph_dark_theme' ] = args .graph_dark_theme
215- graph_settings ['graph_inline_depth' ] = args .graph_inline_depth
216- graph_settings ['graph_label_edges' ] = args .graph_label_edges
217- graph_settings ['graph_show_outputs' ] = args .graph_show_outputs
218-
219- # to be gieven io absolute_yaml_tags function
220- yaml_tag_paths : Dict [str , str ] = {}
221- yaml_tag_paths ['cachedir' ] = args .cachedir
222- yaml_tag_paths ['yaml' ] = args .yaml
223- yaml_tag_paths ['homedir' ] = args .homedir
224-
225217 for i , step_key in enumerate (steps_keys ):
226218 step_name_i = utils .step_name_str (yaml_stem , i , step_key )
227219 stem = Path (step_key ).stem
@@ -254,9 +246,9 @@ def compile_workflow_once(yaml_tree_ast: YamlTree,
254246 graphdata = GraphData (step_key )
255247 subgraph = GraphReps (subgraph_gv , subgraph_nx , graphdata )
256248
257- sub_compiler_info = compile_workflow (sub_yaml_tree , args , namespaces + [ step_name_or_key ] ,
258- subgraphs + [subgraph ], explicit_edge_defs_copy ,
259- explicit_edge_calls_copy ,
249+ sub_compiler_info = compile_workflow (sub_yaml_tree , compiler_options , graph_settings , yaml_tag_paths ,
250+ namespaces + [step_name_or_key ], subgraphs + [ subgraph ] ,
251+ explicit_edge_defs_copy , explicit_edge_calls_copy ,
260252 input_mapping_copy , output_mapping_copy ,
261253 tools , False , relative_run_path , testing )
262254
@@ -340,14 +332,6 @@ def compile_workflow_once(yaml_tree_ast: YamlTree,
340332 rose_tree_list .append (rose_tree_base_case )
341333 tools_lst .append (tool_i )
342334
343- if not testing :
344- # Disable for testing because when testing in parallel, the *.gv Graphviz files
345- # can be written/read to/from disk simultaneously, which results in
346- # intermittent 'syntax errors'.
347- pass
348- # Actually, this is a significant performance bottleneck and isn't really necessary.
349- # utils_graphs.make_tool_dag(stem, tool_i, args.graph_dark_theme)
350-
351335 # Add run tag, using relative or flat-directory paths
352336 # NOTE: run: path issues were causing test_cwl_embedding_independence()
353337 # to fail, so I simply ignore the run tag in that test.
@@ -419,13 +403,11 @@ def compile_workflow_once(yaml_tree_ast: YamlTree,
419403 # (Solution: refactor all required arguments out of config and list
420404 # them as explicit inputs in the cwl files, then modify the python
421405 # files accordingly.)
422- # print(args_required)
423406
424407 sub_args_provided = [arg for arg in args_required if arg in explicit_edge_calls_copy ]
425- # print(sub_args_provided)
426408
427409 label = step_key
428- if args . graph_label_stepname :
410+ if graph_settings [ ' graph_label_stepname' ] :
429411 label = step_name_or_key
430412 step_node_name = '___' .join (namespaces + [step_name_or_key ])
431413
@@ -439,11 +421,11 @@ def compile_workflow_once(yaml_tree_ast: YamlTree,
439421 graph_gv .node (step_node_name , ** attrs )
440422 graph_nx .add_node (step_node_name )
441423 graphdata .nodes .append ((step_node_name , attrs ))
442- elif not (step_key in subkeys and len (namespaces ) < args . graph_inline_depth ):
424+ elif not (step_key in subkeys and len (namespaces ) < graph_settings [ ' graph_inline_depth' ] ):
443425 nssnode = namespaces + [step_name_or_key ]
444426 # Just like in add_graph_edge(), here we can hide all of the details
445427 # below a given depth by simply truncating the node's namespaces.
446- nssnode = nssnode [:(1 + args . graph_inline_depth )]
428+ nssnode = nssnode [:(1 + graph_settings [ ' graph_inline_depth' ] )]
447429 step_node_name = '___' .join (nssnode )
448430 # NOTE: NOT wic_graphviz_step_i
449431 # get the label (if any) from the subworkflow
@@ -633,11 +615,11 @@ def compile_workflow_once(yaml_tree_ast: YamlTree,
633615 new_val = {'source' : in_name }
634616 steps [i ]['in' ][arg_key ] = new_val
635617
636- if args . graph_show_inputs :
618+ if graph_settings [ ' graph_show_inputs' ] :
637619 input_node_name = '___' .join (namespaces + [step_name_or_key , arg_key ])
638620 attrs = {'label' : arg_key , 'shape' : 'box' , 'style' : 'rounded, filled' , 'fillcolor' : 'lightgreen' }
639621 graph_gv .node (input_node_name , ** attrs )
640- font_edge_color = 'black' if args . graph_dark_theme else 'white'
622+ font_edge_color = 'black' if graph_settings [ ' graph_dark_theme' ] else 'white'
641623 graph_gv .edge (input_node_name , step_node_name , color = font_edge_color )
642624 graph_nx .add_node (input_node_name )
643625 graph_nx .add_edge (input_node_name , step_node_name )
@@ -668,18 +650,10 @@ def compile_workflow_once(yaml_tree_ast: YamlTree,
668650 except Exception :
669651 pass
670652
671- if not args .allow_raw_cwl and (not hashable or arg_var not in yaml_tree .get ('inputs' , {})):
672- if not args .allow_raw_cwl :
673- print (f"Warning! Did you forget to use !ii before { arg_var } in { yaml_stem } .wic?" )
674- print ('If you want to compile the workflow anyway, use --allow_raw_cwl' )
675- sys .exit (1 )
676-
677- inputs = yaml_tree .get ('inputs' , {})
678- unbound_lit_var = 'Error! Unbound literal variable'
679- if inputs == {}:
680- raise Exception (f"{ unbound_lit_var } { arg_var } not in inputs: tag in { yaml_stem } .wic" )
681- inputs_dump = yaml .dump ({'inputs' : inputs })
682- raise Exception (f"{ unbound_lit_var } { arg_var } not in\n { inputs_dump } \n in { yaml_stem } .wic" )
653+ if not compiler_options ['allow_raw_cwl' ] and (not hashable or arg_var not in yaml_tree .get ('inputs' , {})):
654+ print (f"Warning! Did you forget to use !ii before { arg_var } in { yaml_stem } .wic?" )
655+ print ('If you want to compile the workflow anyway, use --allow_raw_cwl' )
656+ sys .exit (1 )
683657
684658 if 'doc' in inputs_key_dict :
685659 inputs_key_dict ['doc' ] += '\\ n' + in_dict .get ('doc' , '' )
@@ -757,22 +731,24 @@ def compile_workflow_once(yaml_tree_ast: YamlTree,
757731 # NOTE: We already added an edge to the appropriate subgraph above.
758732 # TODO: vars_workflow_output_internal?
759733 else :
760- if args . inference_disable :
734+ if compiler_options [ ' inference_disable' ] :
761735 continue
762736 insertions : List [StepId ] = []
763737 in_name_in_inputs_file_workflow : bool = (in_name in inputs_file_workflow )
764738 arg_key_in_yaml_tree_inputs : bool = (arg_key in yaml_tree .get ('inputs' , {}))
765- inference_use_naming_conventions = args .inference_use_naming_conventions
766- steps [i ] = inference .perform_edge_inference (inference_use_naming_conventions , graph_settings , tools , tools_lst , steps_keys ,
767- yaml_stem , i , steps , arg_key , graph , is_root , namespaces ,
768- vars_workflow_output_internal , input_mapping_copy , output_mapping_copy , inputs_workflow , in_name ,
769- in_name_in_inputs_file_workflow , arg_key_in_yaml_tree_inputs , insertions , wic_steps , testing )
739+ steps [i ] = inference .perform_edge_inference (compiler_options ['inference_use_naming_conventions' ],
740+ graph_settings , tools , tools_lst , steps_keys ,
741+ yaml_stem , i , steps , arg_key , graph ,
742+ is_root , namespaces , vars_workflow_output_internal ,
743+ input_mapping_copy , output_mapping_copy , inputs_workflow ,
744+ in_name , in_name_in_inputs_file_workflow ,
745+ arg_key_in_yaml_tree_inputs , insertions , wic_steps , testing )
770746 # NOTE: For now, perform_edge_inference mutably appends to
771747 # inputs_workflow and vars_workflow_output_internal.
772748
773749 # Automatically insert steps
774750 insertions = list (set (insertions )) # Remove duplicates
775- if len (insertions ) != 0 and args . insert_steps_automatically :
751+ if len (insertions ) != 0 and compiler_options [ ' insert_steps_automatically' ] :
776752 insertion = insertions [0 ]
777753 print ('Automaticaly inserting step' , insertion , i )
778754 if len (insertions ) != 1 :
@@ -802,7 +778,7 @@ def compile_workflow_once(yaml_tree_ast: YamlTree,
802778
803779 steps [i ] = utils_cwl .add_yamldict_keyval_out (steps [i ], step_key , list (tool_i .cwl ['outputs' ].keys ()))
804780
805- if args . partial_failure_enable :
781+ if compiler_options [ ' partial_failure_enable' ] :
806782 when_null_clauses = []
807783 for arg_in in args_required :
808784 when_null_clauses .append (f'inputs["{ arg_in } "] != null' )
0 commit comments