Mercurial > repos > fubar2 > toolfactory_gtn
comparison toolfactory/ToolFactory_tester.xml @ 0:f288fab71d8b draft default tip
Uploaded
author | fubar2 |
---|---|
date | Mon, 26 Apr 2021 04:18:54 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:f288fab71d8b |
---|---|
1 <tool name="toolfactory_tester" id="toolfactory_tester" version="1"> | |
2 <!--Source in git at: https://github.com/fubar2/toolfactory--> | |
3 <!--Created by admin@galaxy.org at 23/04/2021 10:25:58 using the Galaxy Tool Factory.--> | |
4 <description>Test an untested tool and update it</description> | |
5 <requirements> | |
6 <requirement type="package" version="2.30.2">git</requirement> | |
7 <requirement type="package" version="0.74.3">planemo</requirement> </requirements> | |
8 <stdio> | |
9 <exit_code range="1:" level="fatal"/> | |
10 </stdio> | |
11 <version_command><![CDATA[echo "1"]]></version_command> | |
12 <command><![CDATA[ | |
13 python | |
14 $runme | |
15 --in_tool_archive | |
16 $in_tool_archive | |
17 --new_tested_tool_archive | |
18 $new_tested_tool_archive | |
19 --galaxy_root | |
20 "$galaxyroot" | |
21 > | |
22 $tf_archive_tester_log; | |
23 ]]></command> | |
24 <configfiles> | |
25 <configfile name="runme"><![CDATA[#raw | |
26 | |
27 # see https://github.com/fubar2/toolfactory | |
28 # | |
29 # copyright ross lazarus (ross stop lazarus at gmail stop com) May 2012 | |
30 # | |
31 # all rights reserved | |
32 # Licensed under the LGPL | |
33 # suggestions for improvement and bug fixes welcome at | |
34 # https://github.com/fubar2/toolfactory | |
35 # | |
36 # July 2020: BCC was fun and I feel like rip van winkle after 5 years. | |
37 # Decided to | |
38 # 1. Fix the toolfactory so it works - done for simplest case | |
39 # 2. Fix planemo so the toolfactory function works | |
40 # 3. Rewrite bits using galaxyxml functions where that makes sense - done | |
41 | |
42 import argparse | |
43 import copy | |
44 import os | |
45 import subprocess | |
46 import shutil | |
47 import sys | |
48 import tarfile | |
49 import tempfile | |
50 import time | |
51 import xml.etree.ElementTree as ET | |
52 | |
53 | |
54 myversion = "V2.2 April 2021" | |
55 verbose = True | |
56 debug = True | |
57 toolFactoryURL = "https://github.com/fubar2/toolfactory" | |
58 | |
59 def timenow(): | |
60 """return current time as a string""" | |
61 return time.strftime("%d/%m/%Y %H:%M:%S", time.localtime(time.time())) | |
62 | |
63 class ToolTester(): | |
64 # requires highly insecure docker settings - like write to tool_conf.xml and to tools ! | |
65 # if in a container possibly not so courageous. | |
66 # Fine on your own laptop but security red flag for most production instances | |
67 # uncompress passed tar, run planemo and rebuild a new tarball with tests | |
68 | |
69 def __init__(self, args=None, in_tool_archive='/galaxy-central/tools/newtool/newtool_toolshed.gz', new_tool_archive=None): | |
70 self.args = args | |
71 self.new_tool_archive = new_tool_archive | |
72 assert tarfile.is_tarfile(in_tool_archive) | |
73 # this is not going to go well with arbitrary names. | |
74 tff = tarfile.open(in_tool_archive, "r:*") | |
75 flist = tff.getnames() | |
76 ourdir = os.path.commonpath(flist) # eg pyrevpos | |
77 self.tool_name = ourdir | |
78 ourxmls = [x for x in flist if x.lower().endswith('.xml') and os.path.split(x)[0] == ourdir] | |
79 # planemo_test/planemo_test.xml | |
80 assert len(ourxmls) > 0 | |
81 self.ourxmls = ourxmls # [os.path.join(tool_path,x) for x in ourxmls] | |
82 res = tff.extractall() | |
83 self.update_tests(ourdir) | |
84 tff.close() | |
85 self.tooloutdir = "./tfout" | |
86 self.repdir = "./TF_run_report" | |
87 self.testdir = os.path.join(self.tooloutdir, "test-data") | |
88 if not os.path.exists(self.tooloutdir): | |
89 os.mkdir(self.tooloutdir) | |
90 if not os.path.exists(self.testdir): | |
91 os.mkdir(self.testdir) | |
92 if not os.path.exists(self.repdir): | |
93 os.mkdir(self.repdir) | |
94 self.makeTool() | |
95 self.moveRunOutputs() | |
96 self.makeToolTar() | |
97 | |
98 def call_planemo(self,xmlpath,ourdir): | |
99 penv = os.environ | |
100 #penv['HOME'] = os.path.join(self.args.galaxy_root,'planemo') | |
101 #penv["GALAXY_VIRTUAL_ENV"] = os.path.join(penv['HOME'],'.planemo','gx_venv_3.9') | |
102 penv["PIP_CACHE_DIR"] = os.path.join(self.args.galaxy_root,'pipcache') | |
103 toolfile = os.path.split(xmlpath)[1] | |
104 tool_name = self.tool_name | |
105 tool_test_output = f"{tool_name}_planemo_test_report.html" | |
106 cll = [ | |
107 "planemo", | |
108 "test", | |
109 "--biocontainers", | |
110 "--test_output", | |
111 os.path.abspath(tool_test_output), | |
112 "--galaxy_root", | |
113 self.args.galaxy_root, | |
114 "--update_test_data", | |
115 os.path.abspath(xmlpath), | |
116 ] | |
117 print(cll) | |
118 p = subprocess.run( | |
119 cll, | |
120 #capture_output=True, | |
121 encoding='utf8', | |
122 env = penv, | |
123 shell=False, | |
124 ) | |
125 return p | |
126 | |
127 def makeTool(self): | |
128 """write xmls and input samples into place""" | |
129 for xreal in self.ourxmls: | |
130 x = os.path.split(xreal)[1] | |
131 xout = os.path.join(self.tooloutdir,x) | |
132 shutil.copyfile(xreal, xout) | |
133 # for p in self.infiles: | |
134 # pth = p["name"] | |
135 # dest = os.path.join(self.testdir, "%s_sample" % p["infilename"]) | |
136 # shutil.copyfile(pth, dest) | |
137 # dest = os.path.join(self.repdir, "%s_sample" % p["infilename"]) | |
138 # shutil.copyfile(pth, dest) | |
139 | |
140 def makeToolTar(self): | |
141 """move outputs into test-data and prepare the tarball""" | |
142 excludeme = "_planemo_test_report.html" | |
143 | |
144 def exclude_function(tarinfo): | |
145 filename = tarinfo.name | |
146 return None if filename.endswith(excludeme) else tarinfo | |
147 | |
148 newtar = 'new_%s_toolshed.gz' % self.tool_name | |
149 ttf = tarfile.open(newtar, "w:gz") | |
150 ttf.add(name=self.tool_name, | |
151 arcname=self.tool_name, | |
152 filter=exclude_function) | |
153 ttf.close() | |
154 shutil.copyfile(newtar, self.new_tool_archive) | |
155 | |
156 def moveRunOutputs(self): | |
157 """need to move planemo or run outputs into toolfactory collection""" | |
158 with os.scandir(self.tooloutdir) as outs: | |
159 for entry in outs: | |
160 if not entry.is_file(): | |
161 continue | |
162 if "." in entry.name: | |
163 _, ext = os.path.splitext(entry.name) | |
164 if ext in [".tgz", ".json"]: | |
165 continue | |
166 if ext in [".yml", ".xml", ".yaml"]: | |
167 newname = f"{entry.name.replace('.','_')}.txt" | |
168 else: | |
169 newname = entry.name | |
170 else: | |
171 newname = f"{entry.name}.txt" | |
172 dest = os.path.join(self.repdir, newname) | |
173 src = os.path.join(self.tooloutdir, entry.name) | |
174 shutil.copyfile(src, dest) | |
175 with os.scandir('.') as outs: | |
176 for entry in outs: | |
177 if not entry.is_file(): | |
178 continue | |
179 if "." in entry.name: | |
180 _, ext = os.path.splitext(entry.name) | |
181 if ext in [".yml", ".xml", ".yaml"]: | |
182 newname = f"{entry.name.replace('.','_')}.txt" | |
183 else: | |
184 newname = entry.name | |
185 else: | |
186 newname = f"{entry.name}.txt" | |
187 dest = os.path.join(self.repdir, newname) | |
188 src =entry.name | |
189 shutil.copyfile(src, dest) | |
190 if True or self.args.include_tests: | |
191 with os.scandir(self.testdir) as outs: | |
192 for entry in outs: | |
193 if (not entry.is_file()) or entry.name.endswith( | |
194 "_planemo_test_report.html" | |
195 ): | |
196 continue | |
197 if "." in entry.name: | |
198 _, ext = os.path.splitext(entry.name) | |
199 if ext in [".tgz", ".json"]: | |
200 continue | |
201 if ext in [".yml", ".xml", ".yaml"]: | |
202 newname = f"{entry.name.replace('.','_')}.txt" | |
203 else: | |
204 newname = entry.name | |
205 else: | |
206 newname = f"{entry.name}.txt" | |
207 dest = os.path.join(self.repdir, newname) | |
208 src = os.path.join(self.testdir, entry.name) | |
209 shutil.copyfile(src, dest) | |
210 | |
211 | |
212 def update_tests(self,ourdir): | |
213 for xmlf in self.ourxmls: | |
214 capture = self.call_planemo(xmlf,ourdir) | |
215 #sys.stderr.write('%s, stdout=%s, stderr=%s' % (xmlf, capture.stdout, capture.stdout)) | |
216 #print('%s, stdout=%s, stderr=%s' % (capture.stdout, capture.stdout,xmlf)) | |
217 | |
218 def main(): | |
219 """ | |
220 This is a Galaxy wrapper. | |
221 It expects to be called by a special purpose tool.xml | |
222 | |
223 """ | |
224 parser = argparse.ArgumentParser() | |
225 a = parser.add_argument | |
226 a("--in_tool_archive", default=None) | |
227 a("--new_tested_tool_archive", default=None) | |
228 a("--galaxy_root", default="/home/ross/gal21/") | |
229 args = parser.parse_args() | |
230 print('Hello from',os.getcwd()) | |
231 tt = ToolTester(args=args, in_tool_archive=args.in_tool_archive, new_tool_archive=args.new_tested_tool_archive) | |
232 | |
233 if __name__ == "__main__": | |
234 main() | |
235 | |
236 | |
237 #end raw]]></configfile> | |
238 </configfiles> | |
239 <inputs> | |
240 <param name="new_tool_name" value="" type="hidden"/> | |
241 <param name="in_tool_archive" type="data" optional="false" label="Select a no_test tarfile to test and update for a toolshed" help="" format="toolshed.gz" multiple="false"/> | |
242 <param name="galaxyroot" type="text" value="/home/ross/gal21" label="Galaxy root for planemo to use - MUST be made available in the Galaxy job runner configuration" help=""/> | |
243 </inputs> | |
244 <outputs> | |
245 <data name="new_tested_tool_archive" format="toolshed.gz" label="${in_tool_archive.name.split('_')[0]}_tested_toolshed.gz" hidden="false"/> | |
246 <data name="tf_archive_tester_log" format="txt" label="${in_tool_archive.name}_test_log" hidden="false"/> | |
247 <collection name="TF_run_report" type="list" label="${in_tool_archive.name} test Run reports"> | |
248 <discover_datasets pattern="__name_and_ext__" directory="TF_run_report" visible="false"/> | |
249 </collection> | |
250 </outputs> | |
251 <tests> | |
252 <test> | |
253 <output name="new_tested_tool_archive" value="new_tested_tool_archive_sample" compare="sim_size" delta_frac="0.5"/> | |
254 <output name="tf_archive_tester_log" value="tf_archive_tester_log_sample" compare="sim_size" delta_frac="0.1"/> | |
255 <param name="in_tool_archive" value="in_tool_archive_sample"/> | |
256 <param name="galaxyroot" value="/home/ross/gal21"/> | |
257 <output_collection name="TF_run_report"/> | |
258 </test> | |
259 </tests> | |
260 <help><![CDATA[ | |
261 | |
262 **What it Does** | |
263 | |
264 ------ | |
265 | |
266 Script:: | |
267 | |
268 import argparse | |
269 import copy | |
270 import os | |
271 import subprocess | |
272 import shutil | |
273 import sys | |
274 import tarfile | |
275 import tempfile | |
276 import time | |
277 import xml.etree.ElementTree as ET | |
278 myversion = "V2.2 April 2021" | |
279 verbose = True | |
280 debug = True | |
281 toolFactoryURL = "https://github.com/fubar2/toolfactory" | |
282 def timenow(): | |
283 """return current time as a string""" | |
284 return time.strftime("%d/%m/%Y %H:%M:%S", time.localtime(time.time())) | |
285 | |
286 class ToolTester(): | |
287 # requires highly insecure docker settings - like write to tool_conf.xml and to tools ! | |
288 # if in a container possibly not so courageous. | |
289 # Fine on your own laptop but security red flag for most production instances | |
290 # uncompress passed tar, run planemo and rebuild a new tarball with tests | |
291 def __init__(self, args=None, in_tool_archive='/galaxy-central/tools/newtool/newtool_toolshed.gz', new_tool_archive=None): | |
292 self.args = args | |
293 self.new_tool_archive = new_tool_archive | |
294 assert tarfile.is_tarfile(in_tool_archive) | |
295 # this is not going to go well with arbitrary names. | |
296 tff = tarfile.open(in_tool_archive, "r:*") | |
297 flist = tff.getnames() | |
298 ourdir = os.path.commonpath(flist) # eg pyrevpos | |
299 self.tool_name = ourdir | |
300 ourxmls = [x for x in flist if x.lower().endswith('.xml') and os.path.split(x)[0] == ourdir] | |
301 # planemo_test/planemo_test.xml | |
302 assert len(ourxmls) > 0 | |
303 self.ourxmls = ourxmls # [os.path.join(tool_path,x) for x in ourxmls] | |
304 res = tff.extractall() | |
305 self.update_tests(ourdir) | |
306 tff.close() | |
307 self.tooloutdir = "./tfout" | |
308 self.repdir = "./TF_run_report" | |
309 self.testdir = os.path.join(self.tooloutdir, "test-data") | |
310 if not os.path.exists(self.tooloutdir): | |
311 os.mkdir(self.tooloutdir) | |
312 if not os.path.exists(self.testdir): | |
313 os.mkdir(self.testdir) | |
314 if not os.path.exists(self.repdir): | |
315 os.mkdir(self.repdir) | |
316 self.makeTool() | |
317 self.moveRunOutputs() | |
318 self.makeToolTar() | |
319 | |
320 def call_planemo(self,xmlpath,ourdir): | |
321 penv = os.environ | |
322 penv['HOME'] = '/home/ross/galaxy-release_21.01' | |
323 toolfile = os.path.split(xmlpath)[1] | |
324 tool_name = self.tool_name | |
325 tool_test_output = f"{tool_name}_planemo_test_report.html" | |
326 cll = [ | |
327 "planemo", | |
328 "test", | |
329 "--test_output", | |
330 os.path.abspath(tool_test_output), | |
331 "--galaxy_root", | |
332 self.args.galaxy_root, | |
333 "--update_test_data", | |
334 os.path.abspath(xmlpath), | |
335 ] | |
336 print(cll) | |
337 p = subprocess.run( | |
338 cll, | |
339 capture_output=True, | |
340 encoding='utf8', | |
341 env = penv, | |
342 shell=False, | |
343 ) | |
344 return p | |
345 | |
346 def makeTool(self): | |
347 """write xmls and input samples into place""" | |
348 for xreal in self.ourxmls: | |
349 x = os.path.split(xreal)[1] | |
350 xout = os.path.join(self.tooloutdir,x) | |
351 shutil.copyfile(xreal, xout) | |
352 # for p in self.infiles: | |
353 # pth = p["name"] | |
354 # dest = os.path.join(self.testdir, "%s_sample" % p["infilename"]) | |
355 # shutil.copyfile(pth, dest) | |
356 # dest = os.path.join(self.repdir, "%s_sample" % p["infilename"]) | |
357 # shutil.copyfile(pth, dest) | |
358 | |
359 def makeToolTar(self): | |
360 """move outputs into test-data and prepare the tarball""" | |
361 excludeme = "_planemo_test_report.html" | |
362 def exclude_function(tarinfo): | |
363 filename = tarinfo.name | |
364 return None if filename.endswith(excludeme) else tarinfo | |
365 newtar = 'new_%s_toolshed.gz' % self.tool_name | |
366 ttf = tarfile.open(newtar, "w:gz") | |
367 ttf.add(name=self.tooloutdir, | |
368 arcname=self.tool_name, | |
369 filter=exclude_function) | |
370 ttf.close() | |
371 shutil.copyfile(newtar, self.new_tool_archive) | |
372 | |
373 def moveRunOutputs(self): | |
374 """need to move planemo or run outputs into toolfactory collection""" | |
375 with os.scandir(self.tooloutdir) as outs: | |
376 for entry in outs: | |
377 if not entry.is_file(): | |
378 continue | |
379 if "." in entry.name: | |
380 _, ext = os.path.splitext(entry.name) | |
381 if ext in [".tgz", ".json"]: | |
382 continue | |
383 if ext in [".yml", ".xml", ".yaml"]: | |
384 newname = f"{entry.name.replace('.','_')}.txt" | |
385 else: | |
386 newname = entry.name | |
387 else: | |
388 newname = f"{entry.name}.txt" | |
389 dest = os.path.join(self.repdir, newname) | |
390 src = os.path.join(self.tooloutdir, entry.name) | |
391 shutil.copyfile(src, dest) | |
392 with os.scandir('.') as outs: | |
393 for entry in outs: | |
394 if not entry.is_file(): | |
395 continue | |
396 if "." in entry.name: | |
397 _, ext = os.path.splitext(entry.name) | |
398 if ext in [".yml", ".xml", ".yaml"]: | |
399 newname = f"{entry.name.replace('.','_')}.txt" | |
400 else: | |
401 newname = entry.name | |
402 else: | |
403 newname = f"{entry.name}.txt" | |
404 dest = os.path.join(self.repdir, newname) | |
405 src =entry.name | |
406 shutil.copyfile(src, dest) | |
407 if True or self.args.include_tests: | |
408 with os.scandir(self.testdir) as outs: | |
409 for entry in outs: | |
410 if (not entry.is_file()) or entry.name.endswith( | |
411 "_planemo_test_report.html" | |
412 ): | |
413 continue | |
414 if "." in entry.name: | |
415 _, ext = os.path.splitext(entry.name) | |
416 if ext in [".tgz", ".json"]: | |
417 continue | |
418 if ext in [".yml", ".xml", ".yaml"]: | |
419 newname = f"{entry.name.replace('.','_')}.txt" | |
420 else: | |
421 newname = entry.name | |
422 else: | |
423 newname = f"{entry.name}.txt" | |
424 dest = os.path.join(self.repdir, newname) | |
425 src = os.path.join(self.testdir, entry.name) | |
426 shutil.copyfile(src, dest) | |
427 | |
428 def update_tests(self,ourdir): | |
429 for xmlf in self.ourxmls: | |
430 capture = self.call_planemo(xmlf,ourdir) | |
431 #sys.stderr.write('%s, stdout=%s, stderr=%s' % (xmlf, capture.stdout, capture.stdout)) | |
432 print('%s, stdout=%s, stderr=%s' % (capture.stdout, capture.stdout,xmlf)) | |
433 | |
434 def main(): | |
435 """ | |
436 This is a Galaxy wrapper. | |
437 It expects to be called by a special purpose tool.xml | |
438 """ | |
439 parser = argparse.ArgumentParser() | |
440 a = parser.add_argument | |
441 a("--in_tool_archive", default=None) | |
442 a("--new_tested_tool_archive", default=None) | |
443 a("--galaxy_root", default="/home/ross/gal21/") | |
444 args = parser.parse_args() | |
445 print('Hello from',os.getcwd()) | |
446 tt = ToolTester(args=args, in_tool_archive=args.in_tool_archive, new_tool_archive=args.new_tested_tool_archive) | |
447 if __name__ == "__main__": | |
448 main() | |
449 | |
450 ]]></help> | |
451 <citations> | |
452 <citation type="doi">10.1093/bioinformatics/bts573</citation> | |
453 </citations> | |
454 </tool> | |
455 |