1
1
import copy
2
2
import logging
3
3
import math
4
- import os
5
4
from typing import (
6
5
IO ,
7
6
Any ,
14
13
Set ,
15
14
Tuple ,
16
15
Union ,
16
+ cast ,
17
17
)
18
18
19
19
from rdflib import Graph , URIRef
20
20
from rdflib .namespace import OWL , RDFS
21
21
from ruamel .yaml .comments import CommentedMap
22
- from schema_salad import validate
23
- from schema_salad .avro .schema import Schema , make_avsc_object
24
- from schema_salad .schema import Names , convert_to_dict
22
+ from schema_salad .avro .schema import Names , Schema , make_avsc_object
23
+ from schema_salad .exceptions import ValidationException
25
24
from schema_salad .sourceline import SourceLine
26
- from schema_salad .utils import json_dumps
25
+ from schema_salad .utils import convert_to_dict , json_dumps
26
+ from schema_salad .validate import validate
27
27
from typing_extensions import TYPE_CHECKING , Type # pylint: disable=unused-import
28
28
29
29
from . import expression
30
30
from .errors import WorkflowException
31
31
from .loghandler import _logger
32
32
from .mutation import MutationManager
33
- from .pathmapper import CONTENT_LIMIT , get_listing , normalizeFilesDirs , visit_class
34
33
from .stdfsaccess import StdFsAccess
35
- from .utils import aslist , docker_windows_path_adjust , onWindows
36
-
37
- # move to a regular typing import when Python 3.3-3.6 is no longer supported
38
-
34
+ from .utils import (
35
+ CONTENT_LIMIT ,
36
+ CWLObjectType ,
37
+ CWLOutputType ,
38
+ aslist ,
39
+ docker_windows_path_adjust ,
40
+ get_listing ,
41
+ normalizeFilesDirs ,
42
+ onWindows ,
43
+ visit_class ,
44
+ )
39
45
40
46
if TYPE_CHECKING :
41
47
from .provenance import ProvenanceProfile # pylint: disable=unused-import
@@ -111,28 +117,28 @@ def check_format(
111
117
if not afile :
112
118
continue
113
119
if "format" not in afile :
114
- raise validate . ValidationException (
120
+ raise ValidationException (
115
121
"File has no 'format' defined: {}" .format (json_dumps (afile , indent = 4 ))
116
122
)
117
123
for inpf in aslist (input_formats ):
118
124
if afile ["format" ] == inpf or formatSubclassOf (
119
125
afile ["format" ], inpf , ontology , set ()
120
126
):
121
127
return
122
- raise validate . ValidationException (
128
+ raise ValidationException (
123
129
"File has an incompatible format: {}" .format (json_dumps (afile , indent = 4 ))
124
130
)
125
131
126
132
127
133
class HasReqsHints (object ):
128
- def __init__ (self ): # type: () -> None
134
+ def __init__ (self ) -> None :
129
135
"""Initialize this reqs decorator."""
130
- self .requirements = [] # type: List[Dict[str, Any] ]
131
- self .hints = [] # type: List[Dict[str, Any] ]
136
+ self .requirements = [] # type: List[CWLObjectType ]
137
+ self .hints = [] # type: List[CWLObjectType ]
132
138
133
139
def get_requirement (
134
- self , feature # type : str
135
- ): # type: (...) -> Tuple[Optional[Any ], Optional[bool]]
140
+ self , feature : str
141
+ ) -> Tuple [Optional [CWLObjectType ], Optional [bool ]]:
136
142
for item in reversed (self .requirements ):
137
143
if item ["class" ] == feature :
138
144
return (item , True )
@@ -145,28 +151,28 @@ def get_requirement(
145
151
class Builder (HasReqsHints ):
146
152
def __init__ (
147
153
self ,
148
- job , # type: Dict[str, expression.JSON]
149
- files , # type : List[Dict[str, str]]
150
- bindings , # type : List[Dict[str, Any]]
151
- schemaDefs , # type : Dict[str, Dict[str, Any]]
152
- names , # type : Names
153
- requirements , # type : List[Dict[str, Any]]
154
- hints , # type : List[Dict[str, Any]]
155
- resources , # type : Dict[str, int]
154
+ job : CWLObjectType ,
155
+ files : List [CWLObjectType ],
156
+ bindings : List [CWLObjectType ],
157
+ schemaDefs : Dict [str , CWLObjectType ],
158
+ names : Names ,
159
+ requirements : List [CWLObjectType ],
160
+ hints : List [CWLObjectType ],
161
+ resources : Dict [str , int ],
156
162
mutation_manager : Optional [MutationManager ],
157
- formatgraph , # type : Optional[Graph]
163
+ formatgraph : Optional [Graph ],
158
164
make_fs_access : Type [StdFsAccess ],
159
- fs_access , # type : StdFsAccess
160
- job_script_provider , # type : Optional[Any]
161
- timeout , # type : float
162
- debug , # type : bool
163
- js_console , # type : bool
164
- force_docker_pull , # type : bool
165
- loadListing , # type : str
166
- outdir , # type : str
167
- tmpdir , # type : str
168
- stagedir , # type : str
169
- ): # type: (...) -> None
165
+ fs_access : StdFsAccess ,
166
+ job_script_provider : Optional [Any ],
167
+ timeout : float ,
168
+ debug : bool ,
169
+ js_console : bool ,
170
+ force_docker_pull : bool ,
171
+ loadListing : str ,
172
+ outdir : str ,
173
+ tmpdir : str ,
174
+ stagedir : str ,
175
+ ) -> None :
170
176
"""Initialize this Builder."""
171
177
self .job = job
172
178
self .files = files
@@ -201,10 +207,10 @@ def __init__(
201
207
self .prov_obj = None # type: Optional[ProvenanceProfile]
202
208
self .find_default_container = None # type: Optional[Callable[[], str]]
203
209
204
- def build_job_script (self , commands : List [str ]) -> str :
210
+ def build_job_script (self , commands : List [str ]) -> Optional [ str ] :
205
211
build_job_script_method = getattr (
206
212
self .job_script_provider , "build_job_script" , None
207
- ) # type: Callable[[Builder, Union[List[str],List[str]]], str]
213
+ ) # type: Optional[ Callable[[Builder, Union[List[str],List[str]]], str] ]
208
214
if build_job_script_method is not None :
209
215
return build_job_script_method (self , commands )
210
216
return None
@@ -215,16 +221,18 @@ def bind_input(
215
221
datum : Any ,
216
222
discover_secondaryFiles : bool ,
217
223
lead_pos : Optional [Union [int , List [int ]]] = None ,
218
- tail_pos : Optional [List [int ]] = None ,
224
+ tail_pos : Optional [Union [ str , List [int ] ]] = None ,
219
225
) -> List [MutableMapping [str , Any ]]:
220
226
221
227
if tail_pos is None :
222
228
tail_pos = []
223
229
if lead_pos is None :
224
230
lead_pos = []
225
231
226
- bindings = [] # type: List[MutableMapping[str, str]]
227
- binding = {} # type: Union[MutableMapping[str, str], CommentedMap]
232
+ bindings = [] # type: List[MutableMapping[str, Union[str, List[int]]]]
233
+ binding = (
234
+ {}
235
+ ) # type: Union[MutableMapping[str, Union[str, List[int]]], CommentedMap]
228
236
value_from_expression = False
229
237
if "inputBinding" in schema and isinstance (
230
238
schema ["inputBinding" ], MutableMapping
@@ -264,7 +272,7 @@ def bind_input(
264
272
avsc = self .names .get_name (t ["name" ], None )
265
273
if not avsc :
266
274
avsc = make_avsc_object (convert_to_dict (t ), self .names )
267
- if validate . validate (avsc , datum ):
275
+ if validate (avsc , datum ):
268
276
schema = copy .deepcopy (schema )
269
277
schema ["type" ] = t
270
278
if not value_from_expression :
@@ -285,7 +293,7 @@ def bind_input(
285
293
)
286
294
bound_input = True
287
295
if not bound_input :
288
- raise validate . ValidationException (
296
+ raise ValidationException (
289
297
"'%s' is not a valid union %s" % (datum , schema ["type" ])
290
298
)
291
299
elif isinstance (schema ["type" ], MutableMapping ):
@@ -359,7 +367,7 @@ def bind_input(
359
367
)
360
368
binding = {}
361
369
362
- def _capture_files (f ): # type: (Dict[str, str] ) -> Dict[str, str]
370
+ def _capture_files (f ): # type: (CWLObjectType ) -> CWLObjectType
363
371
self .files .append (f )
364
372
return f
365
373
@@ -453,7 +461,7 @@ def addsf(
453
461
check_format (
454
462
datum , self .do_eval (schema ["format" ]), self .formatgraph
455
463
)
456
- except validate . ValidationException as ve :
464
+ except ValidationException as ve :
457
465
raise WorkflowException (
458
466
"Expected value of '%s' to have format %s but\n "
459
467
" %s" % (schema ["name" ], schema ["format" ], ve )
@@ -477,7 +485,9 @@ def addsf(
477
485
# Position to front of the sort key
478
486
if binding :
479
487
for bi in bindings :
480
- bi ["position" ] = binding ["position" ] + bi ["position" ]
488
+ bi ["position" ] = cast (List [int ], binding ["position" ]) + cast (
489
+ List [int ], bi ["position" ]
490
+ )
481
491
bindings .append (binding )
482
492
483
493
return bindings
@@ -503,7 +513,7 @@ def tostr(self, value: Union[MutableMapping[str, str], Any]) -> str:
503
513
else :
504
514
return str (value )
505
515
506
- def generate_arg (self , binding ): # type: (Dict[str, Any] ) -> List[str]
516
+ def generate_arg (self , binding : CWLObjectType ) -> List [str ]:
507
517
value = binding .get ("datum" )
508
518
if "valueFrom" in binding :
509
519
with SourceLine (
@@ -512,9 +522,9 @@ def generate_arg(self, binding): # type: (Dict[str, Any]) -> List[str]
512
522
WorkflowException ,
513
523
_logger .isEnabledFor (logging .DEBUG ),
514
524
):
515
- value = self .do_eval (binding ["valueFrom" ], context = value )
525
+ value = self .do_eval (cast ( str , binding ["valueFrom" ]) , context = value )
516
526
517
- prefix = binding .get ("prefix" ) # type: Optional[str]
527
+ prefix = cast ( Optional [ str ], binding .get ("prefix" ))
518
528
sep = binding .get ("separate" , True )
519
529
if prefix is None and not sep :
520
530
with SourceLine (
@@ -527,13 +537,16 @@ def generate_arg(self, binding): # type: (Dict[str, Any]) -> List[str]
527
537
"'separate' option can not be specified without prefix"
528
538
)
529
539
530
- argl = [] # type: MutableSequence[MutableMapping[str, str] ]
540
+ argl = [] # type: MutableSequence[CWLOutputType ]
531
541
if isinstance (value , MutableSequence ):
532
542
if binding .get ("itemSeparator" ) and value :
533
- argl = [binding ["itemSeparator" ].join ([self .tostr (v ) for v in value ])]
543
+ itemSeparator = cast (str , binding ["itemSeparator" ])
544
+ argl = [itemSeparator .join ([self .tostr (v ) for v in value ])]
534
545
elif binding .get ("valueFrom" ):
535
546
value = [self .tostr (v ) for v in value ]
536
- return ([prefix ] if prefix else []) + value
547
+ return cast (List [str ], ([prefix ] if prefix else [])) + cast (
548
+ List [str ], value
549
+ )
537
550
elif prefix and value :
538
551
return [prefix ]
539
552
else :
@@ -542,7 +555,7 @@ def generate_arg(self, binding): # type: (Dict[str, Any]) -> List[str]
542
555
"File" ,
543
556
"Directory" ,
544
557
):
545
- argl = [ value ]
558
+ argl = cast ( MutableSequence [ CWLOutputType ], [ value ])
546
559
elif isinstance (value , MutableMapping ):
547
560
return [prefix ] if prefix else []
548
561
elif value is True and prefix :
@@ -561,8 +574,15 @@ def generate_arg(self, binding): # type: (Dict[str, Any]) -> List[str]
561
574
562
575
return [a for a in args if a is not None ]
563
576
564
- def do_eval (self , ex , context = None , recursive = False , strip_whitespace = True ):
565
- # type: (Union[Dict[str, str], str], Any, bool, bool) -> Any
577
+ def do_eval (
578
+ self ,
579
+ ex : Union [
580
+ str , float , bool , None , MutableMapping [str , str ], MutableSequence [str ]
581
+ ],
582
+ context : Optional [Any ] = None ,
583
+ recursive : bool = False ,
584
+ strip_whitespace : bool = True ,
585
+ ) -> Any :
566
586
if recursive :
567
587
if isinstance (ex , MutableMapping ):
568
588
return {k : self .do_eval (v , context , recursive ) for k , v in ex .items ()}
0 commit comments