Skip to content

Commit 01e6bda

Browse files
committed
Merge pull request #75 from common-workflow-language/draft-4-pa
Draft 4 support
2 parents baf9e75 + 6408a40 commit 01e6bda

File tree

265 files changed

+120970
-452
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

265 files changed

+120970
-452
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, False, True, self.makeTool, debug, urifrag=frag)
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: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
# pylint: disable=unused-import
2+
"""Loads a CWL document."""
3+
4+
import os
5+
import logging
6+
import re
7+
import urlparse
8+
from schema_salad.ref_resolver import Loader
9+
import schema_salad.validate as validate
10+
import schema_salad.schema as schema
11+
from avro.schema import Names
12+
from . import update
13+
from . import process
14+
from .process import Process, shortname
15+
from .errors import WorkflowException
16+
from typing import Any, Callable, cast, Dict, Tuple, Union
17+
18+
19+
def fetch_document(argsworkflow):
20+
# type: (Union[str, unicode, dict[unicode, Any]]) -> Tuple[Loader, Dict[unicode, Any], unicode]
21+
"""Retrieve a CWL document."""
22+
document_loader = Loader({"cwl": "https://w3id.org/cwl/cwl#", "id": "@id"})
23+
24+
uri = None # type: unicode
25+
workflowobj = None # type: Dict[unicode, Any]
26+
if isinstance(argsworkflow, (str, unicode)):
27+
split = urlparse.urlsplit(argsworkflow)
28+
if split.scheme:
29+
uri = argsworkflow
30+
else:
31+
uri = "file://" + os.path.abspath(argsworkflow)
32+
fileuri = urlparse.urldefrag(uri)[0]
33+
workflowobj = document_loader.fetch(fileuri)
34+
elif isinstance(argsworkflow, dict):
35+
workflowobj = argsworkflow
36+
uri = "#" + str(id(argsworkflow))
37+
else:
38+
raise validate.ValidationException(
39+
"Must be URI or object: '%s'" % argsworkflow)
40+
41+
return document_loader, workflowobj, uri
42+
43+
44+
def validate_document(document_loader, workflowobj, uri,
45+
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."""
48+
jobobj = None
49+
if "cwl:tool" in workflowobj:
50+
jobobj = workflowobj
51+
uri = urlparse.urljoin(uri, jobobj["cwl:tool"])
52+
del jobobj["cwl:tool"]
53+
workflowobj = fetch_document(uri)[1]
54+
55+
if isinstance(workflowobj, list):
56+
workflowobj = {
57+
"$graph": workflowobj
58+
}
59+
60+
fileuri = urlparse.urldefrag(uri)[0]
61+
62+
if "cwlVersion" in workflowobj:
63+
workflowobj["cwlVersion"] = re.sub(
64+
r"^(?:cwl:|https://w3id.org/cwl/cwl#)", "",
65+
workflowobj["cwlVersion"])
66+
else:
67+
workflowobj["cwlVersion"] = "draft-2"
68+
69+
if workflowobj["cwlVersion"] == "draft-2":
70+
workflowobj = update._draft2toDraft3dev1(
71+
workflowobj, document_loader, uri, update_steps=False)
72+
if "@graph" in workflowobj:
73+
workflowobj["$graph"] = workflowobj["@graph"]
74+
del workflowobj["@graph"]
75+
76+
(document_loader, avsc_names) = \
77+
process.get_schema(workflowobj["cwlVersion"])[:2]
78+
79+
if isinstance(avsc_names, Exception):
80+
raise avsc_names
81+
82+
workflowobj["id"] = fileuri
83+
processobj, metadata = document_loader.resolve_all(workflowobj, fileuri)
84+
85+
if preprocess_only:
86+
return document_loader, avsc_names, processobj, metadata, uri
87+
88+
document_loader.validate_links(processobj)
89+
schema.validate_doc(avsc_names, processobj, document_loader, strict)
90+
91+
if not metadata:
92+
metadata = {"$namespaces": processobj.get("$namespaces", {}),
93+
"$schemas": processobj.get("$schemas", []),
94+
"cwlVersion": processobj["cwlVersion"]}
95+
96+
if metadata.get("cwlVersion") != update.LATEST:
97+
processobj = update.update(
98+
processobj, document_loader, fileuri, enable_dev, metadata)
99+
100+
if jobobj:
101+
metadata["cwl:defaults"] = jobobj
102+
103+
return document_loader, avsc_names, processobj, metadata, uri
104+
105+
106+
def make_tool(document_loader, avsc_names, processobj, metadata, uri, makeTool,
107+
kwargs):
108+
# type: (Loader, Names, Dict[str, Any], Dict[str, Any], unicode, Callable[..., Process], Dict[str, Any]) -> Process
109+
"""Make a Python CWL object."""
110+
resolveduri = document_loader.resolve_ref(uri)[0]
111+
112+
if isinstance(resolveduri, list):
113+
if len(resolveduri) == 1:
114+
processobj = resolveduri[0]
115+
else:
116+
raise WorkflowException(
117+
u"Tool file contains graph of multiple objects, must specify "
118+
"one of #%s" % ", #".join(
119+
urlparse.urldefrag(i["id"])[1] for i in resolveduri
120+
if "id" in i))
121+
else:
122+
processobj = cast(Dict[str, Any], resolveduri)
123+
124+
kwargs = kwargs.copy()
125+
kwargs.update({
126+
"makeTool": makeTool,
127+
"loader": document_loader,
128+
"avsc_names": avsc_names,
129+
"metadata": metadata
130+
})
131+
tool = makeTool(processobj, **kwargs)
132+
133+
if "cwl:defaults" in metadata:
134+
jobobj = metadata["cwl:defaults"]
135+
for inp in tool.tool["inputs"]:
136+
if shortname(inp["id"]) in jobobj:
137+
inp["default"] = jobobj[shortname(inp["id"])]
138+
139+
return tool
140+
141+
142+
def load_tool(argsworkflow, makeTool, kwargs=None,
143+
enable_dev=False,
144+
strict=True):
145+
# type: (Union[str,unicode,dict[unicode,Any]], Callable[...,Process], Dict[str, Any], bool, bool) -> Any
146+
document_loader, workflowobj, uri = fetch_document(argsworkflow)
147+
document_loader, avsc_names, processobj, metadata, uri = validate_document(
148+
document_loader, workflowobj, uri, enable_dev=enable_dev,
149+
strict=strict)
150+
return make_tool(document_loader, avsc_names, processobj, metadata, uri,
151+
makeTool, kwargs if kwargs else {})

0 commit comments

Comments
 (0)