Mercurial > repos > bcclaywell > argo_navis
comparison venv/lib/python2.7/site-packages/planemo/shed2tap/base.py @ 0:d67268158946 draft
planemo upload commit a3f181f5f126803c654b3a66dd4e83a48f7e203b
author | bcclaywell |
---|---|
date | Mon, 12 Oct 2015 17:43:33 -0400 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:d67268158946 |
---|---|
1 from __future__ import print_function | |
2 | |
3 from xml.etree import ElementTree | |
4 | |
5 from six.moves.urllib.request import urlretrieve | |
6 from six.moves.urllib.error import URLError | |
7 from six import string_types | |
8 | |
9 import os | |
10 import tarfile | |
11 import zipfile | |
12 from ftplib import all_errors as FTPErrors # tuple of exceptions | |
13 | |
14 TOOLSHED_MAP = { | |
15 "toolshed": "https://toolshed.g2.bx.psu.edu", | |
16 "testtoolshed": "https://testtoolshed.g2.bx.psu.edu", | |
17 } | |
18 | |
19 | |
20 class Dependencies(object): | |
21 """ Base class for parsing Tool Shed dependency files. | |
22 """ | |
23 | |
24 def __init__( | |
25 self, | |
26 dependencies_file, | |
27 repo=None, | |
28 package_factory=None, | |
29 ): | |
30 if package_factory is None: | |
31 package_factory = BasePackage | |
32 self.repo = repo | |
33 self.root = ElementTree.parse(dependencies_file).getroot() | |
34 packages = [] | |
35 dependencies = [] | |
36 package_els = self.root.findall("package") | |
37 assert package_els is not None | |
38 for package_el in package_els: | |
39 install_els = package_el.findall("install") | |
40 readme_els = package_el.findall("readme") | |
41 if len(readme_els) > 0: | |
42 readme = readme_els[0].text | |
43 else: | |
44 readme = None | |
45 assert len(install_els) in (0, 1) | |
46 if len(install_els) == 1: | |
47 install_el = install_els[0] | |
48 package = package_factory( | |
49 self, | |
50 package_el, | |
51 install_el, | |
52 readme=readme | |
53 ) | |
54 packages.append(package) | |
55 else: | |
56 repository_el = package_el.find("repository") | |
57 if repository_el is None: | |
58 message = "no repository in package el for %s" % repo | |
59 raise AssertionError(message) | |
60 dependency = Dependency(self, package_el, repository_el) | |
61 dependencies.append(dependency) | |
62 | |
63 self.packages = packages | |
64 self.dependencies = dependencies | |
65 | |
66 def single_package(self): | |
67 return len(self.packages) == 1 | |
68 | |
69 def __repr__(self): | |
70 return "Dependencies[for_repo=%s]" % self.repo | |
71 | |
72 | |
73 class Repo(object): | |
74 | |
75 def __init__(self, **kwds): | |
76 for key, value in kwds.iteritems(): | |
77 setattr(self, key, value) | |
78 | |
79 def recipe_base_name(self): | |
80 owner = self.owner.replace("-", "") | |
81 name = self.name | |
82 name = name.replace("_", "").replace("-", "") | |
83 base = "%s_%s" % (owner, name) | |
84 return base | |
85 | |
86 @staticmethod | |
87 def from_xml(elem): | |
88 tool_shed_url = elem.attrib.get("toolshed", None) | |
89 if tool_shed_url and ("testtoolshed" in tool_shed_url): | |
90 prefix = "testtoolshed" | |
91 else: | |
92 prefix = "toolshed" | |
93 prior = elem.attrib.get("prior_installation_required", False) | |
94 return Repo( | |
95 prefix=prefix, | |
96 name=elem.attrib["name"], | |
97 owner=elem.attrib["owner"], | |
98 tool_shed_url=tool_shed_url, | |
99 changeset_revision=elem.attrib.get("changeset_revision", None), | |
100 prior_installation_required=prior, | |
101 ) | |
102 | |
103 @staticmethod | |
104 def from_api(prefix, repo_json): | |
105 return Repo( | |
106 prefix=prefix, | |
107 name=repo_json["name"], | |
108 owner=repo_json["owner"], | |
109 tool_shed_url=TOOLSHED_MAP[prefix], | |
110 ) | |
111 | |
112 def get_file(self, path): | |
113 try: | |
114 url_template = "%s/repos/%s/%s/raw-file/tip/%s" | |
115 url = url_template % ( | |
116 self.tool_shed_url, | |
117 self.owner, | |
118 self.name, | |
119 path | |
120 ) | |
121 path, headers = urlretrieve(url) | |
122 return path | |
123 except Exception as e: | |
124 print(e) | |
125 return None | |
126 | |
127 def __repr__(self): | |
128 return "Repository[name=%s,owner=%s]" % (self.name, self.owner) | |
129 | |
130 | |
131 class Dependency(object): | |
132 | |
133 def __init__(self, dependencies, package_el, repository_el): | |
134 self.dependencies = dependencies | |
135 self.package_el = package_el | |
136 self.repository_el = repository_el | |
137 self.repo = Repo.from_xml(repository_el) | |
138 | |
139 def __repr__(self): | |
140 temp = "Dependency[package_name=%s,version=%s,dependent_package=%s]" | |
141 return temp % ( | |
142 self.package_el.attrib["name"], | |
143 self.package_el.attrib["version"], | |
144 self.repository_el.attrib["name"] | |
145 ) | |
146 | |
147 | |
148 class BasePackage(object): | |
149 | |
150 def __init__(self, dependencies, package_el, install_el, readme): | |
151 self.dependencies = dependencies | |
152 self.package_el = package_el | |
153 self.install_el = install_el | |
154 self.readme = readme | |
155 self.all_actions = self.get_all_actions() | |
156 self.no_arch_option = self.has_no_achitecture_install() | |
157 | |
158 def get_all_actions(self): | |
159 action_or_group = self.install_el[0] | |
160 parsed_actions = [] | |
161 if action_or_group.tag == "actions": | |
162 parsed_actions.append(self.parse_actions(action_or_group)) | |
163 elif action_or_group.tag == "actions_group": | |
164 actions_els = action_or_group.findall("actions") | |
165 assert actions_els is not None | |
166 for actions in actions_els: | |
167 parsed_actions.append(self.parse_actions(actions)) | |
168 action_els = action_or_group.findall("action") | |
169 assert action_els is not None | |
170 for action in action_els: | |
171 for parsed_a in parsed_actions: | |
172 parsed_a.actions.append(self.parse_action(action)) | |
173 return parsed_actions | |
174 | |
175 def has_no_achitecture_install(self): | |
176 all_actions = self.all_actions | |
177 if len(all_actions) < 2: | |
178 return False | |
179 else: | |
180 last_action = all_actions[-1] | |
181 return (not last_action.architecture) and (not last_action.os) | |
182 | |
183 def has_explicit_set_environments(self): | |
184 all_actions = self.all_actions | |
185 for actions in all_actions: | |
186 for action in actions.actions: | |
187 if action.explicit_variables: | |
188 return True | |
189 return False | |
190 | |
191 def has_multiple_set_environments(self): | |
192 all_actions = self.all_actions | |
193 for actions in all_actions: | |
194 count = 0 | |
195 for action in actions.actions: | |
196 if action.explicit_variables: | |
197 count += 1 | |
198 if count > 1: | |
199 return True | |
200 return False | |
201 | |
202 def parse_actions(self, actions): | |
203 os = actions.attrib.get("os", None) | |
204 architecture = actions.get("architecture", None) | |
205 action_els = actions.findall("action") | |
206 assert action_els is not None | |
207 parsed_actions = map(self.parse_action, action_els) | |
208 action_packages = [] | |
209 for package in actions.findall("package"): | |
210 action_packages.append(self.parse_action_package(package)) | |
211 return Actions(parsed_actions, os, architecture, action_packages) | |
212 | |
213 def parse_action_package(self, elem): | |
214 name = elem.attrib["name"] | |
215 version = elem.attrib["version"] | |
216 repo = Repo.from_xml(elem.find("repository")) | |
217 return ActionPackage(name, version, repo) | |
218 | |
219 def parse_action(self, action): | |
220 return BaseAction.from_elem(action, package=self) | |
221 | |
222 def __repr__(self): | |
223 actions = self.all_actions | |
224 parts = ( | |
225 self.package_el.attrib["name"], | |
226 self.package_el.attrib["version"], | |
227 self.dependencies, | |
228 actions | |
229 ) | |
230 template = "Install[name=%s,version=%s,dependencies=%s,actions=%s]" | |
231 return template % parts | |
232 | |
233 | |
234 class Actions(object): | |
235 | |
236 def __init__( | |
237 self, | |
238 actions, | |
239 os=None, | |
240 architecture=None, | |
241 action_packages=[] | |
242 ): | |
243 self.os = os | |
244 self.architecture = architecture | |
245 self.actions = actions or [] | |
246 self.action_packages = action_packages | |
247 | |
248 def first_download(self): | |
249 for action in self.actions: | |
250 if action.action_type in ["download_by_url", "download_file"]: | |
251 return action | |
252 return None | |
253 | |
254 def downloads(self): | |
255 actions = [] | |
256 for action in self.actions: | |
257 if action.action_type in ["download_by_url", "download_file"]: | |
258 actions.append(action) | |
259 return actions | |
260 | |
261 def __repr__(self): | |
262 platform = "" | |
263 if self.os or self.architecture: | |
264 platform = "os=%s,arch=%s," % (self.os, self.architecture) | |
265 return "Actions[%s%s]" % (platform, map(str, self.actions)) | |
266 | |
267 def _indent_extend(self, target, new_entries, indent=" "): | |
268 for line in new_entries: | |
269 target.append(indent + line) | |
270 | |
271 def to_bash(self): | |
272 # Use self.os.title() to match "Linux" or "Darwin" in bash where case matters: | |
273 if self.os and self.architecture: | |
274 condition = '("%s" == `uname`) && ("%s" == `arch`)' % (self.os.title(), self.architecture) | |
275 elif self.os: | |
276 condition = '"%s" == `uname`' % self.os.title() | |
277 elif self.architecture: | |
278 condition = '"%s" == `arch`' % self.architecture | |
279 else: | |
280 condition = None | |
281 | |
282 install_cmds = [] | |
283 env_cmds = [] | |
284 | |
285 if condition: | |
286 # Conditional actions block | |
287 install_cmds = [ | |
288 '#' + '-' * 60, | |
289 'if [[ $specifc_action_done == 0 && %s ]]' % condition, | |
290 'then', | |
291 ' echo "Platform-specific action for os=%s, arch=%s"' % (self.os, self.architecture)] | |
292 env_cmds = install_cmds[:] | |
293 # TODO - Refactor block indentation? | |
294 for action in self.actions: | |
295 i_cmds, e_cmds = action.to_bash() | |
296 self._indent_extend(install_cmds, i_cmds) | |
297 self._indent_extend(env_cmds, e_cmds) | |
298 # If we run the action, do not want to run any later actions! | |
299 install_cmds.extend([' specifc_action_done=1', 'fi']) | |
300 env_cmds.extend([' specifc_action_done=1', 'fi']) | |
301 else: | |
302 # Non-specific default action... | |
303 install_cmds = [ | |
304 '#' + '-' * 60, | |
305 'if [[ $specifc_action_done == 0 ]]', | |
306 'then', | |
307 ' echo "Non-platform-specific actions"'] | |
308 env_cmds = install_cmds[:] | |
309 for action in self.actions: | |
310 i_cmds, e_cmds = action.to_bash() | |
311 self._indent_extend(install_cmds, i_cmds) | |
312 self._indent_extend(env_cmds, e_cmds) | |
313 install_cmds.append('fi') | |
314 env_cmds.append('fi') | |
315 return install_cmds, env_cmds | |
316 | |
317 | |
318 class ActionPackage(object): | |
319 | |
320 def __init__(self, name, version, repo): | |
321 self.name = name | |
322 self.version = version | |
323 self.repo = repo | |
324 | |
325 | |
326 class BaseAction(object): | |
327 | |
328 def __repr__(self): | |
329 return "Action[type=%s]" % self.action_type | |
330 | |
331 def same_as(self, other): | |
332 if self._keys != other._keys: | |
333 return False | |
334 else: | |
335 for key in self._keys: | |
336 if getattr(self, key) != getattr(other, key): | |
337 return False | |
338 | |
339 return True | |
340 | |
341 def parse_action_repo(self, elem): | |
342 repo_elem = elem.find("repository") | |
343 repo = Repo.from_xml(repo_elem) | |
344 self.repo = repo | |
345 | |
346 def parse_package_elems(self, elem): | |
347 package_els = elem.findall("package") | |
348 packages = [] | |
349 assert package_els is not None | |
350 for package_el in package_els: | |
351 packages.append(package_el.text) | |
352 self.packages = packages | |
353 | |
354 @classmethod | |
355 def from_elem(cls, elem, package): | |
356 type = elem.attrib["type"] | |
357 action_class = actions_by_type[type] | |
358 return action_class(elem) | |
359 | |
360 def to_bash(self): | |
361 """Return lists of bash shell commands to execute this action. | |
362 | |
363 This method is be implemented by each sub-class, and will | |
364 return two list of strings (for ``dep_install.sh`` and | |
365 ``env.sh`` respectively). | |
366 """ | |
367 raise NotImplementedError("No to_bash defined for %r" % self) | |
368 | |
369 | |
370 def _tar_folders(filename): | |
371 archive = tarfile.open(filename, "r", errorlevel=0) | |
372 folders = set() | |
373 for i in archive.getmembers(): | |
374 if i.isdir(): | |
375 folders.add(i.name.rstrip("/")) | |
376 else: | |
377 folders.add(os.path.split(i.name)[0]) | |
378 return folders | |
379 | |
380 | |
381 def _zip_folders(filename): | |
382 archive = zipfile.ZipFile(filename, "r") | |
383 return set(i.filename.rstrip("/") for i in archive.infolist() if i.filename.endswith("/")) | |
384 | |
385 | |
386 def _common_prefix(folders): | |
387 common_prefix = "" | |
388 if len(folders) == 1: | |
389 common_prefix = list(folders)[0] | |
390 else: | |
391 common_prefix = os.path.commonprefix(folders) | |
392 assert not os.path.isabs(common_prefix), folders | |
393 return common_prefix | |
394 | |
395 | |
396 def _cache_download(url, filename): | |
397 """Returns local path to cached copy of URL using given filename.""" | |
398 try: | |
399 cache = os.environ["DOWNLOAD_CACHE"] | |
400 except KeyError: | |
401 # TODO - expose this as a command line option | |
402 raise ValueError("Dependencies cache location $DOWNLOAD_CACHE not set.") | |
403 | |
404 local = os.path.join(cache, filename) | |
405 | |
406 if not os.path.isfile(local): | |
407 # Must download it... | |
408 try: | |
409 import sys # TODO - log this nicely... | |
410 sys.stderr.write("Downloading %s\n" % url) | |
411 urlretrieve(url, local) | |
412 except URLError: | |
413 # Most likely server is down, could be bad URL in XML action: | |
414 raise RuntimeError("Unable to download %s" % url) | |
415 except FTPErrors: | |
416 # Most likely server is down, could be bad URL in XML action: | |
417 raise RuntimeError("Unable to download %s" % url) | |
418 | |
419 return local | |
420 | |
421 | |
422 def _determine_compressed_file_folder(url, downloaded_filename): | |
423 """Determine how to decompress the file & its directory structure. | |
424 | |
425 Returns a list of shell commands. Consider this example where the | |
426 folder to change to cannot be guessed from the tar-ball filename: | |
427 | |
428 $ curl -o "ncbi-blast-2.2.30+-ia32-linux.tar.gz" \ | |
429 "ftp://ftp.ncbi.nlm.nih.gov/blast/executables/blast+/2.2.30/ncbi-blast-2.2.30+-ia32-linux.tar.gz" | |
430 $ tar -zxvf ncbi-blast-2.2.30+-ia32-linux.tar.gz | |
431 $ cd ncbi-blast-2.2.30+ | |
432 | |
433 Here it would return: | |
434 | |
435 ['tar -zxvf ncbi-blast-2.2.30+-ia32-linux.tar.gz', 'cd ncbi-blast-2.2.30+'] | |
436 | |
437 If not cached, this function will download the file to the | |
438 $DOWNLOAD_CACHE folder, and then open it / decompress it in | |
439 order to find common folder prefix used. This will also verify | |
440 how to decompress the file. | |
441 """ | |
442 answer = [] | |
443 local = _cache_download(url, downloaded_filename) | |
444 | |
445 if tarfile.is_tarfile(local): | |
446 folders = _tar_folders(local) | |
447 if downloaded_filename.endswith(".tar.gz") or downloaded_filename.endswith(".tgz"): | |
448 answer.append('tar -zxvf %s' % downloaded_filename) | |
449 elif downloaded_filename.endswith(".tar.bz2"): | |
450 answer.append('tar -jxvf %s' % downloaded_filename) | |
451 elif downloaded_filename.endswith(".tar"): | |
452 answer.extend('tar -xvf %s' % downloaded_filename) | |
453 else: | |
454 # Quite possibly this file doesn't need decompressing, | |
455 # but until we've tested lots of real world tool_dependencies.xml | |
456 # files I'd like to check these cases to confirm this. | |
457 raise NotImplementedError("How to decompress tar file %s?" % downloaded_filename) | |
458 elif zipfile.is_zipfile(local): | |
459 if local.endswith('.jar'): | |
460 # Do not decompress! | |
461 return answer | |
462 folders = _zip_folders(local) | |
463 answer.append('unzip %s' % downloaded_filename) | |
464 elif downloaded_filename.endswith(".dmg"): | |
465 # Do not decompress! | |
466 return answer | |
467 else: | |
468 # No compression? Leave as it is? | |
469 raise NotImplementedError("What kind of compression is %s using?" % local) | |
470 | |
471 common_prefix = _common_prefix(folders) | |
472 if common_prefix: | |
473 answer.append('cd "%s"' % common_prefix) | |
474 | |
475 return answer | |
476 | |
477 | |
478 def _commands_to_download_and_extract(url, target_filename=None): | |
479 # TODO - Include checksum validation here? | |
480 if target_filename: | |
481 downloaded_filename = target_filename | |
482 else: | |
483 downloaded_filename = os.path.split(url)[-1] | |
484 if "?" in downloaded_filename: | |
485 downloaded_filename = downloaded_filename[:downloaded_filename.index("?")] | |
486 if "#" in downloaded_filename: | |
487 downloaded_filename = downloaded_filename[:downloaded_filename.index("#")] | |
488 | |
489 # Curl is present on Mac OS X, can we assume it will be on Linux? | |
490 # Cannot assume that wget will be on Mac OS X. | |
491 answer = [ | |
492 'if [[ -f "%s" ]]' % downloaded_filename, | |
493 'then', | |
494 ' echo "Reusing existing %s"' % downloaded_filename, | |
495 'elif [[ -f "$DOWNLOAD_CACHE/%s" ]]' % downloaded_filename, | |
496 'then', | |
497 ' echo "Reusing cached %s"' % downloaded_filename, | |
498 ' ln -s "$DOWNLOAD_CACHE/%s" "%s"' % (downloaded_filename, downloaded_filename), | |
499 'else', | |
500 ' echo "Downloading %s"' % downloaded_filename, | |
501 ' curl -L -o "$DOWNLOAD_CACHE/%s" "%s"' % (downloaded_filename, url), | |
502 ' ln -s "$DOWNLOAD_CACHE/%s" "%s"' % (downloaded_filename, downloaded_filename), | |
503 'fi', | |
504 ] | |
505 answer.extend(_determine_compressed_file_folder(url, downloaded_filename)) | |
506 return answer, [] | |
507 | |
508 | |
509 class DownloadByUrlAction(BaseAction): | |
510 action_type = "download_by_url" | |
511 _keys = ["url"] | |
512 | |
513 def __init__(self, elem): | |
514 self.url = elem.text.strip() | |
515 assert self.url | |
516 | |
517 def to_bash(self): | |
518 # See class DownloadByUrl in Galaxy, | |
519 # lib/tool_shed/galaxy_install/tool_dependencies/recipe/step_handler.py | |
520 # Do we need to worry about target_filename here? | |
521 return _commands_to_download_and_extract(self.url) | |
522 | |
523 | |
524 class DownloadFileAction(BaseAction): | |
525 action_type = "download_file" | |
526 _keys = ["url", "extract"] | |
527 | |
528 def __init__(self, elem): | |
529 self.url = elem.text.strip() | |
530 self.extract = asbool(elem.attrib.get("extract", False)) | |
531 | |
532 def to_bash(self): | |
533 if self.extract: | |
534 return _commands_to_download_and_extract(self.url) | |
535 else: | |
536 return ['wget %s' % self.url], [] | |
537 | |
538 | |
539 class DownloadBinary(BaseAction): | |
540 action_type = "download_binary" | |
541 _keys = ["url_template", "target_directory"] | |
542 | |
543 def __init__(self, elem): | |
544 self.url_template = elem.text | |
545 assert self.url_template | |
546 self.target_directory = elem.get('target_directory', None) | |
547 | |
548 | |
549 class ShellCommandAction(BaseAction): | |
550 action_type = "shell_command" | |
551 _keys = ["command"] | |
552 | |
553 def __init__(self, elem): | |
554 self.command = elem.text | |
555 | |
556 def to_bash(self): | |
557 return [self.command], [] | |
558 | |
559 | |
560 class TemplateShellCommandAction(BaseAction): | |
561 action_type = "template_command" | |
562 _keys = ["language", "command"] | |
563 | |
564 def __init__(self, elem): | |
565 self.command = elem.text | |
566 self.language = elem.get('language', 'cheetah').lower() | |
567 assert self.command | |
568 assert self.language == "cheetah" | |
569 | |
570 | |
571 class MoveFileAction(BaseAction): | |
572 action_type = "move_file" | |
573 _keys = ["move_file"] | |
574 | |
575 def __init__(self, elem): | |
576 self.source = elem.find("source").text | |
577 self.destination = elem.find("destination").text | |
578 | |
579 def to_bash(self): | |
580 return ["mv %s %s" % (self.source, self.destination)], [] | |
581 | |
582 | |
583 class MoveDirectoryFilesAction(BaseAction): | |
584 action_type = "move_directory_files" | |
585 _keys = ["source_directory", "destination_directory"] | |
586 | |
587 def __init__(self, elem): | |
588 source_directory = elem.find("source_directory").text | |
589 destination_directory = elem.find("destination_directory").text | |
590 self.source_directory = source_directory | |
591 self.destination_directory = destination_directory | |
592 | |
593 def to_bash(self): | |
594 return ["mv %s/* %s/" % (self.source_directory, self.destination_directory)], [] | |
595 | |
596 | |
597 class SetEnvironmentAction(BaseAction): | |
598 action_type = "set_environment" | |
599 _keys = ["variables"] | |
600 | |
601 def __init__(self, elem): | |
602 variables = [] | |
603 var_els = elem.findall("environment_variable") | |
604 assert var_els is not None | |
605 for ev_elem in var_els: | |
606 var = SetVariable(ev_elem) | |
607 variables.append(var) | |
608 self.variables = variables | |
609 assert self.variables | |
610 | |
611 def to_bash(self): | |
612 answer = [] | |
613 for var in self.variables: | |
614 # Expand $INSTALL_DIR here? | |
615 if var.action == "set_to": | |
616 answer.append('export %s=%s' % (var.name, var.raw_value)) | |
617 elif var.action == "prepend_to": | |
618 answer.append('export %s=%s:$%s' % (var.name, var.raw_value, var.name)) | |
619 elif var.action == "append_to": | |
620 answer.append('export %s=$%s:%s' % (var.name, var.name, var.raw_value)) | |
621 else: | |
622 raise ValueError("Undefined environment variable action %r" % var.action) | |
623 return answer, answer # Actions needed in env.sh here! | |
624 | |
625 | |
626 class ChmodAction(BaseAction): | |
627 action_type = "chmod" | |
628 _keys = ["mods"] | |
629 | |
630 def __init__(self, elem): | |
631 mods = [] | |
632 file_els = elem.findall("file") | |
633 assert file_els is not None | |
634 for mod_elem in file_els: | |
635 mod = {} | |
636 mod["mode"] = mod_elem.attrib["mode"] | |
637 mod["target"] = mod_elem.text | |
638 mods.append(mod) | |
639 self.mods = mods | |
640 assert self.mods | |
641 | |
642 def to_bash(self): | |
643 return ["chmod %s %s" % (m["mode"], m["target"]) for m in self.mods], [] | |
644 | |
645 | |
646 class MakeInstallAction(BaseAction): | |
647 action_type = "make_install" | |
648 _keys = [] | |
649 | |
650 def __init__(self, elem): | |
651 pass | |
652 | |
653 def to_bash(self): | |
654 return ["make install"], [] | |
655 | |
656 | |
657 class AutoconfAction(BaseAction): | |
658 action_type = "autoconf" | |
659 _keys = ["options"] | |
660 | |
661 def __init__(self, elem): | |
662 self.options = elem.text | |
663 | |
664 def to_bash(self): | |
665 if self.options: | |
666 raise NotImplementedError("Options with action autoconf not implemented yet.") | |
667 return ['./configure', 'make', 'make install'], [] | |
668 | |
669 | |
670 class ChangeDirectoryAction(BaseAction): | |
671 action_type = "change_directory" | |
672 _keys = ["directory"] | |
673 | |
674 def __init__(self, elem): | |
675 self.directory = elem.text | |
676 assert self.directory | |
677 | |
678 def to_bash(self): | |
679 return ["cd %s" % self.directory], [] | |
680 | |
681 | |
682 class MakeDirectoryAction(BaseAction): | |
683 action_type = "make_directory" | |
684 _keys = ["directory"] | |
685 | |
686 def __init__(self, elem): | |
687 self.directory = elem.text | |
688 | |
689 def to_bash(self): | |
690 return ["mkdir -p %s" % self.directory], [] | |
691 | |
692 | |
693 class SetupPerlEnvironmentAction(BaseAction): | |
694 action_type = "setup_perl_environment" | |
695 _keys = ["repo", "packages"] | |
696 | |
697 def __init__(self, elem): | |
698 self.parse_action_repo(elem) | |
699 self.parse_package_elems(elem) | |
700 | |
701 | |
702 class SetupRubyEnvironmentAction(BaseAction): | |
703 action_type = "setup_ruby_environment" | |
704 _keys = ["repo", "packages"] | |
705 | |
706 def __init__(self, elem): | |
707 self.parse_action_repo(elem) | |
708 self.parse_package_elems(elem) | |
709 | |
710 | |
711 class SetupPythonEnvironmentAction(BaseAction): | |
712 action_type = "setup_python_environment" | |
713 _keys = ["repo", "packages"] | |
714 | |
715 def __init__(self, elem): | |
716 self.parse_action_repo(elem) | |
717 self.parse_package_elems(elem) | |
718 | |
719 | |
720 class SetupVirtualenvAction(BaseAction): | |
721 action_type = "setup_virtualenv" | |
722 _keys = ["use_requirements_file", "python", "requirements"] | |
723 | |
724 def __init__(self, elem): | |
725 use_reqs = elem.attrib.get("use_requirements_file", "True") | |
726 self.use_requirements_file = asbool(use_reqs) | |
727 self.python = elem.get('python', 'python') | |
728 self.requirements = elem.text or 'requirements.txt' | |
729 | |
730 | |
731 class SetupREnvironmentAction(BaseAction): | |
732 action_type = "setup_r_environment" | |
733 _keys = ["repo", "packages"] | |
734 | |
735 def __init__(self, elem): | |
736 self.parse_action_repo(elem) | |
737 self.parse_package_elems(elem) | |
738 | |
739 | |
740 class SetEnvironmentForInstallAction(BaseAction): | |
741 action_type = "set_environment_for_install" | |
742 | |
743 def __init__(self, elem): | |
744 pass | |
745 | |
746 def to_bash(self): | |
747 # TODO - How could we resolve/check the dependencies? | |
748 return ['echo "WARNING: Assuming packages already installed!"'], [] | |
749 | |
750 | |
751 class SetVariable(object): | |
752 | |
753 def __init__(self, elem): | |
754 self.action = elem.attrib["action"] | |
755 self.name = elem.attrib["name"] | |
756 self.raw_value = elem.text | |
757 | |
758 | |
759 truthy = frozenset(['true', 'yes', 'on', 'y', 't', '1']) | |
760 falsy = frozenset(['false', 'no', 'off', 'n', 'f', '0']) | |
761 | |
762 | |
763 def asbool(obj): | |
764 if isinstance(obj, string_types): | |
765 obj = obj.strip().lower() | |
766 if obj in truthy: | |
767 return True | |
768 elif obj in falsy: | |
769 return False | |
770 else: | |
771 raise ValueError("String is not true/false: %r" % obj) | |
772 return bool(obj) | |
773 | |
774 | |
775 action_classes = [ | |
776 DownloadByUrlAction, | |
777 DownloadFileAction, | |
778 DownloadBinary, | |
779 ShellCommandAction, | |
780 TemplateShellCommandAction, | |
781 MoveFileAction, | |
782 MoveDirectoryFilesAction, | |
783 SetEnvironmentAction, | |
784 ChmodAction, | |
785 MakeInstallAction, | |
786 AutoconfAction, | |
787 ChangeDirectoryAction, | |
788 MakeDirectoryAction, | |
789 SetupPerlEnvironmentAction, | |
790 SetupRubyEnvironmentAction, | |
791 SetupPythonEnvironmentAction, | |
792 SetupVirtualenvAction, | |
793 SetupREnvironmentAction, | |
794 SetEnvironmentForInstallAction, | |
795 ] | |
796 | |
797 actions_by_type = dict(map(lambda c: (c.action_type, c), action_classes)) |