Skip to content

Commit cfdff3b

Browse files
author
Peter Amstutz
committed
Merge branch 'master' into pack
Conflicts: cwltool/load_tool.py cwltool/main.py
2 parents 8dd0cf3 + 01e6bda commit cfdff3b

File tree

8 files changed

+244
-156
lines changed

8 files changed

+244
-156
lines changed

cwltool/cwlrdf.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from typing import Any, Union, Dict, IO
77

88
def makerdf(workflow, wf, ctx):
9-
# type: (str, Dict[str,Any], Loader.ContextType) -> Graph
9+
# type: (Union[str, unicode], Dict[str,Any], Loader.ContextType) -> Graph
1010
prefixes = {}
1111
for k,v in ctx.iteritems():
1212
if isinstance(v, dict):
@@ -31,7 +31,7 @@ def makerdf(workflow, wf, ctx):
3131
return g
3232

3333
def printrdf(workflow, wf, ctx, sr, stdout):
34-
# type: (str, Dict[str,Any], Loader.ContextType, str, IO[Any]) -> None
34+
# type: (Union[str, unicode], Dict[str, Any], Loader.ContextType, str, IO[Any]) -> None
3535
stdout.write(makerdf(workflow, wf, ctx).serialize(format=sr))
3636

3737
def lastpart(uri): # type: (Any) -> str
@@ -172,7 +172,7 @@ def dot_without_parameters(g, stdout): # type: (Graph, IO[Any]) -> None
172172

173173

174174
def printdot(workflow, wf, ctx, stdout, include_parameters=False):
175-
# type: (str, Dict[str,Any], Loader.ContextType, Any, bool) -> None
175+
# type: (Union[str, unicode], Dict[str, Any], Loader.ContextType, Any, bool) -> None
176176
g = makerdf(workflow, wf, ctx)
177177

178178
stdout.write("digraph {")

