Mercurial > repos > fubar > tool_factory_2
comparison toolfactory/rgToolFactory2.py @ 126:def0f754ee1b draft
Uploaded
author | fubar |
---|---|
date | Fri, 26 Mar 2021 09:29:58 +0000 |
parents | f267ed4a3026 |
children | 98c8a76b3638 |
comparison
equal
deleted
inserted
replaced
125:2dbb412af425 | 126:def0f754ee1b |
---|---|
14 # 2. Fix planemo so the toolfactory function works | 14 # 2. Fix planemo so the toolfactory function works |
15 # 3. Rewrite bits using galaxyxml functions where that makes sense - done | 15 # 3. Rewrite bits using galaxyxml functions where that makes sense - done |
16 | 16 |
17 import argparse | 17 import argparse |
18 import copy | 18 import copy |
19 import json | |
19 import logging | 20 import logging |
20 import os | 21 import os |
21 import re | 22 import re |
22 import shutil | 23 import shutil |
23 import subprocess | 24 import subprocess |
34 | 35 |
35 import lxml | 36 import lxml |
36 | 37 |
37 import yaml | 38 import yaml |
38 | 39 |
39 myversion = "V2.1 July 2020" | 40 |
41 myversion = "V2.2 February 2021" | |
40 verbose = True | 42 verbose = True |
41 debug = True | 43 debug = True |
42 toolFactoryURL = "https://github.com/fubar2/toolfactory" | 44 toolFactoryURL = "https://github.com/fubar2/toolfactory" |
43 ourdelim = "~~~" | |
44 | |
45 # --input_files="$intab.input_files~~~$intab.input_CL~~~ | |
46 # $intab.input_formats# ~~~$intab.input_label | |
47 # ~~~$intab.input_help" | |
48 IPATHPOS = 0 | |
49 ICLPOS = 1 | |
50 IFMTPOS = 2 | |
51 ILABPOS = 3 | |
52 IHELPOS = 4 | |
53 IOCLPOS = 5 | |
54 | |
55 # --output_files "$otab.history_name~~~$otab.history_format~~~ | |
56 # $otab.history_CL~~~$otab.history_test" | |
57 ONAMEPOS = 0 | |
58 OFMTPOS = 1 | |
59 OCLPOS = 2 | |
60 OTESTPOS = 3 | |
61 OOCLPOS = 4 | |
62 | |
63 | |
64 # --additional_parameters="$i.param_name~~~$i.param_value~~~ | |
65 # $i.param_label~~~$i.param_help~~~$i.param_type | |
66 # ~~~$i.CL~~~i$.param_CLoverride" | |
67 ANAMEPOS = 0 | |
68 AVALPOS = 1 | |
69 ALABPOS = 2 | |
70 AHELPPOS = 3 | |
71 ATYPEPOS = 4 | |
72 ACLPOS = 5 | |
73 AOVERPOS = 6 | |
74 AOCLPOS = 7 | |
75 | |
76 | |
77 foo = len(lxml.__version__) | 45 foo = len(lxml.__version__) |
78 # fug you, flake8. Say my name! | 46 # fug you, flake8. Say my name! |
79 FAKEEXE = "~~~REMOVE~~~ME~~~" | 47 FAKEEXE = "~~~REMOVE~~~ME~~~" |
80 # need this until a PR/version bump to fix galaxyxml prepending the exe even | 48 # need this until a PR/version bump to fix galaxyxml prepending the exe even |
81 # with override. | 49 # with override. |
84 def timenow(): | 52 def timenow(): |
85 """return current time as a string""" | 53 """return current time as a string""" |
86 return time.strftime("%d/%m/%Y %H:%M:%S", time.localtime(time.time())) | 54 return time.strftime("%d/%m/%Y %H:%M:%S", time.localtime(time.time())) |
87 | 55 |
88 | 56 |
89 def quote_non_numeric(s): | |
90 """return a prequoted string for non-numerics | |
91 useful for perl and Rscript parameter passing? | |
92 """ | |
93 try: | |
94 _ = float(s) | |
95 return s | |
96 except ValueError: | |
97 return '"%s"' % s | |
98 | |
99 | |
100 html_escape_table = { | |
101 "&": "&", | |
102 ">": ">", | |
103 "<": "<", | |
104 "#": "#", | |
105 "$": "$", | |
106 } | |
107 cheetah_escape_table = {"$": "\\$", "#": "\\#"} | 57 cheetah_escape_table = {"$": "\\$", "#": "\\#"} |
108 | |
109 | |
110 def html_escape(text): | |
111 """Produce entities within text.""" | |
112 return "".join([html_escape_table.get(c, c) for c in text]) | |
113 | 58 |
114 | 59 |
115 def cheetah_escape(text): | 60 def cheetah_escape(text): |
116 """Produce entities within text.""" | 61 """Produce entities within text.""" |
117 return "".join([cheetah_escape_table.get(c, c) for c in text]) | 62 return "".join([cheetah_escape_table.get(c, c) for c in text]) |
139 """ | 84 """ |
140 prepare command line cl for running the tool here | 85 prepare command line cl for running the tool here |
141 and prepare elements needed for galaxyxml tool generation | 86 and prepare elements needed for galaxyxml tool generation |
142 """ | 87 """ |
143 self.ourcwd = os.getcwd() | 88 self.ourcwd = os.getcwd() |
144 self.ourenv = copy.deepcopy(os.environ) | 89 self.collections = [] |
145 self.infiles = [x.split(ourdelim) for x in args.input_files] | 90 if len(args.collection) > 0: |
146 self.outfiles = [x.split(ourdelim) for x in args.output_files] | 91 try: |
147 self.addpar = [x.split(ourdelim) for x in args.additional_parameters] | 92 self.collections = [ |
93 json.loads(x) for x in args.collection if len(x.strip()) > 1 | |
94 ] | |
95 except Exception: | |
96 print( | |
97 f"--collections parameter {str(args.collection)} is malformed - should be a dictionary" | |
98 ) | |
99 try: | |
100 self.infiles = [ | |
101 json.loads(x) for x in args.input_files if len(x.strip()) > 1 | |
102 ] | |
103 except Exception: | |
104 print( | |
105 f"--input_files parameter {str(args.input_files)} is malformed - should be a dictionary" | |
106 ) | |
107 try: | |
108 self.outfiles = [ | |
109 json.loads(x) for x in args.output_files if len(x.strip()) > 1 | |
110 ] | |
111 except Exception: | |
112 print( | |
113 f"--output_files parameter {args.output_files} is malformed - should be a dictionary" | |
114 ) | |
115 try: | |
116 self.addpar = [ | |
117 json.loads(x) for x in args.additional_parameters if len(x.strip()) > 1 | |
118 ] | |
119 except Exception: | |
120 print( | |
121 f"--additional_parameters {args.additional_parameters} is malformed - should be a dictionary" | |
122 ) | |
123 try: | |
124 self.selpar = [ | |
125 json.loads(x) for x in args.selecttext_parameters if len(x.strip()) > 1 | |
126 ] | |
127 except Exception: | |
128 print( | |
129 f"--selecttext_parameters {args.selecttext_parameters} is malformed - should be a dictionary" | |
130 ) | |
148 self.args = args | 131 self.args = args |
149 self.cleanuppar() | 132 self.cleanuppar() |
150 self.lastclredirect = None | 133 self.lastclredirect = None |
151 self.lastxclredirect = None | 134 self.lastxclredirect = None |
152 self.cl = [] | 135 self.cl = [] |
153 self.xmlcl = [] | 136 self.xmlcl = [] |
154 self.is_positional = self.args.parampass == "positional" | 137 self.is_positional = self.args.parampass == "positional" |
155 if self.args.sysexe: | 138 if self.args.sysexe: |
156 self.executeme = self.args.sysexe | 139 if ' ' in self.args.sysexe: |
140 self.executeme = self.args.sysexe.split(' ') | |
141 else: | |
142 self.executeme = [self.args.sysexe, ] | |
157 else: | 143 else: |
158 if self.args.packages: | 144 if self.args.packages: |
159 self.executeme = self.args.packages.split(",")[0].split(":")[0].strip() | 145 self.executeme = [self.args.packages.split(",")[0].split(":")[0].strip(), ] |
160 else: | 146 else: |
161 self.executeme = None | 147 self.executeme = None |
162 aCL = self.cl.append | 148 aCL = self.cl.append |
163 aXCL = self.xmlcl.append | 149 aXCL = self.xmlcl.append |
164 assert args.parampass in [ | 150 assert args.parampass in [ |
173 self.tool_id, | 159 self.tool_id, |
174 self.args.tool_version, | 160 self.args.tool_version, |
175 self.args.tool_desc, | 161 self.args.tool_desc, |
176 FAKEEXE, | 162 FAKEEXE, |
177 ) | 163 ) |
178 self.newtarpath = "toolfactory_%s.tgz" % self.tool_name | 164 self.newtarpath = "%s_toolshed.gz" % self.tool_name |
179 self.tooloutdir = "./tfout" | 165 self.tooloutdir = "./tfout" |
180 self.repdir = "./TF_run_report_tempdir" | 166 self.repdir = "./TF_run_report_tempdir" |
181 self.testdir = os.path.join(self.tooloutdir, "test-data") | 167 self.testdir = os.path.join(self.tooloutdir, "test-data") |
182 if not os.path.exists(self.tooloutdir): | 168 if not os.path.exists(self.tooloutdir): |
183 os.mkdir(self.tooloutdir) | 169 os.mkdir(self.tooloutdir) |
198 if self.args.test_override: | 184 if self.args.test_override: |
199 stos = open(self.args.test_override, "r").readlines() | 185 stos = open(self.args.test_override, "r").readlines() |
200 self.test_override = [x.rstrip() for x in stos] | 186 self.test_override = [x.rstrip() for x in stos] |
201 else: | 187 else: |
202 self.test_override = None | 188 self.test_override = None |
203 if self.args.cl_prefix: # DIY CL start | 189 if self.args.script_path: |
190 for ex in self.executeme: | |
191 aCL(ex) | |
192 aXCL(ex) | |
193 aCL(self.sfile) | |
194 aXCL("$runme") | |
195 else: | |
196 aCL(self.executeme[0]) | |
197 aXCL(self.executeme[0]) | |
198 self.elog = os.path.join(self.repdir, "%s_error_log.txt" % self.tool_name) | |
199 self.tlog = os.path.join(self.repdir, "%s_runner_log.txt" % self.tool_name) | |
200 if self.args.parampass == "0": | |
201 self.clsimple() | |
202 else: | |
203 if self.args.parampass == "positional": | |
204 self.prepclpos() | |
205 self.clpositional() | |
206 else: | |
207 self.prepargp() | |
208 self.clargparse() | |
209 if self.args.cl_prefix: # DIY CL end - misnamed! | |
204 clp = self.args.cl_prefix.split(" ") | 210 clp = self.args.cl_prefix.split(" ") |
205 for c in clp: | 211 for c in clp: |
206 aCL(c) | 212 aCL(c) |
207 aXCL(c) | 213 aXCL(c) |
208 else: | 214 |
209 if self.args.script_path: | 215 def clsimple(self): |
210 aCL(self.executeme) | 216 """no parameters - uses < and > for i/o""" |
211 aCL(self.sfile) | 217 aCL = self.cl.append |
212 aXCL(self.executeme) | 218 aXCL = self.xmlcl.append |
213 aXCL("$runme") | 219 if len(self.infiles) > 0: |
214 else: | 220 aCL("<") |
215 aCL(self.executeme) | 221 aCL(self.infiles[0]["infilename"]) |
216 aXCL(self.executeme) | 222 aXCL("<") |
217 self.elog = os.path.join(self.repdir, "%s_error_log.txt" % self.tool_name) | 223 aXCL("$%s" % self.infiles[0]["infilename"]) |
218 self.tlog = os.path.join(self.repdir, "%s_runner_log.txt" % self.tool_name) | 224 if len(self.outfiles) > 0: |
219 | 225 aCL(">") |
220 if self.args.parampass == "0": | 226 aCL(self.outfiles[0]["name"]) |
221 self.clsimple() | 227 aXCL(">") |
222 else: | 228 aXCL("$%s" % self.outfiles[0]["name"]) |
223 clsuffix = [] | 229 |
224 xclsuffix = [] | 230 def prepargp(self): |
225 for i, p in enumerate(self.infiles): | 231 clsuffix = [] |
226 if p[IOCLPOS].upper() == "STDIN": | 232 xclsuffix = [] |
227 appendme = [ | 233 for i, p in enumerate(self.infiles): |
228 p[ICLPOS], | 234 if p["origCL"].strip().upper() == "STDIN": |
229 p[ICLPOS], | 235 appendme = [ |
230 p[IPATHPOS], | 236 p["infilename"], |
231 "< %s" % p[IPATHPOS], | 237 p["infilename"], |
232 ] | 238 "< %s" % p["infilename"], |
233 xappendme = [ | 239 ] |
234 p[ICLPOS], | 240 xappendme = [ |
235 p[ICLPOS], | 241 p["infilename"], |
236 p[IPATHPOS], | 242 p["infilename"], |
237 "< $%s" % p[ICLPOS], | 243 "< $%s" % p["infilename"], |
238 ] | 244 ] |
239 else: | 245 else: |
240 appendme = [p[IOCLPOS], p[ICLPOS], p[IPATHPOS], ""] | 246 appendme = [p["CL"], p["CL"], ""] |
241 xappendme = [p[IOCLPOS], p[ICLPOS], "$%s" % p[ICLPOS], ""] | 247 xappendme = [p["CL"], "$%s" % p["CL"], ""] |
242 clsuffix.append(appendme) | 248 clsuffix.append(appendme) |
243 xclsuffix.append(xappendme) | 249 xclsuffix.append(xappendme) |
244 for i, p in enumerate(self.outfiles): | 250 for i, p in enumerate(self.outfiles): |
245 if p[OOCLPOS] == "STDOUT": | 251 if p["origCL"].strip().upper() == "STDOUT": |
246 self.lastclredirect = [">", p[ONAMEPOS]] | 252 self.lastclredirect = [">", p["name"]] |
247 self.lastxclredirect = [">", "$%s" % p[OCLPOS]] | 253 self.lastxclredirect = [">", "$%s" % p["name"]] |
248 else: | 254 else: |
249 clsuffix.append([p[OCLPOS], p[ONAMEPOS], p[ONAMEPOS], ""]) | 255 clsuffix.append([p["name"], p["name"], ""]) |
250 xclsuffix.append([p[OCLPOS], p[ONAMEPOS], "$%s" % p[ONAMEPOS], ""]) | 256 xclsuffix.append([p["name"], "$%s" % p["name"], ""]) |
251 for p in self.addpar: | 257 for p in self.addpar: |
252 clsuffix.append([p[AOCLPOS], p[ACLPOS], p[AVALPOS], p[AOVERPOS]]) | 258 clsuffix.append([p["CL"], p["name"], p["override"]]) |
253 xclsuffix.append( | 259 xclsuffix.append([p["CL"], '"$%s"' % p["name"], p["override"]]) |
254 [p[AOCLPOS], p[ACLPOS], '"$%s"' % p[ANAMEPOS], p[AOVERPOS]] | 260 for p in self.selpar: |
255 ) | 261 clsuffix.append([p["CL"], p["name"], p["override"]]) |
256 clsuffix.sort() | 262 xclsuffix.append([p["CL"], '"$%s"' % p["name"], p["override"]]) |
257 xclsuffix.sort() | 263 clsuffix.sort() |
258 self.xclsuffix = xclsuffix | 264 xclsuffix.sort() |
259 self.clsuffix = clsuffix | 265 self.xclsuffix = xclsuffix |
260 if self.args.parampass == "positional": | 266 self.clsuffix = clsuffix |
261 self.clpositional() | 267 |
262 else: | 268 def prepclpos(self): |
263 self.clargparse() | 269 clsuffix = [] |
270 xclsuffix = [] | |
271 for i, p in enumerate(self.infiles): | |
272 if p["origCL"].strip().upper() == "STDIN": | |
273 appendme = [ | |
274 "999", | |
275 p["infilename"], | |
276 "< $%s" % p["infilename"], | |
277 ] | |
278 xappendme = [ | |
279 "999", | |
280 p["infilename"], | |
281 "< $%s" % p["infilename"], | |
282 ] | |
283 else: | |
284 appendme = [p["CL"], p["infilename"], ""] | |
285 xappendme = [p["CL"], "$%s" % p["infilename"], ""] | |
286 clsuffix.append(appendme) | |
287 xclsuffix.append(xappendme) | |
288 for i, p in enumerate(self.outfiles): | |
289 if p["origCL"].strip().upper() == "STDOUT": | |
290 self.lastclredirect = [">", p["name"]] | |
291 self.lastxclredirect = [">", "$%s" % p["name"]] | |
292 else: | |
293 clsuffix.append([p["CL"], p["name"], ""]) | |
294 xclsuffix.append([p["CL"], "$%s" % p["name"], ""]) | |
295 for p in self.addpar: | |
296 clsuffix.append([p["CL"], p["name"], p["override"]]) | |
297 xclsuffix.append([p["CL"], '"$%s"' % p["name"], p["override"]]) | |
298 for p in self.selpar: | |
299 clsuffix.append([p["CL"], p["name"], p["override"]]) | |
300 xclsuffix.append([p["CL"], '"$%s"' % p["name"], p["override"]]) | |
301 clsuffix.sort() | |
302 xclsuffix.sort() | |
303 self.xclsuffix = xclsuffix | |
304 self.clsuffix = clsuffix | |
264 | 305 |
265 def prepScript(self): | 306 def prepScript(self): |
266 rx = open(self.args.script_path, "r").readlines() | 307 rx = open(self.args.script_path, "r").readlines() |
267 rx = [x.rstrip() for x in rx] | 308 rx = [x.rstrip() for x in rx] |
268 rxcheck = [x.strip() for x in rx if x.strip() > ""] | 309 rxcheck = [x.strip() for x in rx if x.strip() > ""] |
269 assert len(rxcheck) > 0, "Supplied script is empty. Cannot run" | 310 assert len(rxcheck) > 0, "Supplied script is empty. Cannot run" |
270 self.script = "\n".join(rx) | 311 self.script = "\n".join(rx) |
271 fhandle, self.sfile = tempfile.mkstemp( | 312 fhandle, self.sfile = tempfile.mkstemp( |
272 prefix=self.tool_name, suffix="_%s" % (self.executeme) | 313 prefix=self.tool_name, suffix="_%s" % (self.executeme[0]) |
273 ) | 314 ) |
274 tscript = open(self.sfile, "w") | 315 tscript = open(self.sfile, "w") |
275 tscript.write(self.script) | 316 tscript.write(self.script) |
276 tscript.close() | 317 tscript.close() |
277 self.escapedScript = [cheetah_escape(x) for x in rx] | 318 self.escapedScript = [cheetah_escape(x) for x in rx] |
278 self.spacedScript = [f" {x}" for x in rx if x.strip() > ""] | 319 self.spacedScript = [f" {x}" for x in rx if x.strip() > ""] |
279 art = "%s.%s" % (self.tool_name, self.executeme) | 320 art = "%s.%s" % (self.tool_name, self.executeme[0]) |
280 artifact = open(art, "wb") | 321 artifact = open(art, "wb") |
281 artifact.write(bytes("\n".join(self.escapedScript), "utf8")) | 322 artifact.write(bytes("\n".join(self.escapedScript), "utf8")) |
282 artifact.close() | 323 artifact.close() |
283 | 324 |
284 def cleanuppar(self): | 325 def cleanuppar(self): |
285 """ positional parameters are complicated by their numeric ordinal""" | 326 """ positional parameters are complicated by their numeric ordinal""" |
286 if self.args.parampass == "positional": | 327 if self.args.parampass == "positional": |
287 for i, p in enumerate(self.infiles): | 328 for i, p in enumerate(self.infiles): |
288 assert ( | 329 assert ( |
289 p[ICLPOS].isdigit() or p[ICLPOS].strip().upper() == "STDIN" | 330 p["CL"].isdigit() or p["CL"].strip().upper() == "STDIN" |
290 ), "Positional parameters must be ordinal integers - got %s for %s" % ( | 331 ), "Positional parameters must be ordinal integers - got %s for %s" % ( |
291 p[ICLPOS], | 332 p["CL"], |
292 p[ILABPOS], | 333 p["label"], |
293 ) | 334 ) |
294 for i, p in enumerate(self.outfiles): | 335 for i, p in enumerate(self.outfiles): |
295 assert ( | 336 assert ( |
296 p[OCLPOS].isdigit() or p[OCLPOS].strip().upper() == "STDOUT" | 337 p["CL"].isdigit() or p["CL"].strip().upper() == "STDOUT" |
297 ), "Positional parameters must be ordinal integers - got %s for %s" % ( | 338 ), "Positional parameters must be ordinal integers - got %s for %s" % ( |
298 p[OCLPOS], | 339 p["CL"], |
299 p[ONAMEPOS], | 340 p["name"], |
300 ) | 341 ) |
301 for i, p in enumerate(self.addpar): | 342 for i, p in enumerate(self.addpar): |
302 assert p[ | 343 assert p[ |
303 ACLPOS | 344 "CL" |
304 ].isdigit(), "Positional parameters must be ordinal integers - got %s for %s" % ( | 345 ].isdigit(), "Positional parameters must be ordinal integers - got %s for %s" % ( |
305 p[ACLPOS], | 346 p["CL"], |
306 p[ANAMEPOS], | 347 p["name"], |
307 ) | 348 ) |
308 for i, p in enumerate(self.infiles): | 349 for i, p in enumerate(self.infiles): |
309 infp = copy.copy(p) | 350 infp = copy.copy(p) |
310 icl = infp[ICLPOS] | 351 infp["origCL"] = infp["CL"] |
311 infp.append(icl) | 352 if self.args.parampass in ["positional", "0"]: |
312 if ( | 353 infp["infilename"] = infp["label"].replace(" ", "_") |
313 infp[ICLPOS].isdigit() | 354 else: |
314 or self.args.parampass == "0" | 355 infp["infilename"] = infp["CL"] |
315 or infp[ICLPOS].strip().upper() == "STDOUT" | |
316 ): | |
317 scl = "input%d" % (i + 1) | |
318 infp[ICLPOS] = scl | |
319 self.infiles[i] = infp | 356 self.infiles[i] = infp |
320 for i, p in enumerate(self.outfiles): | 357 for i, p in enumerate(self.outfiles): |
321 p.append(p[OCLPOS]) # keep copy | 358 p["origCL"] = p["CL"] # keep copy |
322 if (p[OOCLPOS].isdigit() and self.args.parampass != "positional") or p[ | |
323 OOCLPOS | |
324 ].strip().upper() == "STDOUT": | |
325 scl = p[ONAMEPOS] | |
326 p[OCLPOS] = scl | |
327 self.outfiles[i] = p | 359 self.outfiles[i] = p |
328 for i, p in enumerate(self.addpar): | 360 for i, p in enumerate(self.addpar): |
329 p.append(p[ACLPOS]) | 361 p["origCL"] = p["CL"] |
330 if p[ACLPOS].isdigit(): | |
331 scl = "param%s" % p[ACLPOS] | |
332 p[ACLPOS] = scl | |
333 self.addpar[i] = p | 362 self.addpar[i] = p |
334 | |
335 def clsimple(self): | |
336 """no parameters - uses < and > for i/o""" | |
337 aCL = self.cl.append | |
338 aXCL = self.xmlcl.append | |
339 | |
340 if len(self.infiles) > 0: | |
341 aCL("<") | |
342 aCL(self.infiles[0][IPATHPOS]) | |
343 aXCL("<") | |
344 aXCL("$%s" % self.infiles[0][ICLPOS]) | |
345 if len(self.outfiles) > 0: | |
346 aCL(">") | |
347 aCL(self.outfiles[0][OCLPOS]) | |
348 aXCL(">") | |
349 aXCL("$%s" % self.outfiles[0][ONAMEPOS]) | |
350 | 363 |
351 def clpositional(self): | 364 def clpositional(self): |
352 # inputs in order then params | 365 # inputs in order then params |
353 aCL = self.cl.append | 366 aCL = self.cl.append |
354 for (o_v, k, v, koverride) in self.clsuffix: | 367 for (k, v, koverride) in self.clsuffix: |
355 if " " in v: | 368 if " " in v: |
356 aCL("%s" % v) | 369 aCL("%s" % v) |
357 else: | 370 else: |
358 aCL(v) | 371 aCL(v) |
359 aXCL = self.xmlcl.append | 372 aXCL = self.xmlcl.append |
360 for (o_v, k, v, koverride) in self.xclsuffix: | 373 for (k, v, koverride) in self.xclsuffix: |
361 aXCL(v) | 374 aXCL(v) |
362 if self.lastxclredirect: | 375 if self.lastxclredirect: |
363 aXCL(self.lastxclredirect[0]) | 376 aXCL(self.lastxclredirect[0]) |
364 aXCL(self.lastxclredirect[1]) | 377 aXCL(self.lastxclredirect[1]) |
365 | 378 |
367 """argparse style""" | 380 """argparse style""" |
368 aCL = self.cl.append | 381 aCL = self.cl.append |
369 aXCL = self.xmlcl.append | 382 aXCL = self.xmlcl.append |
370 # inputs then params in argparse named form | 383 # inputs then params in argparse named form |
371 | 384 |
372 for (o_v, k, v, koverride) in self.xclsuffix: | 385 for (k, v, koverride) in self.xclsuffix: |
373 if koverride > "": | 386 if koverride > "": |
374 k = koverride | 387 k = koverride |
375 elif len(k.strip()) == 1: | 388 elif len(k.strip()) == 1: |
376 k = "-%s" % k | 389 k = "-%s" % k |
377 else: | 390 else: |
378 k = "--%s" % k | 391 k = "--%s" % k |
379 aXCL(k) | 392 aXCL(k) |
380 aXCL(v) | 393 aXCL(v) |
381 for (o_v, k, v, koverride) in self.clsuffix: | 394 for (k, v, koverride) in self.clsuffix: |
382 if koverride > "": | 395 if koverride > "": |
383 k = koverride | 396 k = koverride |
384 elif len(k.strip()) == 1: | 397 elif len(k.strip()) == 1: |
385 k = "-%s" % k | 398 k = "-%s" % k |
386 else: | 399 else: |
398 return ndash | 411 return ndash |
399 | 412 |
400 def doXMLparam(self): | 413 def doXMLparam(self): |
401 """flake8 made me do this...""" | 414 """flake8 made me do this...""" |
402 for p in self.outfiles: | 415 for p in self.outfiles: |
403 # --output_files "$otab.history_name~~~$otab.history_format~~~$otab.history_CL~~~$otab.history_test" | 416 newname = p["name"] |
404 newname, newfmt, newcl, test, oldcl = p | 417 newfmt = p["format"] |
418 newcl = p["CL"] | |
419 test = p["test"] | |
420 oldcl = p["origCL"] | |
405 test = test.strip() | 421 test = test.strip() |
406 ndash = self.getNdash(newcl) | 422 ndash = self.getNdash(newcl) |
407 aparm = gxtp.OutputData( | 423 aparm = gxtp.OutputData( |
408 name=newname, format=newfmt, num_dashes=ndash, label=newname | 424 name=newname, format=newfmt, num_dashes=ndash, label=newname |
409 ) | 425 ) |
444 value="%s_sample" % newname, | 460 value="%s_sample" % newname, |
445 compare=c, | 461 compare=c, |
446 delta=delta, | 462 delta=delta, |
447 delta_frac=delta_frac, | 463 delta_frac=delta_frac, |
448 ) | 464 ) |
465 else: | |
466 c = test | |
467 tp = gxtp.TestOutput( | |
468 name=newname, | |
469 value="%s_sample" % newname, | |
470 compare=c, | |
471 ) | |
449 self.testparam.append(tp) | 472 self.testparam.append(tp) |
450 for p in self.infiles: | 473 for p in self.infiles: |
451 newname = p[ICLPOS] | 474 newname = p["infilename"] |
452 newfmt = p[IFMTPOS] | 475 newfmt = p["format"] |
453 ndash = self.getNdash(newname) | 476 ndash = self.getNdash(newname) |
454 if not len(p[ILABPOS]) > 0: | 477 if not len(p["label"]) > 0: |
455 alab = p[ICLPOS] | 478 alab = p["CL"] |
456 else: | 479 else: |
457 alab = p[ILABPOS] | 480 alab = p["label"] |
458 aninput = gxtp.DataParam( | 481 aninput = gxtp.DataParam( |
459 newname, | 482 newname, |
460 optional=False, | 483 optional=False, |
461 label=alab, | 484 label=alab, |
462 help=p[IHELPOS], | 485 help=p["help"], |
463 format=newfmt, | 486 format=newfmt, |
464 multiple=False, | 487 multiple=False, |
465 num_dashes=ndash, | 488 num_dashes=ndash, |
466 ) | 489 ) |
467 aninput.positional = self.is_positional | 490 aninput.positional = self.is_positional |
491 if self.is_positional: | |
492 if p["origCL"].upper() == "STDIN": | |
493 aparm.positional = 9999998 | |
494 aparm.command_line_override = "> $%s" % newname | |
495 else: | |
496 aparm.positional = int(p["origCL"]) | |
497 aparm.command_line_override = "$%s" % newname | |
468 self.tinputs.append(aninput) | 498 self.tinputs.append(aninput) |
469 tparm = gxtp.TestParam(name=newname, value="%s_sample" % newname) | 499 tparm = gxtp.TestParam(name=newname, value="%s_sample" % newname) |
470 self.testparam.append(tparm) | 500 self.testparam.append(tparm) |
471 for p in self.addpar: | 501 for p in self.addpar: |
472 ( | 502 newname = p["name"] |
473 newname, | 503 newval = p["value"] |
474 newval, | 504 newlabel = p["label"] |
475 newlabel, | 505 newhelp = p["help"] |
476 newhelp, | 506 newtype = p["type"] |
477 newtype, | 507 newcl = p["CL"] |
478 newcl, | 508 oldcl = p["origCL"] |
479 override, | |
480 oldcl, | |
481 ) = p | |
482 if not len(newlabel) > 0: | 509 if not len(newlabel) > 0: |
483 newlabel = newname | 510 newlabel = newname |
484 ndash = self.getNdash(newname) | 511 ndash = self.getNdash(newname) |
485 if newtype == "text": | 512 if newtype == "text": |
486 aparm = gxtp.TextParam( | 513 aparm = gxtp.TextParam( |
504 label=newname, | 531 label=newname, |
505 help=newhelp, | 532 help=newhelp, |
506 value=newval, | 533 value=newval, |
507 num_dashes=ndash, | 534 num_dashes=ndash, |
508 ) | 535 ) |
536 elif newtype == "boolean": | |
537 aparm = gxtp.BooleanParam( | |
538 newname, | |
539 label=newname, | |
540 help=newhelp, | |
541 value=newval, | |
542 num_dashes=ndash, | |
543 ) | |
509 else: | 544 else: |
510 raise ValueError( | 545 raise ValueError( |
511 'Unrecognised parameter type "%s" for\ | 546 'Unrecognised parameter type "%s" for\ |
512 additional parameter %s in makeXML' | 547 additional parameter %s in makeXML' |
513 % (newtype, newname) | 548 % (newtype, newname) |
516 if self.is_positional: | 551 if self.is_positional: |
517 aparm.positional = int(oldcl) | 552 aparm.positional = int(oldcl) |
518 self.tinputs.append(aparm) | 553 self.tinputs.append(aparm) |
519 tparm = gxtp.TestParam(newname, value=newval) | 554 tparm = gxtp.TestParam(newname, value=newval) |
520 self.testparam.append(tparm) | 555 self.testparam.append(tparm) |
556 for p in self.selpar: | |
557 newname = p["name"] | |
558 newval = p["value"] | |
559 newlabel = p["label"] | |
560 newhelp = p["help"] | |
561 newtype = p["type"] | |
562 newcl = p["CL"] | |
563 if not len(newlabel) > 0: | |
564 newlabel = newname | |
565 ndash = self.getNdash(newname) | |
566 if newtype == "selecttext": | |
567 newtext = p["texts"] | |
568 aparm = gxtp.SelectParam( | |
569 newname, | |
570 label=newlabel, | |
571 help=newhelp, | |
572 num_dashes=ndash, | |
573 ) | |
574 for i in range(len(newval)): | |
575 anopt = gxtp.SelectOption( | |
576 value=newval[i], | |
577 text=newtext[i], | |
578 ) | |
579 aparm.append(anopt) | |
580 aparm.positional = self.is_positional | |
581 if self.is_positional: | |
582 aparm.positional = int(newcl) | |
583 self.tinputs.append(aparm) | |
584 tparm = gxtp.TestParam(newname, value=newval) | |
585 self.testparam.append(tparm) | |
586 else: | |
587 raise ValueError( | |
588 'Unrecognised parameter type "%s" for\ | |
589 selecttext parameter %s in makeXML' | |
590 % (newtype, newname) | |
591 ) | |
592 for p in self.collections: | |
593 newkind = p["kind"] | |
594 newname = p["name"] | |
595 newlabel = p["label"] | |
596 newdisc = p["discover"] | |
597 collect = gxtp.OutputCollection(newname, label=newlabel, type=newkind) | |
598 disc = gxtp.DiscoverDatasets( | |
599 pattern=newdisc, directory=f"{newname}", visible="false" | |
600 ) | |
601 collect.append(disc) | |
602 self.toutputs.append(collect) | |
603 tparm = gxtp.TestOutput(newname, ftype="pdf") | |
604 self.testparam.append(tparm) | |
521 | 605 |
522 def doNoXMLparam(self): | 606 def doNoXMLparam(self): |
523 """filter style package - stdin to stdout""" | 607 """filter style package - stdin to stdout""" |
524 if len(self.infiles) > 0: | 608 if len(self.infiles) > 0: |
525 alab = self.infiles[0][ILABPOS] | 609 alab = self.infiles[0]["label"] |
526 if len(alab) == 0: | 610 if len(alab) == 0: |
527 alab = self.infiles[0][ICLPOS] | 611 alab = self.infiles[0]["infilename"] |
528 max1s = ( | 612 max1s = ( |
529 "Maximum one input if parampass is 0 but multiple input files supplied - %s" | 613 "Maximum one input if parampass is 0 but multiple input files supplied - %s" |
530 % str(self.infiles) | 614 % str(self.infiles) |
531 ) | 615 ) |
532 assert len(self.infiles) == 1, max1s | 616 assert len(self.infiles) == 1, max1s |
533 newname = self.infiles[0][ICLPOS] | 617 newname = self.infiles[0]["infilename"] |
534 aninput = gxtp.DataParam( | 618 aninput = gxtp.DataParam( |
535 newname, | 619 newname, |
536 optional=False, | 620 optional=False, |
537 label=alab, | 621 label=alab, |
538 help=self.infiles[0][IHELPOS], | 622 help=self.infiles[0]["help"], |
539 format=self.infiles[0][IFMTPOS], | 623 format=self.infiles[0]["format"], |
540 multiple=False, | 624 multiple=False, |
541 num_dashes=0, | 625 num_dashes=0, |
542 ) | 626 ) |
543 aninput.command_line_override = "< $%s" % newname | 627 aninput.command_line_override = "< $%s" % newname |
544 aninput.positional = self.is_positional | 628 aninput.positional = True |
545 self.tinputs.append(aninput) | 629 self.tinputs.append(aninput) |
546 tp = gxtp.TestParam(name=newname, value="%s_sample" % newname) | 630 tp = gxtp.TestParam(name=newname, value="%s_sample" % newname) |
547 self.testparam.append(tp) | 631 self.testparam.append(tp) |
548 if len(self.outfiles) > 0: | 632 if len(self.outfiles) > 0: |
549 newname = self.outfiles[0][OCLPOS] | 633 newname = self.outfiles[0]["name"] |
550 newfmt = self.outfiles[0][OFMTPOS] | 634 newfmt = self.outfiles[0]["format"] |
551 anout = gxtp.OutputData(newname, format=newfmt, num_dashes=0) | 635 anout = gxtp.OutputData(newname, format=newfmt, num_dashes=0) |
552 anout.command_line_override = "> $%s" % newname | 636 anout.command_line_override = "> $%s" % newname |
553 anout.positional = self.is_positional | 637 anout.positional = self.is_positional |
554 self.toutputs.append(anout) | 638 self.toutputs.append(anout) |
555 tp = gxtp.TestOutput( | 639 tp = gxtp.TestOutput(name=newname, value="%s_sample" % newname) |
556 name=newname, value="%s_sample" % newname | |
557 ) | |
558 self.testparam.append(tp) | 640 self.testparam.append(tp) |
559 | 641 |
560 def makeXML(self): | 642 def makeXML(self): |
561 """ | 643 """ |
562 Create a Galaxy xml tool wrapper for the new script | 644 Create a Galaxy xml tool wrapper for the new script |
637 if ( | 719 if ( |
638 self.test_override | 720 self.test_override |
639 ): # cannot do this inside galaxyxml as it expects lxml objects for tests | 721 ): # cannot do this inside galaxyxml as it expects lxml objects for tests |
640 part1 = exml.split("<tests>")[0] | 722 part1 = exml.split("<tests>")[0] |
641 part2 = exml.split("</tests>")[1] | 723 part2 = exml.split("</tests>")[1] |
642 fixed = "%s\n%s\n%s" % (part1, self.test_override, part2) | 724 fixed = "%s\n%s\n%s" % (part1, "\n".join(self.test_override), part2) |
643 exml = fixed | 725 exml = fixed |
644 # exml = exml.replace('range="1:"', 'range="1000:"') | 726 # exml = exml.replace('range="1:"', 'range="1000:"') |
645 xf = open("%s.xml" % self.tool_name, "w") | 727 xf = open("%s.xml" % self.tool_name, "w") |
646 xf.write(exml) | 728 xf.write(exml) |
647 xf.write("\n") | 729 xf.write("\n") |
672 sto.write( | 754 sto.write( |
673 "## Executing Toolfactory generated command line = %s\n" % scl | 755 "## Executing Toolfactory generated command line = %s\n" % scl |
674 ) | 756 ) |
675 sto.flush() | 757 sto.flush() |
676 subp = subprocess.run( | 758 subp = subprocess.run( |
677 self.cl, env=self.ourenv, shell=False, stdout=sto, stderr=ste | 759 self.cl, shell=False, stdout=sto, stderr=ste |
678 ) | 760 ) |
679 sto.close() | 761 sto.close() |
680 ste.close() | 762 ste.close() |
681 retval = subp.returncode | 763 retval = subp.returncode |
682 else: # work around special case - stdin and write to stdout | 764 else: # work around special case - stdin and write to stdout |
683 if len(self.infiles) > 0: | 765 if len(self.infiles) > 0: |
684 sti = open(self.infiles[0][IPATHPOS], "rb") | 766 sti = open(self.infiles[0]["name"], "rb") |
685 else: | 767 else: |
686 sti = sys.stdin | 768 sti = sys.stdin |
687 if len(self.outfiles) > 0: | 769 if len(self.outfiles) > 0: |
688 sto = open(self.outfiles[0][ONAMEPOS], "wb") | 770 sto = open(self.outfiles[0]["name"], "wb") |
689 else: | 771 else: |
690 sto = sys.stdout | 772 sto = sys.stdout |
691 subp = subprocess.run( | 773 subp = subprocess.run( |
692 self.cl, env=self.ourenv, shell=False, stdout=sto, stdin=sti | 774 self.cl, shell=False, stdout=sto, stdin=sti |
693 ) | 775 ) |
694 sto.write("## Executing Toolfactory generated command line = %s\n" % scl) | 776 sto.write("## Executing Toolfactory generated command line = %s\n" % scl) |
695 retval = subp.returncode | 777 retval = subp.returncode |
696 sto.close() | 778 sto.close() |
697 sti.close() | 779 sti.close() |
783 "ToolFactory", | 865 "ToolFactory", |
784 ] | 866 ] |
785 tout.write("running\n%s\n" % " ".join(cll)) | 867 tout.write("running\n%s\n" % " ".join(cll)) |
786 subp = subprocess.run( | 868 subp = subprocess.run( |
787 cll, | 869 cll, |
788 env=self.ourenv, | |
789 cwd=self.ourcwd, | 870 cwd=self.ourcwd, |
790 shell=False, | 871 shell=False, |
791 stderr=tout, | 872 stderr=tout, |
792 stdout=tout, | 873 stdout=tout, |
793 ) | 874 ) |
813 yaml.dump(odict, yamlf, allow_unicode=True) | 894 yaml.dump(odict, yamlf, allow_unicode=True) |
814 yamlf.close() | 895 yamlf.close() |
815 | 896 |
816 def makeTool(self): | 897 def makeTool(self): |
817 """write xmls and input samples into place""" | 898 """write xmls and input samples into place""" |
818 self.makeXML() | 899 if self.args.parampass == 0: |
900 self.doNoXMLparam() | |
901 else: | |
902 self.makeXML() | |
819 if self.args.script_path: | 903 if self.args.script_path: |
820 stname = os.path.join(self.tooloutdir, "%s" % (self.sfile)) | 904 stname = os.path.join(self.tooloutdir, self.sfile) |
821 if not os.path.exists(stname): | 905 if not os.path.exists(stname): |
822 shutil.copyfile(self.sfile, stname) | 906 shutil.copyfile(self.sfile, stname) |
823 xreal = "%s.xml" % self.tool_name | 907 xreal = "%s.xml" % self.tool_name |
824 xout = os.path.join(self.tooloutdir, xreal) | 908 xout = os.path.join(self.tooloutdir, xreal) |
825 shutil.copyfile(xreal, xout) | 909 shutil.copyfile(xreal, xout) |
826 for p in self.infiles: | 910 for p in self.infiles: |
827 pth = p[IPATHPOS] | 911 pth = p["name"] |
828 dest = os.path.join(self.testdir, "%s_sample" % p[ICLPOS]) | 912 dest = os.path.join(self.testdir, "%s_sample" % p["infilename"]) |
829 shutil.copyfile(pth, dest) | 913 shutil.copyfile(pth, dest) |
830 | 914 dest = os.path.join(self.repdir, "%s_sample" % p["infilename"]) |
831 def makeToolTar(self): | 915 shutil.copyfile(pth, dest) |
916 | |
917 def makeToolTar(self, report_fail=False): | |
832 """move outputs into test-data and prepare the tarball""" | 918 """move outputs into test-data and prepare the tarball""" |
833 excludeme = "_planemo_test_report.html" | 919 excludeme = "_planemo_test_report.html" |
834 | 920 |
835 def exclude_function(tarinfo): | 921 def exclude_function(tarinfo): |
836 filename = tarinfo.name | 922 filename = tarinfo.name |
839 if os.path.exists(self.tlog): | 925 if os.path.exists(self.tlog): |
840 tout = open(self.tlog, "a") | 926 tout = open(self.tlog, "a") |
841 else: | 927 else: |
842 tout = open(self.tlog, "w") | 928 tout = open(self.tlog, "w") |
843 for p in self.outfiles: | 929 for p in self.outfiles: |
844 oname = p[ONAMEPOS] | 930 oname = p["name"] |
845 tdest = os.path.join(self.testdir, "%s_sample" % oname) | 931 tdest = os.path.join(self.testdir, "%s_sample" % oname) |
932 src = os.path.join(self.testdir, oname) | |
846 if not os.path.isfile(tdest): | 933 if not os.path.isfile(tdest): |
847 src = os.path.join(self.testdir, oname) | |
848 if os.path.isfile(src): | 934 if os.path.isfile(src): |
849 shutil.copyfile(src, tdest) | 935 shutil.copyfile(src, tdest) |
850 dest = os.path.join(self.repdir, "%s.sample" % (oname)) | 936 dest = os.path.join(self.repdir, "%s.sample" % (oname)) |
851 shutil.copyfile(src, dest) | 937 shutil.copyfile(src, dest) |
852 else: | 938 else: |
853 tout.write( | 939 if report_fail: |
854 "###Output file %s not found in testdir %s. This is normal during the first Planemo run that generates test outputs" | 940 tout.write( |
855 % (tdest, self.testdir) | 941 "###Tool may have failed - output file %s not found in testdir after planemo run %s." |
856 ) | 942 % (tdest, self.testdir) |
943 ) | |
857 tf = tarfile.open(self.newtarpath, "w:gz") | 944 tf = tarfile.open(self.newtarpath, "w:gz") |
858 tf.add( | 945 tf.add( |
859 name=self.tooloutdir, | 946 name=self.tooloutdir, |
860 arcname=self.tool_name, | 947 arcname=self.tool_name, |
861 filter=exclude_function, | 948 filter=exclude_function, |
868 with os.scandir(self.tooloutdir) as outs: | 955 with os.scandir(self.tooloutdir) as outs: |
869 for entry in outs: | 956 for entry in outs: |
870 if not entry.is_file(): | 957 if not entry.is_file(): |
871 continue | 958 continue |
872 if "." in entry.name: | 959 if "." in entry.name: |
873 nayme, ext = os.path.splitext(entry.name) | 960 _, ext = os.path.splitext(entry.name) |
874 if ext in [".yml", ".xml", ".json", ".yaml"]: | 961 if ext in [".tgz", ".json"]: |
875 ext = f"{ext}.txt" | 962 continue |
963 if ext in [".yml", ".xml", ".yaml"]: | |
964 newname = f"{entry.name.replace('.','_')}.txt" | |
965 else: | |
966 newname = entry.name | |
876 else: | 967 else: |
877 ext = ".txt" | 968 newname = f"{entry.name}.txt" |
878 ofn = "%s%s" % (entry.name.replace(".", "_"), ext) | 969 dest = os.path.join(self.repdir, newname) |
879 dest = os.path.join(self.repdir, ofn) | |
880 src = os.path.join(self.tooloutdir, entry.name) | 970 src = os.path.join(self.tooloutdir, entry.name) |
881 shutil.copyfile(src, dest) | 971 shutil.copyfile(src, dest) |
882 with os.scandir(self.testdir) as outs: | 972 if self.args.include_tests: |
883 for entry in outs: | 973 with os.scandir(self.testdir) as outs: |
884 if ( | 974 for entry in outs: |
885 (not entry.is_file()) | 975 if (not entry.is_file()) or entry.name.endswith( |
886 or entry.name.endswith("_sample") | 976 "_planemo_test_report.html" |
887 or entry.name.endswith("_planemo_test_report.html") | 977 ): |
888 ): | 978 continue |
889 continue | 979 if "." in entry.name: |
890 if "." in entry.name: | 980 _, ext = os.path.splitext(entry.name) |
891 nayme, ext = os.path.splitext(entry.name) | 981 if ext in [".tgz", ".json"]: |
892 else: | 982 continue |
893 ext = ".txt" | 983 if ext in [".yml", ".xml", ".yaml"]: |
894 newname = f"{entry.name}{ext}" | 984 newname = f"{entry.name.replace('.','_')}.txt" |
895 dest = os.path.join(self.repdir, newname) | 985 else: |
896 src = os.path.join(self.testdir, entry.name) | 986 newname = entry.name |
897 shutil.copyfile(src, dest) | 987 else: |
898 | 988 newname = f"{entry.name}.txt" |
899 def planemo_test(self, genoutputs=True): | 989 dest = os.path.join(self.repdir, newname) |
990 src = os.path.join(self.testdir, entry.name) | |
991 shutil.copyfile(src, dest) | |
992 | |
993 | |
994 def planemo_test_once(self): | |
900 """planemo is a requirement so is available for testing but needs a | 995 """planemo is a requirement so is available for testing but needs a |
901 different call if in the biocontainer - see above | 996 different call if in the biocontainer - see above |
902 and for generating test outputs if command or test overrides are | 997 and for generating test outputs if command or test overrides are |
903 supplied test outputs are sent to repdir for display | 998 supplied test outputs are sent to repdir for display |
904 """ | 999 """ |
908 ) | 1003 ) |
909 if os.path.exists(self.tlog): | 1004 if os.path.exists(self.tlog): |
910 tout = open(self.tlog, "a") | 1005 tout = open(self.tlog, "a") |
911 else: | 1006 else: |
912 tout = open(self.tlog, "w") | 1007 tout = open(self.tlog, "w") |
913 if genoutputs: | 1008 cll = [ |
914 dummy, tfile = tempfile.mkstemp() | 1009 "planemo", |
915 cll = [ | 1010 "test", |
916 "planemo", | 1011 "--conda_auto_init", |
917 "test", | 1012 "--test_data", |
918 "--test_data", | 1013 os.path.abspath(self.testdir), |
919 os.path.abspath(self.testdir), | 1014 "--test_output", |
920 "--test_output", | 1015 os.path.abspath(tool_test_path), |
921 os.path.abspath(tool_test_path), | 1016 "--galaxy_root", |
922 "--skip_venv", | 1017 self.args.galaxy_root, |
923 "--galaxy_root", | 1018 "--update_test_data", |
924 self.args.galaxy_root, | 1019 os.path.abspath(xreal), |
925 "--update_test_data", | 1020 ] |
926 os.path.abspath(xreal), | 1021 p = subprocess.run( |
927 ] | 1022 cll, |
928 p = subprocess.run( | 1023 shell=False, |
929 cll, | 1024 cwd=self.tooloutdir, |
930 env=self.ourenv, | 1025 stderr=tout, |
931 shell=False, | 1026 stdout=tout, |
932 cwd=self.tooloutdir, | 1027 ) |
933 stderr=dummy, | |
934 stdout=dummy, | |
935 ) | |
936 | |
937 else: | |
938 cll = [ | |
939 "planemo", | |
940 "test", | |
941 "--test_data", | |
942 os.path.abspath(self.testdir), | |
943 "--test_output", | |
944 os.path.abspath(tool_test_path), | |
945 "--skip_venv", | |
946 "--galaxy_root", | |
947 self.args.galaxy_root, | |
948 os.path.abspath(xreal), | |
949 ] | |
950 p = subprocess.run( | |
951 cll, | |
952 shell=False, | |
953 env=self.ourenv, | |
954 cwd=self.tooloutdir, | |
955 stderr=tout, | |
956 stdout=tout, | |
957 ) | |
958 tout.close() | 1028 tout.close() |
959 return p.returncode | 1029 return p.returncode |
960 | 1030 |
961 | 1031 |
962 def main(): | 1032 def main(): |
984 a("--tool_version", default=None) | 1054 a("--tool_version", default=None) |
985 a("--citations", default=None) | 1055 a("--citations", default=None) |
986 a("--command_override", default=None) | 1056 a("--command_override", default=None) |
987 a("--test_override", default=None) | 1057 a("--test_override", default=None) |
988 a("--additional_parameters", action="append", default=[]) | 1058 a("--additional_parameters", action="append", default=[]) |
1059 a("--selecttext_parameters", action="append", default=[]) | |
989 a("--edit_additional_parameters", action="store_true", default=False) | 1060 a("--edit_additional_parameters", action="store_true", default=False) |
990 a("--parampass", default="positional") | 1061 a("--parampass", default="positional") |
991 a("--tfout", default="./tfout") | 1062 a("--tfout", default="./tfout") |
992 a("--new_tool", default="new_tool") | 1063 a("--new_tool", default="new_tool") |
993 a("--galaxy_url", default="http://localhost:8080") | 1064 a("--galaxy_url", default="http://localhost:8080") |
996 # localhost != 127.0.0.1 so validation fails | 1067 # localhost != 127.0.0.1 so validation fails |
997 a("--toolshed_api_key", default="fakekey") | 1068 a("--toolshed_api_key", default="fakekey") |
998 a("--galaxy_api_key", default="fakekey") | 1069 a("--galaxy_api_key", default="fakekey") |
999 a("--galaxy_root", default="/galaxy-central") | 1070 a("--galaxy_root", default="/galaxy-central") |
1000 a("--galaxy_venv", default="/galaxy_venv") | 1071 a("--galaxy_venv", default="/galaxy_venv") |
1072 a("--collection", action="append", default=[]) | |
1073 a("--include_tests", default=False, action="store_true") | |
1001 args = parser.parse_args() | 1074 args = parser.parse_args() |
1002 assert not args.bad_user, ( | 1075 assert not args.bad_user, ( |
1003 'UNAUTHORISED: %s is NOT authorized to use this tool until Galaxy \ | 1076 'UNAUTHORISED: %s is NOT authorized to use this tool until Galaxy \ |
1004 admin adds %s to "admin_users" in the galaxy.yml Galaxy configuration file' | 1077 admin adds %s to "admin_users" in the galaxy.yml Galaxy configuration file' |
1005 % (args.bad_user, args.bad_user) | 1078 % (args.bad_user, args.bad_user) |
1007 assert args.tool_name, "## Tool Factory expects a tool name - eg --tool_name=DESeq" | 1080 assert args.tool_name, "## Tool Factory expects a tool name - eg --tool_name=DESeq" |
1008 assert ( | 1081 assert ( |
1009 args.sysexe or args.packages | 1082 args.sysexe or args.packages |
1010 ), "## Tool Factory wrapper expects an interpreter \ | 1083 ), "## Tool Factory wrapper expects an interpreter \ |
1011 or an executable package in --sysexe or --packages" | 1084 or an executable package in --sysexe or --packages" |
1012 args.input_files = [x.replace('"', "").replace("'", "") for x in args.input_files] | |
1013 # remove quotes we need to deal with spaces in CL params | |
1014 for i, x in enumerate(args.additional_parameters): | |
1015 args.additional_parameters[i] = args.additional_parameters[i].replace('"', "") | |
1016 r = ScriptRunner(args) | 1085 r = ScriptRunner(args) |
1017 r.writeShedyml() | 1086 r.writeShedyml() |
1018 r.makeTool() | 1087 r.makeTool() |
1019 if args.make_Tool == "generate": | 1088 if args.make_Tool == "generate": |
1020 retcode = r.run() | 1089 r.run() |
1021 r.moveRunOutputs() | 1090 r.moveRunOutputs() |
1022 r.makeToolTar() | 1091 r.makeToolTar() |
1023 else: | 1092 else: |
1024 retcode = r.planemo_test(genoutputs=True) # this fails :( - see PR | 1093 # r.planemo_test(genoutputs=True) # this fails :( - see PR |
1094 # r.moveRunOutputs() | |
1095 # r.makeToolTar(report_fail=False) | |
1096 r.planemo_test_once() | |
1025 r.moveRunOutputs() | 1097 r.moveRunOutputs() |
1026 r.makeToolTar() | 1098 r.makeToolTar(report_fail=True) |
1027 retcode = r.planemo_test(genoutputs=False) | |
1028 r.moveRunOutputs() | |
1029 r.makeToolTar() | |
1030 print(f"second planemo_test returned {retcode}") | |
1031 if args.make_Tool == "gentestinstall": | 1099 if args.make_Tool == "gentestinstall": |
1032 r.shedLoad() | 1100 r.shedLoad() |
1033 r.eph_galaxy_load() | 1101 r.eph_galaxy_load() |
1034 | 1102 |
1035 | 1103 |