annotate toolfactory/ToolFactory_tester.xml @ 0:f288fab71d8b draft default tip

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