Skip to content

Commit b7da32f

Browse files
authored
Merge branch 'master' into random_output_dir
2 parents 6816508 + a972860 commit b7da32f

Some content is hidden

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

82 files changed

+3590
-1870
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ eggs/
99
*.egg-info/
1010
*.egg
1111
.tox/
12+
.pytest_cache
1213

1314
# Editor Temps
1415
.*.sw?
@@ -44,4 +45,5 @@ output.txt
4445
pydocstyle_report.txt
4546
response.txt
4647
test.txt
48+
time.txt
4749
value

Makefile

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,12 @@ install-deb-dep:
5959

6060
## install : install the ${MODULE} module and schema-salad-tool
6161
install: FORCE
62-
pip install .
62+
pip install .[deps]
63+
64+
## dev : install the ${MODULE} module in dev mode
65+
dev: install-dep
66+
pip install -e .[deps]
67+
6368

6469
## dist : create a module package for distribution
6570
dist: dist/${MODULE}-$(VERSION).tar.gz

appveyor.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ build_script:
4141
test_script:
4242
- |
4343
%PYTHON%\\python.exe setup.py test --addopts "--cov-report xml --cov cwltool -p no:cacheprovider --junit-xml=tests.xml"
44-
- "%PYTHON%\\python.exe -m codecov"
44+
- "%PYTHON%\\python.exe -m codecov --file coverage.xml"
4545

4646
on_finish:
4747
- ps: |

cwltool/__main__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
"""Default entrypoint for the cwltool module."""
12
from __future__ import absolute_import
23

34
from . import main

cwltool/argparser.py

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
1+
"""Command line argument parsing for cwltool."""
12
from __future__ import absolute_import, print_function
23

34
import argparse
45
import os
5-
from typing import Any, AnyStr, Dict, List, Optional, Sequence, Union, cast
6+
from typing import (Any, AnyStr, Dict, List, MutableMapping, MutableSequence,
7+
Optional, Sequence, Union, cast)
68

9+
from schema_salad.ref_resolver import file_uri
710
from typing_extensions import Text # pylint: disable=unused-import
811
# move to a regular typing import when Python 3.3-3.6 is no longer supported
912