cwltool/factory.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from . import main
2+
from . import load_tool
23
from . import workflow
34
import os
45
from .process import Process
@@ -23,8 +24,9 @@ def __init__(self, makeTool=workflow.defaultMakeTool,
2324
self.executor = executor
2425
self.execkwargs = execkwargs
2526

26-
def make(self, cwl, frag=None, debug=False):
27-
l = main.load_tool(cwl, self.makeTool)
28-
if type(l) == int:
27+
def make(self, cwl):
28+
"""Instantiate a CWL object from a CWl document."""
29+
load = load_tool.load_tool(cwl, self.makeTool)
30+
if isinstance(load, int):
2931
raise Exception("Error loading tool")
30-
return Callable(l, self)
32+
return Callable(load, self)

cwltool/load_tool.py

Lines changed: 51 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,70 +1,81 @@
1+
# pylint: disable=unused-import
2+
"""Loads a CWL document."""
3+
14
import os
25
import logging
36
import re
47
import urlparse
5-
import sys
6-
import json
78
from schema_salad.ref_resolver import Loader
89
import schema_salad.validate as validate
910
import schema_salad.schema as schema
11+
from avro.schema import Names
1012
from . import update
1113
from . import process
14+
from .process import Process, shortname
1215
from .errors import WorkflowException
16+
from typing import Any, Callable, cast, Dict, Tuple, Union
1317

14-
_logger = logging.getLogger("cwltool")
1518

1619
def fetch_document(argsworkflow):
20+
# type: (Union[str, unicode, dict[unicode, Any]]) -> Tuple[Loader, Dict[unicode, Any], unicode]
21+
"""Retrieve a CWL document."""
1722
document_loader = Loader({"cwl": "https://w3id.org/cwl/cwl#", "id": "@id"})
1823

19-
jobobj = None
20-
uri = None # type: str
24+
uri = None # type: unicode
2125
workflowobj = None # type: Dict[unicode, Any]
22-
if isinstance(argsworkflow, basestring):
26+
if isinstance(argsworkflow, (str, unicode)):
2327
split = urlparse.urlsplit(argsworkflow)
2428
if split.scheme:
2529
uri = argsworkflow
2630
else:
2731
uri = "file://" + os.path.abspath(argsworkflow)
28-
fileuri, urifrag = urlparse.urldefrag(uri)
32+
fileuri = urlparse.urldefrag(uri)[0]
2933
workflowobj = document_loader.fetch(fileuri)
3034
elif isinstance(argsworkflow, dict):
3135
workflowobj = argsworkflow
3236
uri = "#" + str(id(argsworkflow))
3337
else:
34-
raise validate.ValidationException("Must be URI or object: '%s'" % argsworkflow)
38+
raise validate.ValidationException(
39+
"Must be URI or object: '%s'" % argsworkflow)
3540

3641
return document_loader, workflowobj, uri
3742

3843

3944
def validate_document(document_loader, workflowobj, uri,
4045
enable_dev=False, strict=True, preprocess_only=False):
46+
# type: (Loader, Dict[unicode, Any], unicode, bool, bool, bool) -> Tuple[Loader, Names, Any, Dict[str, str], unicode]
47+
"""Validate a CWL document."""
4148
jobobj = None
4249
if "cwl:tool" in workflowobj:
4350
jobobj = workflowobj
4451
uri = urlparse.urljoin(uri, jobobj["cwl:tool"])
4552
del jobobj["cwl:tool"]
46-
workflowobj = fetch_document(uri)
53+
workflowobj = fetch_document(uri)[1]
4754

4855
if isinstance(workflowobj, list):
4956
workflowobj = {
5057
"$graph": workflowobj
5158
}
5259

53-
fileuri, urifrag = urlparse.urldefrag(uri)
60+
fileuri = urlparse.urldefrag(uri)[0]
5461

5562
if "cwlVersion" in workflowobj:
56-
workflowobj["cwlVersion"] = re.sub(r"^(?:cwl:|https://w3id.org/cwl/cwl#)", "", workflowobj["cwlVersion"])
63+
workflowobj["cwlVersion"] = re.sub(
64+
r"^(?:cwl:|https://w3id.org/cwl/cwl#)", "",
65+
workflowobj["cwlVersion"])
5766
else:
5867
_logger.warn("No cwlVersion found, treating this file as draft-2.")
5968
workflowobj["cwlVersion"] = "draft-2"
6069

6170
if workflowobj["cwlVersion"] == "draft-2":
62-
workflowobj = update._draft2toDraft3dev1(workflowobj, document_loader, uri, updateSteps=False)
71+
workflowobj = update._draft2toDraft3dev1(
72+
workflowobj, document_loader, uri, update_steps=False)
6373
if "@graph" in workflowobj:
6474
workflowobj["$graph"] = workflowobj["@graph"]
6575
del workflowobj["@graph"]
6676

67-
(document_loader, avsc_names, schema_metadata, schema_loader) = process.get_schema(workflowobj["cwlVersion"])
77+
(document_loader, avsc_names) = \
78+
process.get_schema(workflowobj["cwlVersion"])[:2]
6879

6980
if isinstance(avsc_names, Exception):
7081
raise avsc_names
@@ -83,26 +94,33 @@ def validate_document(document_loader, workflowobj, uri,
8394
document_loader.validate_links(processobj)
8495
schema.validate_doc(avsc_names, processobj, document_loader, strict)
8596

86-
if metadata.get("cwlVersion") != update.latest:
87-
processobj = update.update(processobj, document_loader, fileuri, enable_dev, metadata)
97+
if metadata.get("cwlVersion") != update.LATEST:
98+
processobj = update.update(
99+
processobj, document_loader, fileuri, enable_dev, metadata)
88100

89101
if jobobj:
90102
metadata["cwl:defaults"] = jobobj
91103

92104
return document_loader, avsc_names, processobj, metadata, uri
93105

94106

95-
def make_tool(document_loader, avsc_names, processobj, metadata, uri, makeTool, kwargs):
96-
processobj, _ = document_loader.resolve_ref(uri)
107+
def make_tool(document_loader, avsc_names, processobj, metadata, uri, makeTool,
108+
kwargs):
109+
# type: (Loader, Names, Dict[str, Any], Dict[str, Any], unicode, Callable[..., Process], Dict[str, Any]) -> Process
110+
"""Make a Python CWL object."""
111+
resolveduri = document_loader.resolve_ref(uri)[0]
97112

98-
if isinstance(processobj, list):
99-
if 1 == len(processobj):
100-
processobj = processobj[0]
113+
if isinstance(resolveduri, list):
114+
if len(resolveduri) == 1:
115+
processobj = resolveduri[0]
101116
else:
102-
raise WorkflowException(u"Tool file contains graph of multiple objects, "
103-
"must specify one of #%s" %
104-
", #".join(urlparse.urldefrag(i["id"])[1]
105-
for i in processobj if "id" in i))
117+
raise WorkflowException(
118+
u"Tool file contains graph of multiple objects, must specify "
119+
"one of #%s" % ", #".join(
120+
urlparse.urldefrag(i["id"])[1] for i in resolveduri
121+
if "id" in i))
122+
else:
123+
processobj = cast(Dict[str, Any], resolveduri)
106124

107125
kwargs = kwargs.copy()
108126
kwargs.update({
@@ -111,25 +129,24 @@ def make_tool(document_loader, avsc_names, processobj, metadata, uri, makeTool,
111129
"avsc_names": avsc_names,
112130
"metadata": metadata
113131
})
114-
t = makeTool(processobj, **kwargs)
132+
tool = makeTool(processobj, **kwargs)
115133

116134
if "cwl:defaults" in metadata:
117135
jobobj = metadata["cwl:defaults"]
118-
for inp in t.tool["inputs"]:
136+
for inp in tool.tool["inputs"]:
119137
if shortname(inp["id"]) in jobobj:
120138
inp["default"] = jobobj[shortname(inp["id"])]
121139

122-
return t
140+
return tool
123141

124142

125143
def load_tool(argsworkflow, makeTool, kwargs=None,
126144
enable_dev=False,
127145
strict=True):
128-
146+
# type: (Union[str,unicode,dict[unicode,Any]], Callable[...,Process], Dict[str, Any], bool, bool) -> Any
129147
document_loader, workflowobj, uri = fetch_document(argsworkflow)
130-
document_loader, avsc_names, processobj, metadata, uri = validate_document(document_loader,
131-
workflowobj,
132-
uri,
133-
enable_dev=enable_dev,
134-
strict=strict)
135-
return make_tool(document_loader, avsc_names, processobj, metadata, uri, makeTool, kwargs if kwargs else {})
148+
document_loader, avsc_names, processobj, metadata, uri = validate_document(
149+
document_loader, workflowobj, uri, enable_dev=enable_dev,
150+
strict=strict)
151+
return make_tool(document_loader, avsc_names, processobj, metadata, uri,
152+
makeTool, kwargs if kwargs else {})

cwltool/main.py

Lines changed: 51 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -11,22 +11,19 @@
1111
import copy
1212
from . import workflow
1313
from .errors import WorkflowException
14+
from . import process
15+
from .cwlrdf import printrdf, printdot
16+
from .process import shortname, Process
17+
from .load_tool import fetch_document, validate_document, make_tool
1418
import schema_salad.validate as validate
1519
import tempfile
1620
import schema_salad.jsonld_context
1721
import schema_salad.makedoc
1822
import yaml
1923
import urlparse
20-
from . import process
21-
from . import job
22-
from .cwlrdf import printrdf, printdot
2324
import pkg_resources # part of setuptools
24-
from . import update
25-
from .process import shortname, Process
2625
import rdflib
27-
from load_tool import load_tool, fetch_document, validate_document, make_tool
2826
import hashlib
29-
from .utils import aslist
3027
from typing import Union, Any, cast, Callable, Dict, Tuple, IO
3128

3229
_logger = logging.getLogger("cwltool")
@@ -136,14 +133,16 @@ def arg_parser(): # type: () -> argparse.ArgumentParser
136133
parser.add_argument("--relative-deps", choices=['primary', 'cwd'], default="primary",
137134
help="When using --print-deps, print paths relative to primary file or current working directory.")
138135

139-
parser.add_argument("--enable-dev", action="store_true", help="Allow loading and running development versions of CWL spec.", default=False)
136+
parser.add_argument("--enable-dev", action="store_true",
137+
help="Allow loading and running development versions "
138+
"of CWL spec.", default=False)
140139

141140
parser.add_argument("--enable-net", action="store_true",
142-
help="Use docker's default networking for containers; the default is "
143-
"to disable networking.")
141+
help="Use docker's default networking for containers;"
142+
" the default is to disable networking.")
144143
parser.add_argument("--custom-net", type=str,
145-
help="Will be passed to `docker run` as the '--net' parameter. "
146-
"Implies '--enable-net'.")
144+
help="Will be passed to `docker run` as the '--net' "
145+
"parameter. Implies '--enable-net'.")
147146

148147
parser.add_argument("workflow", type=str, nargs="?", default=None)
149148
parser.add_argument("job_order", nargs=argparse.REMAINDER)
@@ -291,8 +290,13 @@ def generate_parser(toolparser, tool, namemap):
291290
_logger.debug(u"Can't make command line argument from %s", inptype)
292291
return None
293292

293+
if inptype != "boolean":
294+
typekw = { 'type': atype }
295+
else:
296+
typekw = {}
297+
294298
toolparser.add_argument(flag + name, required=required,
295-
help=ahelp, action=action, type=atype, default=default)
299+
help=ahelp, action=action, default=default, **typekw)
296300

