@@ -66,21 +66,16 @@ def main(args: Optional[List[str]] = None) -> int:
66
66
def run (args : argparse .Namespace ) -> int :
67
67
"""Main function."""
68
68
imports : Set [str ] = set ()
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 ()
69
+ root_out_dir = Path (args .dir )
70
+ root_out_dir .mkdir (parents = True , exist_ok = True )
74
71
for p in args .inputs :
75
72
path = Path (os .path .normpath (p ))
76
73
_logger .info ("Processing %s" , path )
77
74
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
75
+ current_out_dir = root_out_dir / path .parent
81
76
current_out_dir .mkdir (parents = True , exist_ok = True )
82
77
else :
83
- current_out_dir = out_dir
78
+ current_out_dir = root_out_dir
84
79
document = load_cwl_document (path )
85
80
if "cwlVersion" not in document :
86
81
_logger .warn ("No cwlVersion found in %s, skipping it." , path )
@@ -103,6 +98,7 @@ def run(args: argparse.Namespace) -> int:
103
98
upgraded_document = upgrade_document (
104
99
document ,
105
100
current_out_dir ,
101
+ root_out_dir ,
106
102
target_version = target_version ,
107
103
imports = imports ,
108
104
)
@@ -113,6 +109,7 @@ def run(args: argparse.Namespace) -> int:
113
109
def upgrade_document (
114
110
document : Any ,
115
111
output_dir : Path ,
112
+ root_dir : Path ,
116
113
target_version : Optional [str ] = "latest" ,
117
114
imports : Optional [Set [str ]] = None ,
118
115
) -> Any :
@@ -167,8 +164,8 @@ def upgrade_document(
167
164
pass # does not happen? How to do the case that base version is v1.0?
168
165
else :
169
166
_logger .error (f"Unsupported cwlVersion: { version } " )
170
- process_imports (document , imports , inner_updater , output_dir )
171
- return main_updater (document , output_dir )
167
+ process_imports (document , imports , inner_updater , output_dir , root_dir )
168
+ return main_updater (document , output_dir , root_dir )
172
169
173
170
174
171
def load_cwl_document (path : Union [str , Path ]) -> Any :
@@ -200,8 +197,23 @@ def write_cwl_document(document: Any, path: Path) -> None:
200
197
path .chmod (path .stat ().st_mode | stat .S_IXUSR | stat .S_IXGRP | stat .S_IXOTH )
201
198
202
199
200
+ def check_path (root_dir : Path , new_path : Path ) -> None :
201
+ """Issue a warning if the new path is outside of the root path."""
202
+ common_path = Path (os .path .commonpath ([root_dir .resolve (), new_path .resolve ()]))
203
+ if common_path != root_dir :
204
+ _logger .warn (
205
+ "Writing file, '%s', outside of the output directory, '%s'." ,
206
+ os .path .normpath (new_path ),
207
+ root_dir ,
208
+ )
209
+
210
+
203
211
def process_imports (
204
- document : Any , imports : Set [str ], updater : Callable [[Any , Path ], Any ], outdir : Path
212
+ document : Any ,
213
+ imports : Set [str ],
214
+ updater : Callable [[Any , Path , Path ], Any ],
215
+ out_dir : Path ,
216
+ root_dir : Path ,
205
217
) -> None :
206
218
"""Find any '$import's and process them."""
207
219
if isinstance (document , CommentedMap ):
@@ -212,72 +224,85 @@ def process_imports(
212
224
import_doc = load_cwl_document (
213
225
Path (document .lc .filename ).parent / value
214
226
)
215
- new_path = (outdir / value ).resolve ()
227
+ new_path = (out_dir / value ).resolve ()
228
+ check_path (root_dir , new_path )
216
229
new_path .parent .mkdir (parents = True , exist_ok = True )
217
- write_cwl_document (updater (import_doc , outdir ), new_path )
230
+ write_cwl_document (updater (import_doc , out_dir , root_dir ), new_path )
218
231
imports .add (value )
219
232
else :
220
- process_imports (value , imports , updater , outdir )
233
+ process_imports (value , imports , updater , out_dir , root_dir )
221
234
elif isinstance (document , MutableSequence ):
222
235
for entry in document :
223
- process_imports (entry , imports , updater , outdir )
236
+ process_imports (entry , imports , updater , out_dir , root_dir )
224
237
225
238
226
- def v1_0_to_v1_1 (document : CommentedMap , outdir : Path ) -> CommentedMap :
239
+ def v1_0_to_v1_1 (document : CommentedMap , out_dir : Path , root_dir : Path ) -> CommentedMap :
227
240
"""CWL v1.0.x to v1.1 transformation loop."""
228
- _v1_0_to_v1_1 (document , outdir )
241
+ _v1_0_to_v1_1 (document , out_dir , root_dir )
229
242
for key , value in document .items ():
230
243
with SourceLine (document , key , Exception ):
231
244
if isinstance (value , CommentedMap ):
232
- document [key ] = _v1_0_to_v1_1 (value , outdir )
245
+ document [key ] = _v1_0_to_v1_1 (value , out_dir , root_dir )
233
246
elif isinstance (value , list ):
234
247
for index , entry in enumerate (value ):
235
248
if isinstance (entry , CommentedMap ):
236
- value [index ] = _v1_0_to_v1_1 (entry , outdir )
249
+ value [index ] = _v1_0_to_v1_1 (entry , out_dir , root_dir )
237
250
document ["cwlVersion" ] = "v1.1"
238
251
return sort_v1_0 (document )
239
252
240
253
241
- def v1_0_to_v1_2 (document : CommentedMap , outdir : Path ) -> CommentedMap :
254
+ def v1_0_to_v1_2 (document : CommentedMap , out_dir : Path , root_dir : Path ) -> CommentedMap :
242
255
"""CWL v1.0.x to v1.2 transformation."""
243
- document = v1_0_to_v1_1 (document , outdir )
256
+ document = v1_0_to_v1_1 (document , out_dir , root_dir )
244
257
document ["cwlVersion" ] = "v1.2"
245
258
return document
246
259
247
260
248
- def v1_1_to_v1_2 (document : CommentedMap , outdir : Path ) -> CommentedMap :
261
+ def v1_1_to_v1_2 (document : CommentedMap , out_dir : Path , root_dir : Path ) -> CommentedMap :
249
262
"""CWL v1.1 to v1.2 transformation."""
250
263
document ["cwlVersion" ] = "v1.2"
251
264
return document
252
265
253
266
254
- def draft3_to_v1_0 (document : CommentedMap , outdir : Path ) -> CommentedMap :
267
+ def draft3_to_v1_0 (
268
+ document : CommentedMap , out_dir : Path , root_dir : Path
269
+ ) -> CommentedMap :
255
270
"""Transformation loop."""
256
- _draft3_to_v1_0 (document , outdir )
271
+ _draft3_to_v1_0 (document , out_dir , root_dir )
257
272
if isinstance (document , MutableMapping ):
258
273
for key , value in document .items ():
259
274
with SourceLine (document , key , Exception ):
260
275
if isinstance (value , CommentedMap ):
261
- document [key ] = _draft3_to_v1_0 (value , outdir )
276
+ document [key ] = _draft3_to_v1_0 (value , out_dir , root_dir )
262
277
elif isinstance (value , list ):
263
278
for index , entry in enumerate (value ):
264
279
if isinstance (entry , CommentedMap ):
265
- value [index ] = _draft3_to_v1_0 (entry , outdir )
280
+ value [index ] = _draft3_to_v1_0 (entry , out_dir , root_dir )
266
281
document ["cwlVersion" ] = "v1.0"
267
282
return sort_v1_0 (document )
268
283
269
284
270
- def draft3_to_v1_1 (document : CommentedMap , outdir : Path ) -> CommentedMap :
285
+ def draft3_to_v1_1 (
286
+ document : CommentedMap , out_dir : Path , root_dir : Path
287
+ ) -> CommentedMap :
271
288
"""transformation loop."""
272
- return v1_0_to_v1_1 (draft3_to_v1_0 (document , outdir ), outdir )
289
+ return v1_0_to_v1_1 (draft3_to_v1_0 (document , out_dir , root_dir ), out_dir , root_dir )
273
290
274
291
275
- def draft3_to_v1_2 (document : CommentedMap , outdir : Path ) -> CommentedMap :
292
+ def draft3_to_v1_2 (
293
+ document : CommentedMap , out_dir : Path , root_dir : Path
294
+ ) -> CommentedMap :
276
295
"""transformation loop."""
277
- return v1_1_to_v1_2 (v1_0_to_v1_1 (draft3_to_v1_0 (document , outdir ), outdir ), outdir )
296
+ return v1_1_to_v1_2 (
297
+ v1_0_to_v1_1 (draft3_to_v1_0 (document , out_dir , root_dir ), out_dir , root_dir ),
298
+ out_dir ,
299
+ root_dir ,
300
+ )
278
301
279
302
280
- def _draft3_to_v1_0 (document : CommentedMap , outdir : Path ) -> CommentedMap :
303
+ def _draft3_to_v1_0 (
304
+ document : CommentedMap , out_dir : Path , root_dir : Path
305
+ ) -> CommentedMap :
281
306
"""Inner loop for transforming draft-3 to v1.0."""
282
307
if "class" in document :
283
308
if document ["class" ] == "Workflow" :
@@ -302,12 +327,16 @@ def _draft3_to_v1_0(document: CommentedMap, outdir: Path) -> CommentedMap:
302
327
return document
303
328
304
329
305
- def _draft3_to_v1_1 (document : CommentedMap , outdir : Path ) -> CommentedMap :
306
- return v1_0_to_v1_1 (_draft3_to_v1_0 (document , outdir ), outdir )
330
+ def _draft3_to_v1_1 (
331
+ document : CommentedMap , out_dir : Path , root_dir : Path
332
+ ) -> CommentedMap :
333
+ return v1_0_to_v1_1 (_draft3_to_v1_0 (document , out_dir , root_dir ), out_dir , root_dir )
307
334
308
335
309
- def _draft3_to_v1_2 (document : CommentedMap , outdir : Path ) -> CommentedMap :
310
- return _draft3_to_v1_1 (document , outdir ) # nothing needs doing for 1.2
336
+ def _draft3_to_v1_2 (
337
+ document : CommentedMap , out_dir : Path , root_dir : Path
338
+ ) -> CommentedMap :
339
+ return _draft3_to_v1_1 (document , out_dir , root_dir ) # nothing needs doing for 1.2
311
340
312
341
313
342
WORKFLOW_INPUT_INPUTBINDING = (
@@ -325,7 +354,9 @@ def _draft3_to_v1_2(document: CommentedMap, outdir: Path) -> CommentedMap:
325
354
}
326
355
327
356
328
- def _v1_0_to_v1_1 (document : CommentedMap , outdir : Path ) -> CommentedMap :
357
+ def _v1_0_to_v1_1 (
358
+ document : CommentedMap , out_dir : Path , root_dir : Path
359
+ ) -> CommentedMap :
329
360
"""Inner loop for transforming draft-3 to v1.0."""
330
361
if "class" in document :
331
362
if document ["class" ] == "Workflow" :
@@ -339,7 +370,7 @@ def _v1_0_to_v1_1(document: CommentedMap, outdir: Path) -> CommentedMap:
339
370
upgrade_v1_0_hints_and_reqs (entry )
340
371
if "run" in entry and isinstance (entry ["run" ], CommentedMap ):
341
372
process = entry ["run" ]
342
- _v1_0_to_v1_1 (process , outdir )
373
+ _v1_0_to_v1_1 (process , out_dir , root_dir )
343
374
if "cwlVersion" in process :
344
375
del process ["cwlVersion" ]
345
376
elif isinstance (steps , MutableMapping ):
@@ -350,18 +381,21 @@ def _v1_0_to_v1_1(document: CommentedMap, outdir: Path) -> CommentedMap:
350
381
if "run" in entry :
351
382
if isinstance (entry ["run" ], CommentedMap ):
352
383
process = entry ["run" ]
353
- _v1_0_to_v1_1 (process , outdir )
384
+ _v1_0_to_v1_1 (process , out_dir , root_dir )
354
385
if "cwlVersion" in process :
355
386
del process ["cwlVersion" ]
356
387
elif (
357
388
isinstance (entry ["run" ], str )
358
389
and "#" not in entry ["run" ]
359
390
):
360
- path = (
391
+ run_path = (
361
392
Path (document .lc .filename ).parent / entry ["run" ]
362
393
).resolve ()
363
- process = v1_0_to_v1_1 (load_cwl_document (path ), outdir )
364
- new_path = (outdir / entry ["run" ]).resolve ()
394
+ process = v1_0_to_v1_1 (
395
+ load_cwl_document (run_path ), out_dir , root_dir
396
+ )
397
+ new_path = out_dir / entry ["run" ]
398
+ check_path (root_dir , new_path )
365
399
new_path .parent .mkdir (parents = True , exist_ok = True )
366
400
write_cwl_document (process , new_path )
367
401
elif isinstance (entry ["run" ], str ) and "#" in entry ["run" ]:
@@ -406,11 +440,15 @@ def _v1_0_to_v1_1(document: CommentedMap, outdir: Path) -> CommentedMap:
406
440
return document
407
441
408
442
409
- def _v1_0_to_v1_2 (document : CommentedMap , outdir : Path ) -> CommentedMap :
410
- return _v1_0_to_v1_1 (document , outdir ) # nothing needs doing for v1.2
443
+ def _v1_0_to_v1_2 (
444
+ document : CommentedMap , out_dir : Path , root_dir : Path
445
+ ) -> CommentedMap :
446
+ return _v1_0_to_v1_1 (document , out_dir , root_dir ) # nothing needs doing for v1.2
411
447
412
448
413
- def _v1_1_to_v1_2 (document : CommentedMap , outdir : Path ) -> CommentedMap :
449
+ def _v1_1_to_v1_2 (
450
+ document : CommentedMap , out_dir : Path , root_dir : Path
451
+ ) -> CommentedMap :
414
452
return document
415
453
416
454
0 commit comments