|
8 | 8 | import os
|
9 | 9 | import sys
|
10 | 10 | import logging
|
| 11 | +import copy |
11 | 12 | from . import workflow
|
12 | 13 | from .errors import WorkflowException
|
13 | 14 | from . import process
|
@@ -114,6 +115,7 @@ def arg_parser(): # type: () -> argparse.ArgumentParser
|
114 | 115 | exgroup.add_argument("--print-pre", action="store_true", help="Print CWL document after preprocessing.")
|
115 | 116 | exgroup.add_argument("--print-deps", action="store_true", help="Print CWL document dependencies.")
|
116 | 117 | exgroup.add_argument("--print-input-deps", action="store_true", help="Print input object document dependencies.")
|
| 118 | + exgroup.add_argument("--pack", action="store_true", help="Combine components into single document and print.") |
117 | 119 | exgroup.add_argument("--version", action="store_true", help="Print version and exit")
|
118 | 120 |
|
119 | 121 | exgroup = parser.add_mutually_exclusive_group()
|
@@ -417,6 +419,76 @@ def makeRelative(u):
|
417 | 419 |
|
418 | 420 | stdout.write(json.dumps(deps, indent=4))
|
419 | 421 |
|
| 422 | +def flatten_deps(d, files): |
| 423 | + if isinstance(d, list): |
| 424 | + for s in d: |
| 425 | + flatten_deps(s, files) |
| 426 | + elif isinstance(d, dict): |
| 427 | + files.add(d["path"]) |
| 428 | + if "secondaryFiles" in d: |
| 429 | + flatten_deps(d["secondaryFiles"], files) |
| 430 | + |
| 431 | +def find_run(d, runs): |
| 432 | + if isinstance(d, list): |
| 433 | + for s in d: |
| 434 | + find_run(s, runs) |
| 435 | + elif isinstance(d, dict): |
| 436 | + if "run" in d and isinstance(d["run"], basestring): |
| 437 | + runs.add(d["run"]) |
| 438 | + for s in d.values(): |
| 439 | + find_run(s, runs) |
| 440 | + |
| 441 | +def replace_refs(d, rewrite, stem, newstem): |
| 442 | + if isinstance(d, list): |
| 443 | + for s,v in enumerate(d): |
| 444 | + if isinstance(v, basestring) and v.startswith(stem): |
| 445 | + d[s] = newstem + v[len(stem):] |
| 446 | + else: |
| 447 | + replace_refs(v, rewrite, stem, newstem) |
| 448 | + elif isinstance(d, dict): |
| 449 | + if "run" in d and isinstance(d["run"], basestring): |
| 450 | + d["run"] = rewrite[d["run"]] |
| 451 | + for s,v in d.items(): |
| 452 | + if isinstance(v, basestring) and v.startswith(stem): |
| 453 | + d[s] = newstem + v[len(stem):] |
| 454 | + replace_refs(v, rewrite, stem, newstem) |
| 455 | + |
| 456 | +def print_pack(document_loader, processobj, uri, metadata): |
| 457 | + def loadref(b, u): |
| 458 | + return document_loader.resolve_ref(u, base_url=b)[0] |
| 459 | + deps = process.scandeps(uri, processobj, |
| 460 | + set(("run",)), set(), loadref) |
| 461 | + |
| 462 | + fdeps = set((uri,)) |
| 463 | + flatten_deps(deps, fdeps) |
| 464 | + |
| 465 | + runs = set() |
| 466 | + for f in fdeps: |
| 467 | + find_run(document_loader.idx[f], runs) |
| 468 | + |
| 469 | + rewrite = {} |
| 470 | + if isinstance(processobj, list): |
| 471 | + for p in processobj: |
| 472 | + rewrite[p["id"]] = "#" + shortname(p["id"]) |
| 473 | + else: |
| 474 | + rewrite[uri] = "#main" |
| 475 | + |
| 476 | + for r in runs: |
| 477 | + rewrite[r] = "#" + shortname(r) |
| 478 | + |
| 479 | + packed = {"$graph": [], "cwlVersion": metadata["cwlVersion"]} |
| 480 | + for r,v in rewrite.items(): |
| 481 | + dc = copy.deepcopy(document_loader.idx[r]) |
| 482 | + dc["id"] = v |
| 483 | + dc["name"] = v |
| 484 | + replace_refs(dc, rewrite, r+"/" if "#" in r else r+"#", v+"/") |
| 485 | + packed["$graph"].append(dc) |
| 486 | + |
| 487 | + if len(packed["$graph"]) > 1: |
| 488 | + return json.dumps(packed, indent=4) |
| 489 | + else: |
| 490 | + return json.dumps(packed["$graph"][0], indent=4) |
| 491 | + |
420 | 492 | def versionstring():
|
421 | 493 | # type: () -> unicode
|
422 | 494 | pkg = pkg_resources.require("cwltool")
|
@@ -498,7 +570,11 @@ def main(argsl=None,
|
498 | 570 | document_loader, avsc_names, processobj, metadata, uri \
|
499 | 571 | = validate_document(document_loader, workflowobj, uri,
|
500 | 572 | enable_dev=args.enable_dev, strict=args.strict,
|
501 |
| - preprocess_only=args.print_pre) |
| 573 | + preprocess_only=args.print_pre or args.pack) |
| 574 | + |
| 575 | + if args.pack: |
| 576 | + stdout.write(print_pack(document_loader, processobj, uri, metadata)) |
| 577 | + return 0 |
502 | 578 |
|
503 | 579 | if args.print_pre:
|
504 | 580 | stdout.write(json.dumps(processobj, indent=4))
|
|
0 commit comments