297301
return toolparser
298302

@@ -538,11 +542,10 @@ def main(argsl=None,
538542
printdeps(workflowobj, document_loader, stdout, args.relative_deps)
539543
return 0
540544

541-
document_loader, avsc_names, processobj, metadata, uri = validate_document(document_loader,
542-
workflowobj, uri,
543-
enable_dev=args.enable_dev,
544-
strict=args.strict,
545-
preprocess_only=args.print_pre or args.pack)
545+
document_loader, avsc_names, processobj, metadata, uri \
546+
= validate_document(document_loader, workflowobj, uri,
547+
enable_dev=args.enable_dev, strict=args.strict,
548+
preprocess_only=args.print_pre or args.pack)
546549

547550
if args.pack:
548551
stdout.write(print_pack(document_loader, processobj, uri, metadata))
@@ -560,22 +563,26 @@ def main(argsl=None,
560563
printdot(uri, processobj, document_loader.ctx, stdout)
561564
return 0
562565

563-
t = make_tool(document_loader, avsc_names, processobj,
564-
metadata, uri, makeTool, {})
565-
except (validate.ValidationException) as e:
566-
_logger.error(u"Tool definition failed validation:\n%s", e, exc_info=(e if args.debug else False))
566+
tool = make_tool(document_loader, avsc_names, processobj, metadata,
567+
uri, makeTool, {})
568+
except (validate.ValidationException) as exc:
569+
_logger.error(u"Tool definition failed validation:\n%s", exc,
570+
exc_info=(exc if args.debug else False))
567571
return 1
568-
except (RuntimeError, WorkflowException) as e:
569-
_logger.error(u"Tool definition failed initialization:\n%s", e, exc_info=(e if args.debug else False))
572+
except (RuntimeError, WorkflowException) as exc:
573+
_logger.error(u"Tool definition failed initialization:\n%s", exc,
574+
exc_info=(exc if args.debug else False))
570575
return 1
571-
except Exception as e:
572-
_logger.error(u"I'm sorry, I couldn't load this CWL file%s",
573-
", try again with --debug for more information.\nThe error was: %s" % e if not args.debug else ". The error was:",
574-
exc_info=(e if args.debug else False))
576+
except Exception as exc:
577+
_logger.error(
578+
u"I'm sorry, I couldn't load this CWL file%s",
579+
", try again with --debug for more information.\nThe error was: "
580+
"%s" % exc if not args.debug else ". The error was:",
581+
exc_info=(exc if args.debug else False))
575582
return 1
576583

577-
if isinstance(t, int):
578-
return t
584+
if isinstance(tool, int):
585+
return tool
579586

580587
if args.tmp_outdir_prefix != 'tmp':
581588
# Use user defined temp directory (if it exists)
@@ -591,7 +598,7 @@ def main(argsl=None,
591598
_logger.error("Temporary directory prefix doesn't exist.")
592599
return 1
593600

594-
job_order_object = load_job_order(args, t, parser, stdin,
601+
job_order_object = load_job_order(args, tool, parser, stdin,
595602
print_input_deps=args.print_input_deps,
596603
relative_deps=args.relative_deps,
597604
stdout=stdout)
@@ -604,7 +611,7 @@ def main(argsl=None,
604611
args.move_outputs = False
605612

606613
try:
607-
out = executor(t, job_order_object[0],
614+
out = executor(tool, job_order_object[0],
608615
job_order_object[1], args,
609616
conformance_test=args.conformance_test,
610617
dry_run=args.dry_run,
@@ -633,14 +640,20 @@ def main(argsl=None,
633640
stdout.flush()
634641
else:
635642
return 1
636-
except (validate.ValidationException) as e:
637-
_logger.error(u"Input object failed validation:\n%s", e, exc_info=(e if args.debug else False))
643+
except (validate.ValidationException) as exc:
644+
_logger.error(
645+
u"Input object failed validation:\n%s", exc,
646+
exc_info=(exc if args.debug else False))
638647
return 1
639-
except WorkflowException as e:
640-
_logger.error(u"Workflow error, try again with --debug for more information:\n %s", e, exc_info=(e if args.debug else False))
648+
except WorkflowException as exc:
649+
_logger.error(
650+
u"Workflow error, try again with --debug for more "
651+
"information:\n %s", exc, exc_info=(exc if args.debug else False))
641652
return 1
642-
except Exception as e:
643-
_logger.error(u"Unhandled error, try again with --debug for more information:\n %s", e, exc_info=(e if args.debug else False))
653+
except Exception as exc:
654+
_logger.error(
655+
u"Unhandled error, try again with --debug for more information:\n"
656+
" %s", exc, exc_info=(exc if args.debug else False))
644657
return 1
645658

646659
return 0

0 commit comments

Comments
 (0)