33import argparse
44import os
55import sys
6- from pathlib import Path
7- from typing import Iterator , List , Union , cast
6+ from typing import Iterator , List , cast
87
9- import cwl_utils .parser .cwl_v1_0 as cwl
8+ import ruamel .yaml
9+
10+ import cwl_utils .parser as cwl
1011from cwl_utils .image_puller import (
1112 DockerImagePuller ,
1213 ImagePuller ,
1314 SingularityImagePuller ,
1415)
1516
16- ProcessType = Union [cwl .Workflow , cwl .CommandLineTool , cwl .ExpressionTool ]
17-
1817
1918def arg_parser () -> argparse .ArgumentParser :
2019 """Argument parser."""
@@ -35,41 +34,51 @@ def arg_parser() -> argparse.ArgumentParser:
3534 parser .add_argument (
3635 "--container-engine" ,
3736 dest = "container_engine" ,
38- default = "docker" ,
39- help = "Specify which command to use to run OCI containers ." ,
37+ help = "Specify which command to use to run OCI containers. "
38+ "Defaults to 'docker' (or 'singularity' if --singularity/-s is passed) ." ,
4039 )
4140 return parser
4241
4342
44- def parse_args (args : List [str ]) -> argparse .Namespace :
45- """Parse the command line arguments."""
46- return arg_parser ().parse_args (args )
47-
48-
49- def run (args : argparse .Namespace ) -> int :
50- """Extract the docker reqs and download them using Singularity or docker."""
43+ def run (args : argparse .Namespace ) -> List [cwl .DockerRequirement ]:
44+ """Extract the docker reqs and download them using Singularity or Docker."""
5145 os .makedirs (args .dir , exist_ok = True )
5246
53- top = cwl .load_document (args .input )
47+ top = cwl .load_document_by_uri (args .input )
48+ reqs : List [cwl .DockerRequirement ] = []
5449
5550 for req in traverse (top ):
51+ reqs .append (req )
5652 if not req .dockerPull :
57- print (f"Unable to save image from { req } due to lack of 'dockerPull'." )
53+ print (
54+ "Unable to save image from due to lack of 'dockerPull':" ,
55+ file = sys .stderr ,
56+ )
57+ yaml = ruamel .yaml .YAML ()
58+ yaml .dump (req .save (), sys .stderr )
5859 continue
5960 if args .singularity :
6061 image_puller : ImagePuller = SingularityImagePuller (
61- req .dockerPull , args .dir , "singularity"
62+ req .dockerPull ,
63+ args .dir ,
64+ args .container_engine
65+ if args .container_engine is not None
66+ else "singularity" ,
6267 )
6368 else :
6469 image_puller = DockerImagePuller (
65- req .dockerPull , args .dir , args .container_engine
70+ req .dockerPull ,
71+ args .dir ,
72+ args .container_engine
73+ if args .container_engine is not None
74+ else "docker" ,
6675 )
6776 image_puller .save_docker_image ()
68- return 0
77+ return reqs
6978
7079
7180def extract_docker_requirements (
72- process : ProcessType ,
81+ process : cwl . Process ,
7382) -> Iterator [cwl .DockerRequirement ]:
7483 """Yield an iterator of the docker reqs, normalizing the pull request."""
7584 for req in extract_docker_reqs (process ):
@@ -78,38 +87,30 @@ def extract_docker_requirements(
7887 yield req
7988
8089
81- def extract_docker_reqs (process : ProcessType ) -> Iterator [cwl .DockerRequirement ]:
90+ def extract_docker_reqs (process : cwl . Process ) -> Iterator [cwl .DockerRequirement ]:
8291 """For the given process, extract the DockerRequirement(s)."""
8392 if process .requirements :
8493 for req in process .requirements :
85- if isinstance (req , cwl .DockerRequirement ):
94+ if isinstance (req , cwl .DockerRequirementTypes ):
8695 yield req
8796 if process .hints :
8897 for req in process .hints :
89- if isinstance (req , cwl .ProcessRequirement ):
90- if isinstance (req , cwl .DockerRequirement ):
91- yield req
92- elif req ["class" ] == "DockerRequirement" :
93- yield cwl .load_field (
94- req ,
95- cwl .DockerRequirementLoader ,
96- Path .cwd ().as_uri (),
97- process .loadingOptions ,
98- )
99-
100-
101- def traverse (process : ProcessType ) -> Iterator [cwl .DockerRequirement ]:
98+ if isinstance (req , cwl .DockerRequirementTypes ):
99+ yield req
100+
101+
102+ def traverse (process : cwl .Process ) -> Iterator [cwl .DockerRequirement ]:
102103 """Yield the iterator for the docker reqs, including an workflow steps."""
103104 yield from extract_docker_requirements (process )
104- if isinstance (process , cwl .Workflow ):
105+ if isinstance (process , cwl .WorkflowTypes ):
105106 yield from traverse_workflow (process )
106107
107108
108- def get_process_from_step (step : cwl .WorkflowStep ) -> ProcessType :
109+ def get_process_from_step (step : cwl .WorkflowStep ) -> cwl . Process :
109110 """Return the process for this step, loading it if necessary."""
110111 if isinstance (step .run , str ):
111- return cast (ProcessType , cwl .load_document (step .run ))
112- return cast (ProcessType , step .run )
112+ return cast (cwl . Process , cwl .load_document_by_uri (step .run ))
113+ return cast (cwl . Process , step .run )
113114
114115
115116def traverse_workflow (workflow : cwl .Workflow ) -> Iterator [cwl .DockerRequirement ]:
@@ -119,10 +120,11 @@ def traverse_workflow(workflow: cwl.Workflow) -> Iterator[cwl.DockerRequirement]
119120 yield from traverse (get_process_from_step (step ))
120121
121122
122- def main () -> None :
123+ def main () -> int :
123124 """Command line entry point."""
124- sys .exit (run (parse_args (sys .argv [1 :])))
125+ run (arg_parser ().parse_args (sys .argv [1 :]))
126+ return 0
125127
126128
127129if __name__ == "__main__" :
128- main ()
130+ sys . exit ( main () )
0 commit comments