@@ -31,7 +31,9 @@ def parse_args(args: List[str]) -> argparse.Namespace:
31
31
"""Argument parser."""
32
32
parser = argparse .ArgumentParser (
33
33
description = "Tool to upgrade CWL documents from one version to another. "
34
- "Supports upgrading 'draft-3', 'v1.0', and 'v1.1' to 'v1.2'" ,
34
+ "Supports upgrading 'draft-3', 'v1.0', and 'v1.1' to 'v1.2'. For workflows "
35
+ 'that include "$import" or "run:" reference that refer to parent '
36
+ "directories, start cwl-upgrader from the topmost directory of your project." ,
35
37
formatter_class = argparse .ArgumentDefaultsHelpFormatter ,
36
38
)
37
39
parser .add_argument (
@@ -40,11 +42,11 @@ def parse_args(args: List[str]) -> argparse.Namespace:
40
42
parser .add_argument (
41
43
"--v1.1-only" ,
42
44
dest = "v1_1_only" ,
43
- help = "Don't upgrade past cwlVersion: v1.1" ,
45
+ help = "Don't upgrade past cwlVersion: v1.1. " ,
44
46
action = "store_true" ,
45
47
)
46
48
parser .add_argument (
47
- "--dir" , help = "Directory in which to save converted files" , default = Path .cwd ()
49
+ "--dir" , help = "Directory in which to save converted files. " , default = Path .cwd ()
48
50
)
49
51
parser .add_argument (
50
52
"inputs" ,
@@ -64,10 +66,21 @@ def main(args: Optional[List[str]] = None) -> int:
64
66
def run (args : argparse .Namespace ) -> int :
65
67
"""Main function."""
66
68
imports : Set [str ] = set ()
67
- if args .dir and not os .path .exists (args .dir ):
68
- os .makedirs (args .dir )
69
- for path in args .inputs :
69
+ if args .dir :
70
+ out_dir = Path (args .dir )
71
+ out_dir .mkdir (parents = True , exist_ok = True )
72
+ else :
73
+ out_dir = Path .cwd ()
74
+ for p in args .inputs :
75
+ path = Path (os .path .normpath (p ))
70
76
_logger .info ("Processing %s" , path )
77
+ if not p .startswith ("../" ) and path .resolve () != path :
78
+ # common_path = os.path.commonpath([out_dir.resolve(), path.resolve()])
79
+ # current_out_dir = out_dir / os.path.relpath(path, start=common_path)
80
+ current_out_dir = out_dir / path .parent
81
+ current_out_dir .mkdir (parents = True , exist_ok = True )
82
+ else :
83
+ current_out_dir = out_dir
71
84
document = load_cwl_document (path )
72
85
if "cwlVersion" not in document :
73
86
_logger .warn ("No cwlVersion found in %s, skipping it." , path )
@@ -89,17 +102,17 @@ def run(args: argparse.Namespace) -> int:
89
102
target_version = "latest"
90
103
upgraded_document = upgrade_document (
91
104
document ,
92
- args . dir ,
105
+ current_out_dir ,
93
106
target_version = target_version ,
94
107
imports = imports ,
95
108
)
96
- write_cwl_document (upgraded_document , Path (path ) .name , args . dir )
109
+ write_cwl_document (upgraded_document , current_out_dir / (path .name ) )
97
110
return 0
98
111
99
112
100
113
def upgrade_document (
101
114
document : Any ,
102
- output_dir : str ,
115
+ output_dir : Path ,
103
116
target_version : Optional [str ] = "latest" ,
104
117
imports : Optional [Set [str ]] = None ,
105
118
) -> Any :
@@ -158,7 +171,7 @@ def upgrade_document(
158
171
return main_updater (document , output_dir )
159
172
160
173
161
- def load_cwl_document (path : str ) -> Any :
174
+ def load_cwl_document (path : Union [ str , Path ] ) -> Any :
162
175
"""
163
176
Load the given path using the Ruamel YAML round-trip loader.
164
177
@@ -171,15 +184,14 @@ def load_cwl_document(path: str) -> Any:
171
184
return document
172
185
173
186
174
- def write_cwl_document (document : Any , name : str , dirname : str ) -> None :
187
+ def write_cwl_document (document : Any , path : Path ) -> None :
175
188
"""
176
189
Serialize the document using the Ruamel YAML round trip dumper.
177
190
178
191
Will also prepend "#!/usr/bin/env cwl-runner\n " and
179
192
set the executable bit if it is a CWL document.
180
193
"""
181
194
ruamel .yaml .scalarstring .walk_tree (document )
182
- path = Path (dirname ) / name
183
195
with open (path , "w" ) as handle :
184
196
if "cwlVersion" in document :
185
197
handle .write ("#!/usr/bin/env cwl-runner\n " )
@@ -189,7 +201,7 @@ def write_cwl_document(document: Any, name: str, dirname: str) -> None:
189
201
190
202
191
203
def process_imports (
192
- document : Any , imports : Set [str ], updater : Callable [[Any , str ], Any ], outdir : str
204
+ document : Any , imports : Set [str ], updater : Callable [[Any , Path ], Any ], outdir : Path
193
205
) -> None :
194
206
"""Find any '$import's and process them."""
195
207
if isinstance (document , CommentedMap ):
@@ -200,14 +212,9 @@ def process_imports(
200
212
import_doc = load_cwl_document (
201
213
Path (document .lc .filename ).parent / value
202
214
)
203
- write_cwl_document (
204
- updater (
205
- import_doc ,
206
- outdir ,
207
- ),
208
- Path (value ).name ,
209
- outdir ,
210
- )
215
+ new_path = (outdir / value ).resolve ()
216
+ new_path .parent .mkdir (parents = True , exist_ok = True )
217
+ write_cwl_document (updater (import_doc , outdir ), new_path )
211
218
imports .add (value )
212
219
else :
213
220
process_imports (value , imports , updater , outdir )
@@ -216,7 +223,7 @@ def process_imports(
216
223
process_imports (entry , imports , updater , outdir )
217
224
218
225
219
- def v1_0_to_v1_1 (document : CommentedMap , outdir : str ) -> CommentedMap :
226
+ def v1_0_to_v1_1 (document : CommentedMap , outdir : Path ) -> CommentedMap :
220
227
"""CWL v1.0.x to v1.1 transformation loop."""
221
228
_v1_0_to_v1_1 (document , outdir )
222
229
for key , value in document .items ():
@@ -231,20 +238,20 @@ def v1_0_to_v1_1(document: CommentedMap, outdir: str) -> CommentedMap:
231
238
return sort_v1_0 (document )
232
239
233
240
234
- def v1_0_to_v1_2 (document : CommentedMap , outdir : str ) -> CommentedMap :
241
+ def v1_0_to_v1_2 (document : CommentedMap , outdir : Path ) -> CommentedMap :
235
242
"""CWL v1.0.x to v1.2 transformation."""
236
243
document = v1_0_to_v1_1 (document , outdir )
237
244
document ["cwlVersion" ] = "v1.2"
238
245
return document
239
246
240
247
241
- def v1_1_to_v1_2 (document : CommentedMap , outdir : str ) -> CommentedMap :
248
+ def v1_1_to_v1_2 (document : CommentedMap , outdir : Path ) -> CommentedMap :
242
249
"""CWL v1.1 to v1.2 transformation."""
243
250
document ["cwlVersion" ] = "v1.2"
244
251
return document
245
252
246
253
247
- def draft3_to_v1_0 (document : CommentedMap , outdir : str ) -> CommentedMap :
254
+ def draft3_to_v1_0 (document : CommentedMap , outdir : Path ) -> CommentedMap :
248
255
"""Transformation loop."""
249
256
_draft3_to_v1_0 (document , outdir )
250
257
if isinstance (document , MutableMapping ):
@@ -260,17 +267,17 @@ def draft3_to_v1_0(document: CommentedMap, outdir: str) -> CommentedMap:
260
267
return sort_v1_0 (document )
261
268
262
269
263
- def draft3_to_v1_1 (document : CommentedMap , outdir : str ) -> CommentedMap :
270
+ def draft3_to_v1_1 (document : CommentedMap , outdir : Path ) -> CommentedMap :
264
271
"""transformation loop."""
265
272
return v1_0_to_v1_1 (draft3_to_v1_0 (document , outdir ), outdir )
266
273
267
274
268
- def draft3_to_v1_2 (document : CommentedMap , outdir : str ) -> CommentedMap :
275
+ def draft3_to_v1_2 (document : CommentedMap , outdir : Path ) -> CommentedMap :
269
276
"""transformation loop."""
270
277
return v1_1_to_v1_2 (v1_0_to_v1_1 (draft3_to_v1_0 (document , outdir ), outdir ), outdir )
271
278
272
279
273
- def _draft3_to_v1_0 (document : CommentedMap , outdir : str ) -> CommentedMap :
280
+ def _draft3_to_v1_0 (document : CommentedMap , outdir : Path ) -> CommentedMap :
274
281
"""Inner loop for transforming draft-3 to v1.0."""
275
282
if "class" in document :
276
283
if document ["class" ] == "Workflow" :
@@ -295,11 +302,11 @@ def _draft3_to_v1_0(document: CommentedMap, outdir: str) -> CommentedMap:
295
302
return document
296
303
297
304
298
- def _draft3_to_v1_1 (document : CommentedMap , outdir : str ) -> CommentedMap :
305
+ def _draft3_to_v1_1 (document : CommentedMap , outdir : Path ) -> CommentedMap :
299
306
return v1_0_to_v1_1 (_draft3_to_v1_0 (document , outdir ), outdir )
300
307
301
308
302
- def _draft3_to_v1_2 (document : CommentedMap , outdir : str ) -> CommentedMap :
309
+ def _draft3_to_v1_2 (document : CommentedMap , outdir : Path ) -> CommentedMap :
303
310
return _draft3_to_v1_1 (document , outdir ) # nothing needs doing for 1.2
304
311
305
312
@@ -318,7 +325,7 @@ def _draft3_to_v1_2(document: CommentedMap, outdir: str) -> CommentedMap:
318
325
}
319
326
320
327
321
- def _v1_0_to_v1_1 (document : CommentedMap , outdir : str ) -> CommentedMap :
328
+ def _v1_0_to_v1_1 (document : CommentedMap , outdir : Path ) -> CommentedMap :
322
329
"""Inner loop for transforming draft-3 to v1.0."""
323
330
if "class" in document :
324
331
if document ["class" ] == "Workflow" :
@@ -350,11 +357,13 @@ def _v1_0_to_v1_1(document: CommentedMap, outdir: str) -> CommentedMap:
350
357
isinstance (entry ["run" ], str )
351
358
and "#" not in entry ["run" ]
352
359
):
353
- path = Path (document .lc .filename ).parent / entry ["run" ]
354
- process = v1_0_to_v1_1 (
355
- load_cwl_document (str (path )), outdir
356
- )
357
- write_cwl_document (process , path .name , outdir )
360
+ path = (
361
+ Path (document .lc .filename ).parent / entry ["run" ]
362
+ ).resolve ()
363
+ process = v1_0_to_v1_1 (load_cwl_document (path ), outdir )
364
+ new_path = (outdir / entry ["run" ]).resolve ()
365
+ new_path .parent .mkdir (parents = True , exist_ok = True )
366
+ write_cwl_document (process , new_path )
358
367
elif isinstance (entry ["run" ], str ) and "#" in entry ["run" ]:
359
368
pass # reference to $graph entry
360
369
else :
@@ -397,11 +406,11 @@ def _v1_0_to_v1_1(document: CommentedMap, outdir: str) -> CommentedMap:
397
406
return document
398
407
399
408
400
- def _v1_0_to_v1_2 (document : CommentedMap , outdir : str ) -> CommentedMap :
409
+ def _v1_0_to_v1_2 (document : CommentedMap , outdir : Path ) -> CommentedMap :
401
410
return _v1_0_to_v1_1 (document , outdir ) # nothing needs doing for v1.2
402
411
403
412
404
- def _v1_1_to_v1_2 (document : CommentedMap , outdir : str ) -> CommentedMap :
413
+ def _v1_1_to_v1_2 (document : CommentedMap , outdir : Path ) -> CommentedMap :
405
414
return document
406
415
407
416
0 commit comments