1
1
import os
2
2
import json
3
+ import schema_salad .ref_resolver
4
+ from subprocess32 import check_call , DEVNULL , CalledProcessError
5
+ import yaml
3
6
import glob
4
7
import requests
5
8
import urllib
6
9
import logging
7
- import schema_salad .ref_resolver
8
10
9
11
from wes_service .util import visit
12
+ from urllib import urlopen
10
13
11
14
12
- def wf_type (workflow_file ):
13
- if workflow_file .lower ().endswith ('wdl' ):
14
- return 'WDL'
15
- elif workflow_file .lower ().endswith ('cwl' ):
16
- return 'CWL'
17
- elif workflow_file .lower ().endswith ('py' ):
18
- return 'PY'
19
- else :
20
- raise ValueError ('Unrecognized/unsupported workflow file extension: %s' % workflow_file .lower ().split ('.' )[- 1 ])
15
+ def two_seven_compatible (filePath ):
16
+ """Determines if a python file is 2.7 compatible by seeing if it compiles in a subprocess"""
17
+ try :
18
+ check_call (['python2' , '-m' , 'py_compile' , filePath ], stderr = DEVNULL )
19
+ except CalledProcessError :
20
+ raise RuntimeError ('Python files must be 2.7 compatible' )
21
+ return True
21
22
22
23
23
- def wf_version ( workflow_file ):
24
- # TODO: Check inside of the file, handling local/http/etc.
25
- if wf_type ( workflow_file ) == 'PY' :
24
+ def get_version ( extension , workflow_file ):
25
+ '''Determines the version of a .py, .wdl, or .cwl file.'''
26
+ if extension == 'py' and two_seven_compatible ( workflow_file ) :
26
27
return '2.7'
27
- # elif wf_type(workflow_file) == 'CWL':
28
- # # only works locally
29
- # return yaml.load(open(workflow_file))['cwlVersion']
28
+ elif extension == 'cwl' :
29
+ return yaml .load (open (workflow_file ))['cwlVersion' ]
30
+ else : # Must be a wdl file.
31
+ # Borrowed from https://github.com/Sage-Bionetworks/synapse-orchestrator/blob/develop/synorchestrator/util.py#L142
32
+ try :
33
+ return [l .lstrip ('version' ) for l in workflow_file .splitlines () if 'version' in l .split (' ' )][0 ]
34
+ except IndexError :
35
+ return 'draft-2'
36
+
37
+
38
+ def wf_info (workflow_path ):
39
+ """
40
+ Returns the version of the file and the file extension.
41
+
42
+ Assumes that the file path is to the file directly ie, ends with a valid file extension.Supports checking local
43
+ files as well as files at http:// and https:// locations. Files at these remote locations are recreated locally to
44
+ enable our approach to version checking, then removed after version is extracted.
45
+ """
46
+
47
+ supported_formats = ['py' , 'wdl' , 'cwl' ]
48
+ file_type = workflow_path .lower ().split ('.' )[- 1 ] # Grab the file extension
49
+ workflow_path = workflow_path if ':' in workflow_path else 'file://' + workflow_path
50
+
51
+ if file_type in supported_formats :
52
+ if workflow_path .startswith ('file://' ):
53
+ version = get_version (file_type , workflow_path [7 :])
54
+ elif workflow_path .startswith ('https://' ) or workflow_path .startswith ('http://' ):
55
+ # If file not local go fetch it.
56
+ html = urlopen (workflow_path ).read ()
57
+ local_loc = os .path .join (os .getcwd (), 'fetchedFromRemote.' + file_type )
58
+ with open (local_loc , 'w' ) as f :
59
+ f .write (html )
60
+ version = wf_info ('file://' + local_loc )[0 ] # Don't take the file_type here, found it above.
61
+ os .remove (local_loc ) # TODO: Find a way to avoid recreating file before version determination.
62
+ else :
63
+ raise NotImplementedError ('Unsupported workflow file location: {}. Must be local or HTTP(S).' .format (workflow_path ))
30
64
else :
31
- # TODO: actually check the wdl file
32
- return "v1.0"
65
+ raise TypeError ( 'Unsupported workflow type: .{}. Must be {}.' . format ( file_type , '.py, .cwl, or .wdl' ))
66
+ return version , file_type . upper ()
33
67
34
68
35
69
def build_wes_request (workflow_file , json_path , attachments = None ):
@@ -42,10 +76,11 @@ def build_wes_request(workflow_file, json_path, attachments=None):
42
76
"""
43
77
workflow_file = "file://" + workflow_file if ":" not in workflow_file else workflow_file
44
78
json_path = json_path [7 :] if json_path .startswith ("file://" ) else json_path
79
+ wf_version , wf_type = wf_info (workflow_file )
45
80
46
81
parts = [("workflow_params" , json .dumps (json .load (open (json_path )))),
47
- ("workflow_type" , wf_type ( workflow_file ) ),
48
- ("workflow_type_version" , wf_version ( workflow_file ) )]
82
+ ("workflow_type" , wf_type ),
83
+ ("workflow_type_version" , wf_version )]
49
84
50
85
if workflow_file .startswith ("file://" ):
51
86
parts .append (("workflow_attachment" , (os .path .basename (workflow_file [7 :]), open (workflow_file [7 :], "rb" ))))
0 commit comments