4040from ruamel .yaml .main import YAML
4141from schema_salad .exceptions import ValidationException
4242from schema_salad .ref_resolver import Loader , file_uri , uri_file_path
43- from schema_salad .sourceline import strip_dup_lineno
43+ from schema_salad .sourceline import cmap , strip_dup_lineno
4444from schema_salad .utils import ContextType , FetcherCallableType , json_dumps , yaml_no_ts
4545
4646from . import CWL_CONTENT_TYPES , workflow
4747from .argparser import arg_parser , generate_parser , get_default_args
48- from .builder import HasReqsHints
4948from .context import LoadingContext , RuntimeContext , getdefault
5049from .cwlrdf import printdot , printrdf
5150from .errors import ArgumentException , UnsupportedRequirement , WorkflowException
8988 CWLObjectType ,
9089 CWLOutputAtomType ,
9190 CWLOutputType ,
91+ HasReqsHints ,
9292 adjustDirObjs ,
9393 normalizeFilesDirs ,
9494 processes_to_kill ,
@@ -754,69 +754,95 @@ def my_represent_none(
754754 )
755755
756756
757+ def inherit_reqshints (tool : Process , parent : Process ) -> None :
758+ """Copy down requirements and hints from ancestors of a given process."""
759+ for parent_req in parent .requirements :
760+ found = False
761+ for tool_req in tool .requirements :
762+ if parent_req ["class" ] == tool_req ["class" ]:
763+ found = True
764+ break
765+ if not found :
766+ tool .requirements .append (parent_req )
767+ for parent_hint in parent .hints :
768+ found = False
769+ for tool_req in tool .requirements :
770+ if parent_hint ["class" ] == tool_req ["class" ]:
771+ found = True
772+ break
773+ if not found :
774+ for tool_hint in tool .hints :
775+ if parent_hint ["class" ] == tool_hint ["class" ]:
776+ found = True
777+ break
778+ if not found :
779+ tool .hints .append (parent_hint )
780+
781+
757782def choose_target (
758783 args : argparse .Namespace ,
759784 tool : Process ,
760- loadingContext : LoadingContext ,
785+ loading_context : LoadingContext ,
761786) -> Optional [Process ]:
762787 """Walk the Workflow, extract the subset matches all the args.targets."""
763- if loadingContext .loader is None :
764- raise Exception ("loadingContext .loader cannot be None" )
788+ if loading_context .loader is None :
789+ raise Exception ("loading_context .loader cannot be None" )
765790
766791 if isinstance (tool , Workflow ):
767792 url = urllib .parse .urlparse (tool .tool ["id" ])
768793 if url .fragment :
769794 extracted = get_subgraph (
770- [tool .tool ["id" ] + "/" + r for r in args .target ], tool
795+ [tool .tool ["id" ] + "/" + r for r in args .target ], tool , loading_context
771796 )
772797 else :
773798 extracted = get_subgraph (
774799 [
775- loadingContext .loader .fetcher .urljoin (tool .tool ["id" ], "#" + r )
800+ loading_context .loader .fetcher .urljoin (tool .tool ["id" ], "#" + r )
776801 for r in args .target
777802 ],
778803 tool ,
804+ loading_context ,
779805 )
780806 else :
781807 _logger .error ("Can only use --target on Workflows" )
782808 return None
783- if isinstance (loadingContext .loader .idx , MutableMapping ):
784- loadingContext .loader .idx [extracted ["id" ]] = extracted
785- tool = make_tool (extracted ["id" ], loadingContext )
809+ if isinstance (loading_context .loader .idx , MutableMapping ):
810+ loading_context .loader .idx [extracted ["id" ]] = extracted
811+ tool = make_tool (extracted ["id" ], loading_context )
786812 else :
787- raise Exception ("Missing loadingContext .loader.idx!" )
813+ raise Exception ("Missing loading_context .loader.idx!" )
788814
789815 return tool
790816
791817
792818def choose_step (
793819 args : argparse .Namespace ,
794820 tool : Process ,
795- loadingContext : LoadingContext ,
821+ loading_context : LoadingContext ,
796822) -> Optional [Process ]:
797823 """Walk the given Workflow and extract just args.single_step."""
798- if loadingContext .loader is None :
799- raise Exception ("loadingContext .loader cannot be None" )
824+ if loading_context .loader is None :
825+ raise Exception ("loading_context .loader cannot be None" )
800826
801827 if isinstance (tool , Workflow ):
802828 url = urllib .parse .urlparse (tool .tool ["id" ])
803829 if url .fragment :
804- extracted = get_step ( tool , tool .tool ["id" ] + "/" + args .single_step )
830+ step_id = tool .tool ["id" ] + "/" + args .single_step
805831 else :
806- extracted = get_step (
807- tool ,
808- loadingContext .loader .fetcher .urljoin (
809- tool .tool ["id" ], "#" + args .single_step
810- ),
832+ step_id = loading_context .loader .fetcher .urljoin (
833+ tool .tool ["id" ], "#" + args .single_step
811834 )
835+ extracted = get_step (tool , step_id , loading_context )
812836 else :
813837 _logger .error ("Can only use --single-step on Workflows" )
814838 return None
815- if isinstance (loadingContext .loader .idx , MutableMapping ):
816- loadingContext .loader .idx [extracted ["id" ]] = extracted
817- tool = make_tool (extracted ["id" ], loadingContext )
839+ if isinstance (loading_context .loader .idx , MutableMapping ):
840+ loading_context .loader .idx [extracted ["id" ]] = cast (
841+ Union [CommentedMap , CommentedSeq , str , None ], cmap (extracted )
842+ )
843+ tool = make_tool (extracted ["id" ], loading_context )
818844 else :
819- raise Exception ("Missing loadingContext .loader.idx!" )
845+ raise Exception ("Missing loading_context .loader.idx!" )
820846
821847 return tool
822848
@@ -826,36 +852,33 @@ def choose_process(
826852 tool : Process ,
827853 loadingContext : LoadingContext ,
828854) -> Optional [Process ]:
829- """Walk the given Workflow and extract just args.single_step ."""
855+ """Walk the given Workflow and extract just args.single_process ."""
830856 if loadingContext .loader is None :
831857 raise Exception ("loadingContext.loader cannot be None" )
832858
833859 if isinstance (tool , Workflow ):
834860 url = urllib .parse .urlparse (tool .tool ["id" ])
835861 if url .fragment :
836- extracted = get_process (
837- tool ,
838- tool .tool ["id" ] + "/" + args .single_process ,
839- loadingContext .loader .idx ,
840- )
862+ step_id = tool .tool ["id" ] + "/" + args .single_process
841863 else :
842- extracted = get_process (
843- tool ,
844- loadingContext .loader .fetcher .urljoin (
845- tool .tool ["id" ], "#" + args .single_process
846- ),
847- loadingContext .loader .idx ,
864+ step_id = loadingContext .loader .fetcher .urljoin (
865+ tool .tool ["id" ], "#" + args .single_process
848866 )
867+ extracted , workflow_step = get_process (
868+ tool ,
869+ step_id ,
870+ loadingContext ,
871+ )
849872 else :
850873 _logger .error ("Can only use --single-process on Workflows" )
851874 return None
852875 if isinstance (loadingContext .loader .idx , MutableMapping ):
853876 loadingContext .loader .idx [extracted ["id" ]] = extracted
854- tool = make_tool (extracted ["id" ], loadingContext )
877+ new_tool = make_tool (extracted ["id" ], loadingContext )
855878 else :
856879 raise Exception ("Missing loadingContext.loader.idx!" )
857-
858- return tool
880+ inherit_reqshints ( new_tool , workflow_step )
881+ return new_tool
859882
860883
861884def check_working_directories (
@@ -887,6 +910,33 @@ def check_working_directories(
887910 return None
888911
889912
913+ def print_targets (
914+ tool : Process ,
915+ stdout : Union [TextIO , StreamWriter ],
916+ loading_context : LoadingContext ,
917+ prefix : str = "" ,
918+ ) -> None :
919+ """Recursively find targets for --subgraph and friends."""
920+ for f in ("outputs" , "inputs" ):
921+ if tool .tool [f ]:
922+ _logger .info ("%s %s%s targets:" , prefix [:- 1 ], f [0 ].upper (), f [1 :- 1 ])
923+ stdout .write (
924+ " "
925+ + "\n " .join ([f"{ prefix } { shortname (t ['id' ])} " for t in tool .tool [f ]])
926+ + "\n "
927+ )
928+ if "steps" in tool .tool :
929+ _logger .info ("%s steps targets:" , prefix [:- 1 ])
930+ for t in tool .tool ["steps" ]:
931+ stdout .write (f" { prefix } { shortname (t ['id' ])} \n " )
932+ run : Union [str , Process ] = t ["run" ]
933+ if isinstance (run , str ):
934+ process = make_tool (run , loading_context )
935+ else :
936+ process = run
937+ print_targets (process , stdout , loading_context , shortname (t ["id" ]) + "/" )
938+
939+
890940def main (
891941 argsl : Optional [List [str ]] = None ,
892942 args : Optional [argparse .Namespace ] = None ,
@@ -1084,14 +1134,7 @@ def main(
10841134 return 0
10851135
10861136 if args .print_targets :
1087- for f in ("outputs" , "steps" , "inputs" ):
1088- if tool .tool [f ]:
1089- _logger .info ("%s%s targets:" , f [0 ].upper (), f [1 :- 1 ])
1090- stdout .write (
1091- " "
1092- + "\n " .join ([shortname (t ["id" ]) for t in tool .tool [f ]])
1093- + "\n "
1094- )
1137+ print_targets (tool , stdout , loadingContext )
10951138 return 0
10961139
10971140 if args .target :
0 commit comments