3
3
import argparse
4
4
import os
5
5
import sys
6
- from pathlib import Path
7
- from typing import Iterator , List , Union , cast
6
+ from typing import Iterator , List , cast
8
7
9
- import cwl_utils .parser .cwl_v1_0 as cwl
8
+ import ruamel .yaml
9
+
10
+ import cwl_utils .parser as cwl
10
11
from cwl_utils .image_puller import (
11
12
DockerImagePuller ,
12
13
ImagePuller ,
13
14
SingularityImagePuller ,
14
15
)
15
16
16
- ProcessType = Union [cwl .Workflow , cwl .CommandLineTool , cwl .ExpressionTool ]
17
-
18
17
19
18
def arg_parser () -> argparse .ArgumentParser :
20
19
"""Argument parser."""
@@ -35,41 +34,51 @@ def arg_parser() -> argparse.ArgumentParser:
35
34
parser .add_argument (
36
35
"--container-engine" ,
37
36
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) ." ,
40
39
)
41
40
return parser
42
41
43
42
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."""
51
45
os .makedirs (args .dir , exist_ok = True )
52
46
53
- top = cwl .load_document (args .input )
47
+ top = cwl .load_document_by_uri (args .input )
48
+ reqs : List [cwl .DockerRequirement ] = []
54
49
55
50
for req in traverse (top ):
51
+ reqs .append (req )
56
52
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 )
58
59
continue
59
60
if args .singularity :
60
61
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" ,
62
67
)
63
68
else :
64
69
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" ,
66
75
)
67
76
image_puller .save_docker_image ()
68
- return 0
77
+ return reqs
69
78
70
79
71
80
def extract_docker_requirements (
72
- process : ProcessType ,
81
+ process : cwl . Process ,
73
82
) -> Iterator [cwl .DockerRequirement ]:
74
83
"""Yield an iterator of the docker reqs, normalizing the pull request."""
75
84
for req in extract_docker_reqs (process ):
@@ -78,38 +87,30 @@ def extract_docker_requirements(
78
87
yield req
79
88
80
89
81
- def extract_docker_reqs (process : ProcessType ) -> Iterator [cwl .DockerRequirement ]:
90
+ def extract_docker_reqs (process : cwl . Process ) -> Iterator [cwl .DockerRequirement ]:
82
91
"""For the given process, extract the DockerRequirement(s)."""
83
92
if process .requirements :
84
93
for req in process .requirements :
85
- if isinstance (req , cwl .DockerRequirement ):
94
+ if isinstance (req , cwl .DockerRequirementTypes ):
86
95
yield req
87
96
if process .hints :
88
97
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 ]:
102
103
"""Yield the iterator for the docker reqs, including an workflow steps."""
103
104
yield from extract_docker_requirements (process )
104
- if isinstance (process , cwl .Workflow ):
105
+ if isinstance (process , cwl .WorkflowTypes ):
105
106
yield from traverse_workflow (process )
106
107
107
108
108
- def get_process_from_step (step : cwl .WorkflowStep ) -> ProcessType :
109
+ def get_process_from_step (step : cwl .WorkflowStep ) -> cwl . Process :
109
110
"""Return the process for this step, loading it if necessary."""
110
111
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 )
113
114
114
115
115
116
def traverse_workflow (workflow : cwl .Workflow ) -> Iterator [cwl .DockerRequirement ]:
@@ -119,10 +120,11 @@ def traverse_workflow(workflow: cwl.Workflow) -> Iterator[cwl.DockerRequirement]
119
120
yield from traverse (get_process_from_step (step ))
120
121
121
122
122
- def main () -> None :
123
+ def main () -> int :
123
124
"""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
125
127
126
128
127
129
if __name__ == "__main__" :
128
- main ()
130
+ sys . exit ( main () )
0 commit comments