Skip to content

Commit ca085e0

Browse files
authored
Merge pull request #43 from common-workflow-language/pickValue
CWL v1.2: pickValue & when Also improves support for Union types plus many miscellaneous fixes
2 parents e2728a3 + a244aa3 commit ca085e0

9 files changed

+780
-303
lines changed

cwl_utils/cwl_v1_0_expression_refactor.py

Lines changed: 160 additions & 90 deletions
Large diffs are not rendered by default.

cwl_utils/cwl_v1_1_expression_refactor.py

Lines changed: 173 additions & 95 deletions
Large diffs are not rendered by default.

cwl_utils/cwl_v1_2_expression_refactor.py

Lines changed: 342 additions & 97 deletions
Large diffs are not rendered by default.

cwl_utils/graph_split.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,16 @@
55
Only tested with a single v1.0 workflow.
66
"""
77

8+
import argparse
9+
import json
810
import os
911
import sys
10-
import json
11-
import argparse
1212
from pathlib import Path
1313
from typing import IO, Any, Dict, List, MutableMapping, Set, Text, Union, cast
1414

15+
from cwlformat.formatter import stringify_dict
1516
from ruamel import yaml
1617
from schema_salad.sourceline import SourceLine, add_lc_filename
17-
from cwlformat.formatter import stringify_dict
1818

1919

2020
def main() -> None:

cwl_utils/parser_v1_0.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,10 @@ def expand_url(
176176
if prefix in loadingOptions.vocab:
177177
url = loadingOptions.vocab[prefix] + url[len(prefix) + 1 :]
178178

179-
split = urlsplit(url)
179+
try:
180+
split = urlsplit(url)
181+
except AttributeError as e:
182+
raise ValidationException(str(e))
180183

181184
if (
182185
(bool(split.scheme) and split.scheme in ["http", "https", "file"])

cwl_utils/parser_v1_1.py

Lines changed: 36 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -301,25 +301,53 @@ def load(self, doc, baseuri, loadingOptions, docRoot=None):
301301

302302

303303
class _SecondaryDSLLoader(_Loader):
304-
def __init__(self, items):
304+
def __init__(self, inner):
305305
# type: (_Loader) -> None
306-
self.items = items
306+
self.inner = inner
307307

308308
def load(self, doc, baseuri, loadingOptions, docRoot=None):
309309
# type: (Any, str, LoadingOptions, Optional[str]) -> Any
310+
r: List[Dict[str, Any]] = []
310311
if isinstance(doc, MutableSequence):
311-
r = [] # type: List[Any]
312312
for d in doc:
313313
if isinstance(d, str):
314-
r.append(d)
314+
if d.endswith("?"):
315+
r.append({"pattern": d[:-1], "required": False})
316+
else:
317+
r.append({"pattern": d})
318+
elif isinstance(d, dict):
319+
new_dict: Dict[str, Any] = {}
320+
if "pattern" in d:
321+
new_dict["pattern"] = d.pop("pattern")
322+
else:
323+
raise ValidationException(
324+
"Missing pattern in secondaryFiles specification entry: {}".format(
325+
d
326+
)
327+
)
328+
new_dict["required"] = (
329+
d.pop("required") if "required" in d else None
330+
)
331+
332+
if len(d):
333+
raise ValidationException(
334+
"Unallowed values in secondaryFiles specification entry: {}".format(
335+
d
336+
)
337+
)
338+
315339
else:
316-
raise ValidationException("Expected str or sequence of str")
317-
doc = r
340+
raise ValidationException(
341+
"Expected a string or sequence of (strings or mappings)."
342+
)
318343
elif isinstance(doc, str):
319-
pass
344+
if doc.endswith("?"):
345+
r.append({"pattern": doc[:-1], "required": False})
346+
else:
347+
r.append({"pattern": doc})
320348
else:
321349
raise ValidationException("Expected str or sequence of str")
322-
return doc
350+
return self.inner.load(r, baseuri, loadingOptions, docRoot)
323351

324352

325353
class _RecordLoader(_Loader):

cwl_utils/parser_v1_2.py

Lines changed: 36 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -301,25 +301,53 @@ def load(self, doc, baseuri, loadingOptions, docRoot=None):
301301

302302

303303
class _SecondaryDSLLoader(_Loader):
304-
def __init__(self, items):
304+
def __init__(self, inner):
305305
# type: (_Loader) -> None
306-
self.items = items
306+
self.inner = inner
307307

308308
def load(self, doc, baseuri, loadingOptions, docRoot=None):
309309
# type: (Any, str, LoadingOptions, Optional[str]) -> Any
310+
r: List[Dict[str, Any]] = []
310311
if isinstance(doc, MutableSequence):
311-
r = [] # type: List[Any]
312312
for d in doc:
313313
if isinstance(d, str):
314-
r.append(d)
314+
if d.endswith("?"):
315+
r.append({"pattern": d[:-1], "required": False})
316+
else:
317+
r.append({"pattern": d})
318+
elif isinstance(d, dict):
319+
new_dict: Dict[str, Any] = {}
320+
if "pattern" in d:
321+
new_dict["pattern"] = d.pop("pattern")
322+
else:
323+
raise ValidationException(
324+
"Missing pattern in secondaryFiles specification entry: {}".format(
325+
d
326+
)
327+
)
328+
new_dict["required"] = (
329+
d.pop("required") if "required" in d else None
330+
)
331+
332+
if len(d):
333+
raise ValidationException(
334+
"Unallowed values in secondaryFiles specification entry: {}".format(
335+
d
336+
)
337+
)
338+
315339
else:
316-
raise ValidationException("Expected str or sequence of str")
317-
doc = r
340+
raise ValidationException(
341+
"Expected a string or sequence of (strings or mappings)."
342+
)
318343
elif isinstance(doc, str):
319-
pass
344+
if doc.endswith("?"):
345+
r.append({"pattern": doc[:-1], "required": False})
346+
else:
347+
r.append({"pattern": doc})
320348
else:
321349
raise ValidationException("Expected str or sequence of str")
322-
return doc
350+
return self.inner.load(r, baseuri, loadingOptions, docRoot)
323351

324352

325353
class _RecordLoader(_Loader):

tests/test_docker_extract.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
from unittest import skipIf
55

66
import pytest
7+
78
import cwl_utils.parser_v1_0 as parser
89
from cwl_utils.docker_extract import traverse
910
from cwl_utils.image_puller import DockerImagePuller, SingularityImagePuller

tests/test_etools_to_clt.py

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,15 @@
11
"""Test the CWL Expression refactoring tool."""
2+
import os
3+
import shutil
4+
import tarfile
5+
from pathlib import Path
6+
from typing import Generator
7+
8+
import pytest
9+
import requests
10+
from _pytest.tmpdir import TempPathFactory
211
from cwltool.errors import WorkflowException
312
from pytest import raises
4-
from pathlib import Path
513

614
import cwl_utils.parser_v1_0 as parser
715
import cwl_utils.parser_v1_1 as parser1
@@ -136,3 +144,19 @@ def test_v1_2_workflow_top_level_sf_expr_array() -> None:
136144
False,
137145
False,
138146
)
147+
148+
149+
@pytest.fixture(scope="session")
150+
def cwl_v1_0_dir(
151+
tmp_path_factory: TempPathFactory,
152+
) -> Generator[str, None, None]:
153+
"""Download the CWL 1.0.2 specs and return a path to the directory."""
154+
tmp_path = tmp_path_factory.mktemp("cwl_v1_0_dir")
155+
with requests.get(
156+
"https://github.com/common-workflow-language/common-workflow-language/archive/v1.0.2.tar.gz",
157+
stream=True,
158+
).raw as specfileobj:
159+
tf = tarfile.open(fileobj=specfileobj)
160+
tf.extractall(path=tmp_path)
161+
yield str(tmp_path / "common-workflow-language-1.0.2")
162+
shutil.rmtree(os.path.join(tmp_path))

0 commit comments

Comments
 (0)