40
40
from ruamel .yaml .main import YAML
41
41
from schema_salad .exceptions import ValidationException
42
42
from 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
44
44
from schema_salad .utils import ContextType , FetcherCallableType , json_dumps , yaml_no_ts
45
45
46
46
from . import CWL_CONTENT_TYPES , workflow
47
47
from .argparser import arg_parser , generate_parser , get_default_args
48
- from .builder import HasReqsHints
49
48
from .context import LoadingContext , RuntimeContext , getdefault
50
49
from .cwlrdf import printdot , printrdf
51
50
from .errors import ArgumentException , UnsupportedRequirement , WorkflowException
89
88
CWLObjectType ,
90
89
CWLOutputAtomType ,
91
90
CWLOutputType ,
91
+ HasReqsHints ,
92
92
adjustDirObjs ,
93
93
normalizeFilesDirs ,
94
94
processes_to_kill ,
@@ -754,69 +754,95 @@ def my_represent_none(
754
754
)
755
755
756
756
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
+
757
782
def choose_target (
758
783
args : argparse .Namespace ,
759
784
tool : Process ,
760
- loadingContext : LoadingContext ,
785
+ loading_context : LoadingContext ,
761
786
) -> Optional [Process ]:
762
787
"""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" )
765
790
766
791
if isinstance (tool , Workflow ):
767
792
url = urllib .parse .urlparse (tool .tool ["id" ])
768
793
if url .fragment :
769
794
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
771
796
)
772
797
else :
773
798
extracted = get_subgraph (
774
799
[
775
- loadingContext .loader .fetcher .urljoin (tool .tool ["id" ], "#" + r )
800
+ loading_context .loader .fetcher .urljoin (tool .tool ["id" ], "#" + r )
776
801
for r in args .target
777
802
],
778
803
tool ,
804
+ loading_context ,
779
805
)
780
806
else :
781
807
_logger .error ("Can only use --target on Workflows" )
782
808
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 )
786
812
else :
787
- raise Exception ("Missing loadingContext .loader.idx!" )
813
+ raise Exception ("Missing loading_context .loader.idx!" )
788
814
789
815
return tool
790
816
791
817
792
818
def choose_step (
793
819
args : argparse .Namespace ,
794
820
tool : Process ,
795
- loadingContext : LoadingContext ,
821
+ loading_context : LoadingContext ,
796
822
) -> Optional [Process ]:
797
823
"""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" )
800
826
801
827
if isinstance (tool , Workflow ):
802
828
url = urllib .parse .urlparse (tool .tool ["id" ])
803
829
if url .fragment :
804
- extracted = get_step ( tool , tool .tool ["id" ] + "/" + args .single_step )
830
+ step_id = tool .tool ["id" ] + "/" + args .single_step
805
831
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
811
834
)
835
+ extracted = get_step (tool , step_id , loading_context )
812
836
else :
813
837
_logger .error ("Can only use --single-step on Workflows" )
814
838
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 )
818
844
else :
819
- raise Exception ("Missing loadingContext .loader.idx!" )
845
+ raise Exception ("Missing loading_context .loader.idx!" )
820
846
821
847
return tool
822
848
@@ -826,36 +852,33 @@ def choose_process(
826
852
tool : Process ,
827
853
loadingContext : LoadingContext ,
828
854
) -> Optional [Process ]:
829
- """Walk the given Workflow and extract just args.single_step ."""
855
+ """Walk the given Workflow and extract just args.single_process ."""
830
856
if loadingContext .loader is None :
831
857
raise Exception ("loadingContext.loader cannot be None" )
832
858
833
859
if isinstance (tool , Workflow ):
834
860
url = urllib .parse .urlparse (tool .tool ["id" ])
835
861
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
841
863
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
848
866
)
867
+ extracted , workflow_step = get_process (
868
+ tool ,
869
+ step_id ,
870
+ loadingContext ,
871
+ )
849
872
else :
850
873
_logger .error ("Can only use --single-process on Workflows" )
851
874
return None
852
875
if isinstance (loadingContext .loader .idx , MutableMapping ):
853
876
loadingContext .loader .idx [extracted ["id" ]] = extracted
854
- tool = make_tool (extracted ["id" ], loadingContext )
877
+ new_tool = make_tool (extracted ["id" ], loadingContext )
855
878
else :
856
879
raise Exception ("Missing loadingContext.loader.idx!" )
857
-
858
- return tool
880
+ inherit_reqshints ( new_tool , workflow_step )
881
+ return new_tool
859
882
860
883
861
884
def check_working_directories (
@@ -887,6 +910,33 @@ def check_working_directories(
887
910
return None
888
911
889
912
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
+
890
940
def main (
891
941
argsl : Optional [List [str ]] = None ,
892
942
args : Optional [argparse .Namespace ] = None ,
@@ -1084,14 +1134,7 @@ def main(
1084
1134
return 0
1085
1135
1086
1136
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 )
1095
1138
return 0
1096
1139
1097
1140
if args .target :
0 commit comments