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 |
