comparison env/lib/python3.7/site-packages/planemo/bioc_tool_builder.py @ 0:26e78fe6e8c4 draft

"planemo upload commit c699937486c35866861690329de38ec1a5d9f783"
author shellac
date Sat, 02 May 2020 07:14:21 -0400
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:26e78fe6e8c4
1 """Tool builder for R-bioc tools."""
2
3 import os
4
5 import yaml
6
7 from planemo.conda_recipes import write_bioconda_recipe
8 from planemo.tool_builder import (
9 _find_command,
10 _handle_help,
11 _handle_tests,
12 _render,
13 _replace_file_in_command,
14 append_macro_file,
15 Input,
16 TestCase,
17 ToolDescription,
18 UrlCitation,
19 )
20
21
22 def build(**kwds):
23 """Build up a :func:`ToolDescription` from supplid arguments."""
24 test_case = TestCase()
25 command = _find_command(kwds)
26 # process raw cite urls
27 cite_urls = kwds.get("cite_url", [])
28 del kwds["cite_url"]
29 citations = map(UrlCitation, cite_urls)
30 kwds["bibtex_citations"] = citations
31
32 # process raw inputs
33 # inputs are in a list
34 inputs = kwds.get("input", [])
35 del kwds["input"]
36
37 # TODO: DEPRICATE HANDLING OF EXAMPLE INPUT
38 example_inputs = kwds["example_input"]
39 del kwds["example_input"]
40
41 rscript_data = kwds["rscript_data"]
42
43 # Rscript inputs
44 if bool(rscript_data):
45 input_dict = rscript_data.get('inputs') # dictionary of input parameters
46 inputs = input_dict.values()[0]
47
48 def edit_params(iodata):
49 return iodata.split("/")[-1]
50 inputs = map(edit_params, inputs)
51 param_set = inputs
52 inputs = list(map(Input, inputs or []))
53
54 # TODO: DEPRICATE HANDLING OF EXAMPLE INPUT
55 if not bool(rscript_data) and example_inputs:
56 '''If no Rscript data is found but example_inputs are given - this should not happen'''
57 for i, input_file in enumerate(example_inputs or []):
58 name = "input%d" % (i + 1)
59 inputs.append(Input(input_file, name=name))
60 test_case.params.append((name, input_file))
61 command = _replace_file_in_command(command, input_file, name)
62
63 # handle raw outputs (from_work_dir ones) as well as named_outputs
64 outputs = kwds.get("output", [])
65 del kwds["output"]
66
67 if bool(rscript_data):
68 output_dict = rscript_data.get('outputs')
69 outputs = output_dict.values()[0]
70 # Add all parameters to a list called param_set
71 outputs = map(edit_params, outputs)
72 param_set.extend(outputs)
73
74 outputs = list(map(Output, outputs or []))
75
76 named_outputs = kwds.get("named_output", [])
77 del kwds["named_output"]
78 for named_output in (named_outputs or []):
79 outputs.append(Output(name=named_output))
80
81 # DEPRICATED HANDLING OF EXAMPLE OUTPUT
82 # TODO: handle example outputs
83 # if kwds.get("example_ouput"):
84 # example_outputs = kwds["example_output"]
85 # del kwds["example_output"]
86
87 kwds['inputs'] = inputs
88 kwds["outputs"] = outputs
89
90 # handle requirements and containers
91 if bool(rscript_data):
92 if not type([rscript_data.get('library')]) is list:
93 kwds['requirements'] = [rscript_data.get('library')]
94 else:
95 kwds['requirements'] = rscript_data.get('library')
96 _handle_requirements(kwds)
97 # Add help from requirements
98 if not bool(rscript_data):
99 req = kwds['requirements'][0]
100 command_help = req.package_help + "\n \n" + req.package_url
101 kwds['help_text'] = command_help
102
103 # Handle help
104 _handle_help(kwds)
105
106 # Edit command before sending it into the kwds dictionary
107 command = _parse_command_rbioc(command, param_set)
108 kwds["command"] = command
109
110 # finally wrap up tests
111 tests, test_files = _handle_tests(kwds, test_case)
112 kwds["tests"] = tests
113
114 # Render tool content from template.
115 contents = _render(kwds)
116
117 tool_files = []
118 append_macro_file(tool_files, kwds)
119
120 return ToolDescription(
121 contents,
122 tool_files=tool_files,
123 test_files=test_files
124 )
125
126
127 def _parse_command_rbioc(command, param_set):
128 """
129 Parse command in Rbioc.
130
131 Find a r-bioc command and replace the inputs and
132 outputs with appropriate galaxy template.
133 """
134 cmd = command.split(" ")
135 count = 0
136 for i in range(len(cmd)):
137 if "--" in cmd[i]:
138 cmd[i + 1] = "$" + param_set[count].split(".")[0]
139 count = count + 1
140 return " ".join(cmd)
141
142
143 def _handle_requirements(kwds):
144 """Handle Requirements in R-Bioc tools.
145
146 Convert requirements specified from the command-line
147 into abstract format for consumption by the template.
148 """
149 requirements = kwds["requirements"]
150 # Handle Bioc/R requirements
151 if kwds.get('rversion') and kwds.get("requirements"):
152 rversion = kwds['rversion']
153 rversion = rversion.replace(" ", "@")
154 requirements.append(rversion)
155 requirements.reverse() # FIXME: Flips list so that R is the first in the requirements list
156 bioconda_path = kwds["bioconda_path"]
157 del kwds["requirements"]
158 requirements = requirements or []
159
160 requirements = [Requirement(req, bioconda_path=bioconda_path) for req in requirements]
161 kwds["requirements"] = requirements
162
163
164 class Output(object):
165 """Output class for R bioc tools."""
166
167 def __init__(self, from_path=None, name=None, use_from_path=False):
168 """Initialize Output class."""
169 if from_path:
170 parts = from_path.split(".")
171 name = name or parts[0]
172 if len(parts) > 1:
173 datatype = ".".join(parts[1:])
174 else:
175 datatype = "data"
176 else:
177 name = name
178 datatype = "data"
179
180 self.name = name
181 self.datatype = datatype
182 if use_from_path:
183 self.from_path = from_path
184 else:
185 self.from_path = None
186
187 def __str__(self):
188 """Method override str function in Output class."""
189 if self.from_path:
190 return self._from_path_str()
191 else:
192 return self._named_str()
193
194 def _from_path_str(self):
195 template = '<data name="{0}" format="{1}" from_work_dir="{2}" />'
196 return template.format(self.name, self.datatype, self.from_path)
197
198 def _named_str(self):
199 template = '<data name="{0}" format="{1}" />'
200 return template.format(self.name, self.datatype)
201
202
203 class Requirement(object):
204 """Requirements class for R-Bioc tools."""
205
206 def __init__(self, requirement, bioconda_path=None, update=False):
207 """Initialize Requirements class for Bioc tool builder."""
208 parts = requirement.split("@", 1)
209 # Get version from requirements, if version not given
210 if len(parts) > 1:
211 name = parts[0]
212 version = "@".join(parts[1:])
213 else:
214 name = parts[0]
215 version = None
216 if name == "R":
217 self.name = name
218 self.version = version
219 else:
220 # Write biconda recipe with given requirement
221 if bioconda_path is None:
222 bioconda_path = os.path.expanduser("~")
223 write_bioconda_recipe(name, True, update, bioconda_path)
224
225 recipe_path = os.path.join(bioconda_path,
226 "bioconda-recipes",
227 "recipes",
228 "bioconductor-" + name.lower(),
229 "meta.yaml")
230 if not os.path.exists(recipe_path):
231 recipe_path = os.path.join(bioconda_path,
232 "bioconda-recipes",
233 "recipes",
234 "r-" + name.lower(),
235 "meta.yaml")
236 with open(recipe_path, 'r') as f:
237 doc = yaml.safe_load(f)
238 if not version:
239 version = doc["package"]["version"]
240 package_url = doc["about"]["home"]
241 package_help = doc["about"]["summary"]
242 self.name = name
243 self.version = version
244 self.package_url = package_url
245 self.package_help = package_help
246
247 def __str__(self):
248 """Format requirements string with correct version and name."""
249 base = '<requirement type="package"{0}>{1}</requirement>'
250 if self.version is not None:
251 attrs = ' version="{0}"'.format(self.version)
252 else:
253 attrs = ''
254 return base.format(attrs, self.name)