10-
from schema_salad.ref_resolver import file_uri
11-
1213
from .loghandler import _logger
1314
from .process import Process, shortname # pylint: disable=unused-import
1415
from .resolver import ga4gh_tool_registries
@@ -381,7 +382,7 @@ def add_argument(toolparser, name, inptype, records, description="",
381382
flag = "--"
382383

383384
required = True
384-
if isinstance(inptype, list):
385+
if isinstance(inptype, MutableSequence):
385386
if inptype[0] == "null":
386387
required = False
387388
if len(inptype) == 2:
@@ -398,16 +399,16 @@ def add_argument(toolparser, name, inptype, records, description="",
398399
action = cast(argparse.Action, FileAction)
399400
elif inptype == "Directory":
400401
action = cast(argparse.Action, DirectoryAction)
401-
elif isinstance(inptype, dict) and inptype["type"] == "array":
402+
elif isinstance(inptype, MutableMapping) and inptype["type"] == "array":
402403
if inptype["items"] == "File":
403404
action = cast(argparse.Action, FileAppendAction)
404405
elif inptype["items"] == "Directory":
405406
action = cast(argparse.Action, DirectoryAppendAction)
406407
else:
407408
action = "append"
408-
elif isinstance(inptype, dict) and inptype["type"] == "enum":
409+
elif isinstance(inptype, MutableMapping) and inptype["type"] == "enum":
409410
atype = Text
410-
elif isinstance(inptype, dict) and inptype["type"] == "record":
411+
elif isinstance(inptype, MutableMapping) and inptype["type"] == "record":
411412
records.append(name)
412413
for field in inptype['fields']:
413414
fieldname = name + "." + shortname(field['name'])

cwltool/builder.py

Lines changed: 34 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -2,27 +2,31 @@
22

33
import copy
44
import logging
5-
from typing import Any, Callable, Dict, List, Optional, Set, Union, Tuple
6-
from typing_extensions import Text, Type, TYPE_CHECKING # pylint: disable=unused-import
7-
# move to a regular typing import when Python 3.3-3.6 is no longer supported
5+
from typing import (Any, Callable, Dict, List, MutableMapping, MutableSequence,
6+
Optional, Set, Tuple, Union)
87

98
from rdflib import Graph, URIRef # pylint: disable=unused-import
109
from rdflib.namespace import OWL, RDFS
11-
import schema_salad.schema # pylint: disable=unused-import
10+
from ruamel.yaml.comments import CommentedMap
1211
from schema_salad import validate
13-
from schema_salad.schema import AvroSchemaFromJSONData
12+
from schema_salad.schema import AvroSchemaFromJSONData, Names
1413
from schema_salad.sourceline import SourceLine
1514
from six import iteritems, string_types
15+
from typing_extensions import (TYPE_CHECKING, # pylint: disable=unused-import
16+
Text, Type)
17+
# move to a regular typing import when Python 3.3-3.6 is no longer supported
1618

1719
from . import expression
1820
from .errors import WorkflowException
1921
from .loghandler import _logger
2022
from .mutation import MutationManager # pylint: disable=unused-import
21-
from .pathmapper import (PathMapper, # pylint: disable=unused-import
22-
get_listing, normalizeFilesDirs, visit_class)
23+
from .pathmapper import PathMapper # pylint: disable=unused-import
24+
from .pathmapper import get_listing, normalizeFilesDirs, visit_class
2325
from .stdfsaccess import StdFsAccess # pylint: disable=unused-import
24-
from .utils import (aslist, docker_windows_path_adjust,
25-
json_dumps, onWindows)
26+
from .utils import aslist, docker_windows_path_adjust, json_dumps, onWindows
27+
28+
29+
2630
if TYPE_CHECKING:
2731
from .provenance import CreateProvProfile # pylint: disable=unused-import
2832
CONTENT_LIMIT = 64 * 1024
@@ -109,7 +113,7 @@ def __init__(self,
109113
files=None, # type: List[Dict[Text, Text]]
110114
bindings=None, # type: List[Dict[Text, Any]]
111115
schemaDefs=None, # type: Dict[Text, Dict[Text, Any]]
112-
names=None, # type: schema_salad.schema.Names
116+
names=None, # type: Names
113117
requirements=None, # type: List[Dict[Text, Any]]
114118
hints=None, # type: List[Dict[Text, Any]]
115119
timeout=None, # type: float
@@ -129,7 +133,7 @@ def __init__(self,
129133
): # type: (...) -> None
130134

131135
if names is None:
132-
self.names = schema_salad.schema.Names()
136+
self.names = Names()
133137
else:
134138
self.names = names
135139

@@ -194,22 +198,23 @@ def build_job_script(self, commands):
194198
return None
195199

196200
def bind_input(self,
197-
schema, # type: Dict[Text, Any]
201+
schema, # type: MutableMapping[Text, Any]
198202
datum, # type: Any
199203
discover_secondaryFiles, # type: bool
200204
lead_pos=None, # type: Optional[Union[int, List[int]]]
201205
tail_pos=None, # type: Optional[List[int]]
202-
): # type: (...) -> List[Dict[Text, Any]]
206+
): # type: (...) -> List[MutableMapping[Text, Any]]
203207

204208
if tail_pos is None:
205209
tail_pos = []
206210
if lead_pos is None:
207211
lead_pos = []
208-
bindings = [] # type: List[Dict[Text,Text]]
209-
binding = None # type: Optional[Dict[Text,Any]]
212+
bindings = [] # type: List[MutableMapping[Text, Text]]
213+
binding = None # type: Optional[MutableMapping[Text,Any]]
210214
value_from_expression = False
211-
if "inputBinding" in schema and isinstance(schema["inputBinding"], dict):
212-
binding = copy.copy(schema["inputBinding"])
215+
if "inputBinding" in schema and isinstance(schema["inputBinding"], MutableMapping):
216+
binding = CommentedMap(schema["inputBinding"].items())
217+
assert binding is not None
213218

214219
if "position" in binding:
215220
binding["position"] = aslist(lead_pos) + aslist(binding["position"]) + aslist(tail_pos)
@@ -221,12 +226,12 @@ def bind_input(self,
221226
value_from_expression = True
222227

223228
# Handle union types
224-
if isinstance(schema["type"], list):
229+
if isinstance(schema["type"], MutableSequence):
225230
bound_input = False
226231
for t in schema["type"]:
227232
if isinstance(t, string_types) and self.names.has_name(t, ""):
228233
avsc = self.names.get_name(t, "")
229-
elif isinstance(t, dict) and "name" in t and self.names.has_name(t["name"], ""):
234+
elif isinstance(t, MutableMapping) and "name" in t and self.names.has_name(t["name"], ""):
230235
avsc = self.names.get_name(t["name"], "")
231236
else:
232237
avsc = AvroSchemaFromJSONData(t, self.names)
@@ -240,7 +245,7 @@ def bind_input(self,
240245
bound_input = True
241246
if not bound_input:
242247
raise validate.ValidationException(u"'%s' is not a valid union %s" % (datum, schema["type"]))
243-
elif isinstance(schema["type"], dict):
248+
elif isinstance(schema["type"], MutableMapping):
244249
st = copy.deepcopy(schema["type"])
245250
if binding and "inputBinding" not in st and st["type"] == "array" and "itemSeparator" not in binding:
246251
st["inputBinding"] = {}
@@ -289,7 +294,7 @@ def bind_input(self,
289294
if "secondaryFiles" not in datum:
290295
datum["secondaryFiles"] = []
291296
for sf in aslist(schema["secondaryFiles"]):
292-
if isinstance(sf, dict) or "$(" in sf or "${" in sf:
297+
if isinstance(sf, MutableMapping) or "$(" in sf or "${" in sf:
293298
sfpath = self.do_eval(sf, context=datum)
294299
else:
295300
sfpath = substitute(datum["basename"], sf)
@@ -301,7 +306,7 @@ def bind_input(self,
301306
if d["basename"] == sfname:
302307
found = True
303308
if not found:
304-
if isinstance(sfname, dict):
309+
if isinstance(sfname, MutableMapping):
305310
datum["secondaryFiles"].append(sfname)
306311
elif discover_secondaryFiles:
307312
datum["secondaryFiles"].append({
@@ -344,7 +349,7 @@ def _capture_files(f):
344349
return bindings
345350

346351
def tostr(self, value): # type: (Any) -> Text
347-
if isinstance(value, dict) and value.get("class") in ("File", "Directory"):
352+
if isinstance(value, MutableMapping) and value.get("class") in ("File", "Directory"):
348353
if "path" not in value:
349354
raise WorkflowException(u"%s object missing \"path\": %s" % (value["class"], value))
350355

@@ -372,8 +377,8 @@ def generate_arg(self, binding): # type: (Dict[Text, Any]) -> List[Text]
372377
with SourceLine(binding, "separate", WorkflowException, _logger.isEnabledFor(logging.DEBUG)):
373378
raise WorkflowException("'separate' option can not be specified without prefix")
374379

375-
argl = [] # type: List[Dict[Text,Text]]
376-
if isinstance(value, list):
380+
argl = [] # type: MutableSequence[MutableMapping[Text, Text]]
381+
if isinstance(value, MutableSequence):
377382
if binding.get("itemSeparator") and value:
378383
argl = [binding["itemSeparator"].join([self.tostr(v) for v in value])]
379384
elif binding.get("valueFrom"):
@@ -383,9 +388,9 @@ def generate_arg(self, binding): # type: (Dict[Text, Any]) -> List[Text]
383388
return [prefix]
384389
else:
385390
return []
386-
elif isinstance(value, dict) and value.get("class") in ("File", "Directory"):
391+
elif isinstance(value, MutableMapping) and value.get("class") in ("File", "Directory"):
387392
argl = [value]
388-
elif isinstance(value, dict):
393+
elif isinstance(value, MutableMapping):
389394
return [prefix] if prefix else []
390395
elif value is True and prefix:
391396
return [prefix]
@@ -407,10 +412,10 @@ def generate_arg(self, binding): # type: (Dict[Text, Any]) -> List[Text]
407412
def do_eval(self, ex, context=None, recursive=False, strip_whitespace=True):
408413
# type: (Union[Dict[Text, Text], Text], Any, bool, bool) -> Any
409414
if recursive:
410-
if isinstance(ex, dict):
415+
if isinstance(ex, MutableMapping):
411416
return {k: self.do_eval(v, context, recursive)
412417
for k, v in iteritems(ex)}
413-
if isinstance(ex, list):
418+
if isinstance(ex, MutableSequence):
414419
return [self.do_eval(v, context, recursive)
415420
for v in ex]
416421

cwltool/checker.py

Lines changed: 23 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
1+
"""Static checking of CWL workflow connectivity."""
12
from collections import namedtuple
2-
from typing import Any, Dict, List, Optional
3-
from typing_extensions import Text # pylint: disable=unused-import
4-
# move to a regular typing import when Python 3.3-3.6 is no longer supported
3+
from typing import Any, Dict, List, MutableMapping, MutableSequence, Optional
54

5+
import six
66
from schema_salad import validate
77
from schema_salad.sourceline import SourceLine, bullets, strip_dup_lineno
8-
import six
8+
from typing_extensions import Text # pylint: disable=unused-import
9+
# move to a regular typing import when Python 3.3-3.6 is no longer supported
910

1011
from .errors import WorkflowException
1112
from .loghandler import _logger
@@ -15,7 +16,7 @@
1516

1617
def _get_type(tp):
1718
# type: (Any) -> Any
18-
if isinstance(tp, dict):
19+
if isinstance(tp, MutableMapping):
1920
if tp.get("type") not in ("array", "record", "enum"):
2021
return tp["type"]
2122
return tp
@@ -46,9 +47,9 @@ def merge_flatten_type(src):
4647
"""Return the merge flattened type of the source type
4748
"""
4849

49-
if isinstance(src, list):
50+
if isinstance(src, MutableSequence):
5051
return [merge_flatten_type(t) for t in src]
51-
if isinstance(src, dict) and src.get("type") == "array":
52+
if isinstance(src, MutableMapping) and src.get("type") == "array":
5253
return src
5354
return {"items": src, "type": "array"}
5455

@@ -65,7 +66,7 @@ def can_assign_src_to_sink(src, sink, strict=False): # type: (Any, Any, bool) -
6566

6667
if src == "Any" or sink == "Any":
6768
return True
68-
if isinstance(src, dict) and isinstance(sink, dict):
69+
if isinstance(src, MutableMapping) and isinstance(sink, MutableMapping):
6970
if sink.get("not_connected") and strict:
7071
return False
7172
if src["type"] == "array" and sink["type"] == "array":
@@ -79,35 +80,33 @@ def can_assign_src_to_sink(src, sink, strict=False): # type: (Any, Any, bool) -
7980
return False
8081
return True
8182
return can_assign_src_to_sink(src["type"], sink["type"], strict)
82-
elif isinstance(src, list):
83+
if isinstance(src, MutableSequence):
8384
if strict:
84-
for t in src:
85-
if not can_assign_src_to_sink(t, sink):
85+
for this_src in src:
86+
if not can_assign_src_to_sink(this_src, sink):
8687
return False
8788
return True
88-
else:
89-
for t in src:
90-
if can_assign_src_to_sink(t, sink):
91-
return True
92-
return False
93-
elif isinstance(sink, list):
94-
for t in sink:
95-
if can_assign_src_to_sink(src, t):
89+
for this_src in src:
90+
if can_assign_src_to_sink(this_src, sink):
91+
return True
92+
return False
93+
if isinstance(sink, MutableSequence):
94+
for this_sink in sink:
95+
if can_assign_src_to_sink(src, this_sink):
9696
return True
9797
return False
98-
else:
99-
return src == sink
98+
return src == sink
10099

101100

102101
def _compare_records(src, sink, strict=False):
103-
# type: (Dict[Text, Any], Dict[Text, Any], bool) -> bool
102+
# type: (MutableMapping[Text, Any], MutableMapping[Text, Any], bool) -> bool
104103
"""Compare two records, ensuring they have compatible fields.
105104
106105
This handles normalizing record names, which will be relative to workflow
107106
step, so that they can be compared.
108107
"""
109108

110-
def _rec_fields(rec): # type: (Dict[Text, Any]) -> Dict[Text, Any]
109+
def _rec_fields(rec): # type: (MutableMapping[Text, Any]) -> MutableMapping[Text, Any]
111110
out = {}
112111
for field in rec["fields"]:
113112
name = shortname(field["name"])
@@ -227,7 +226,7 @@ def check_all_types(src_dict, sinks, sourceField):
227226
for sink in sinks:
228227
if sourceField in sink:
229228
valueFrom = sink.get("valueFrom")
230-
if isinstance(sink[sourceField], list):
229+
if isinstance(sink[sourceField], MutableSequence):
231230
srcs_of_sink = [src_dict[parm_id] for parm_id in sink[sourceField]]
232231
linkMerge = sink.get("linkMerge", ("merge_nested"
233232
if len(sink[sourceField]) > 1 else None))

0 commit comments

Comments
 (0)