Mercurial > repos > shellac > sam_consensus_v3
diff env/lib/python3.9/site-packages/ephemeris/get_tool_list_from_galaxy.py @ 0:4f3585e2f14b draft default tip
"planemo upload commit 60cee0fc7c0cda8592644e1aad72851dec82c959"
author | shellac |
---|---|
date | Mon, 22 Mar 2021 18:12:50 +0000 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/env/lib/python3.9/site-packages/ephemeris/get_tool_list_from_galaxy.py Mon Mar 22 18:12:50 2021 +0000 @@ -0,0 +1,288 @@ +#!/usr/bin/env python +"""Tool to extract a tool list from galaxy.""" + +from argparse import ArgumentDefaultsHelpFormatter +from argparse import ArgumentParser +from distutils.version import StrictVersion + +import yaml +from bioblend.galaxy.tools import ToolClient +from bioblend.galaxy.toolshed import ToolShedClient + +from . import get_galaxy_connection +from .common_parser import get_common_args +from .shed_tools_methods import format_tool_shed_url + + +def get_tool_panel(gi): + tool_client = ToolClient(gi) + return tool_client.get_tool_panel() + + +def tools_for_repository(gi, repository): + tool_shed_url = repository.get('tool_shed_url') + name = repository['name'] + owner = repository['owner'] + changeset_revision = repository.get('changeset_revision') + + tools = [] + + def handle_tool(tool_elem): + if not tool_elem.get('tool_shed_repository', None): + return + tsr = tool_elem['tool_shed_repository'] + if tsr['name'] != name or tsr['owner'] != owner: + return + + if tool_shed_url and format_tool_shed_url(tsr['tool_shed']) != format_tool_shed_url(tool_shed_url): + return + + if changeset_revision and changeset_revision != tsr["changeset_revision"]: + return + + tools.append(tool_elem) + + walk_tools(get_tool_panel(gi), handle_tool) + + return tools + + +def walk_tools(tool_panel, f): + for elem in tool_panel: + if elem['model_class'] == 'Tool': + f(elem) + elif elem['model_class'] == 'ToolSection': + walk_tools(elem.get("elems", []), f) + + +class GiToToolYaml: + def __init__(self, gi, + include_tool_panel_section_id=False, + skip_tool_panel_section_name=True, + skip_changeset_revision=False, + get_data_managers=False, + get_all_tools=False): + self.gi = gi + + self.include_tool_panel_section_id = include_tool_panel_section_id + self.skip_tool_panel_section_name = skip_tool_panel_section_name + self.skip_changeset_revision = skip_changeset_revision + self.get_data_managers = get_data_managers + self.get_all_tools = get_all_tools + + @property + def toolbox(self): + """ + Gets the toolbox elements from <galaxy_url>/api/tools + """ + return get_tool_panel(self.gi) + + @property + def installed_tool_list(self): + """ + gets a tool list from the toolclient + :return: + """ + tool_client = ToolClient(self.gi) + return tool_client.get_tools() + + @property + def repository_list(self): + """ + Toolbox elements returned by api/tools may be of class ToolSection or Tool. + Parse these accordingly to get a list of repositories. + """ + repositories = [] + + def record_repo(tool_elem): + repo = get_repo_from_tool(tool_elem) + if repo: + repositories.append(repo) + + walk_tools(self.toolbox, record_repo) + + if self.get_data_managers: + for tool in self.installed_tool_list: + if tool.get("model_class") == 'DataManagerTool': + repo = get_repo_from_tool(tool) + if repo: + repositories.append(repo) + + if self.get_all_tools: + tools_with_panel = repositories[:] + tsc = ToolShedClient(self.gi) + repos = tsc.get_repositories() + # Hereafter follows a gruesomely ineffecient algorithm. + # The for loop and if statement are needed to retrieve tool_panel + # section labels and ids. + # If someone knows a more effecient way around this problem it + # will be greatly appreciated. + for repo in repos: + if not repo['deleted']: + tool_panel_section_id = None + tool_panel_section_label = None + for repo_with_panel in tools_with_panel: + if the_same_repository(repo_with_panel, repo, check_revision=False): + tool_panel_section_id = repo_with_panel.get('tool_panel_section_id') + tool_panel_section_label = repo_with_panel.get('tool_panel_section_label') + break + repositories.append( + dict(name=repo.get('name'), + owner=repo.get('owner'), + tool_shed_url=repo.get('tool_shed'), + revisions=[repo.get('changeset_revision')], + tool_panel_section_label=tool_panel_section_label, + tool_panel_section_id=tool_panel_section_id) + ) + return repositories + + @property + def tool_list(self): + repo_list = self.repository_list + repo_list = merge_repository_changeset_revisions(repo_list) + repo_list = self.filter_section_name_or_id_or_changeset(repo_list) + return {"tools": repo_list} + + def filter_section_name_or_id_or_changeset(self, repository_list): + new_repo_list = [] + for repo in repository_list: + if self.skip_tool_panel_section_name: + del repo['tool_panel_section_label'] + if not self.include_tool_panel_section_id: + del repo['tool_panel_section_id'] + if self.skip_changeset_revision: + del repo['revisions'] + new_repo_list.append(repo) + return new_repo_list + + def write_to_yaml(self, output_file): + with open(output_file, "w") as output: + output.write(yaml.safe_dump(self.tool_list, default_flow_style=False)) + + +def the_same_repository(repo_1_info, repo_2_info, check_revision=True): + """ + Given two dicts containing info about repositories, determine if they are the same + repository. + Each of the dicts must have the following keys: `changeset_revisions`( if check revisions is true), `name`, `owner`, and + (either `tool_shed` or `tool_shed_url`). + """ + # Sort from most unique to least unique for fast comparison. + if not check_revision or repo_1_info.get('changeset_revision') == repo_2_info.get('changeset_revision'): + if repo_1_info.get('name') == repo_2_info.get('name'): + if repo_1_info.get('owner') == repo_2_info.get('owner'): + t1ts = repo_1_info.get('tool_shed', repo_1_info.get('tool_shed_url', None)) + t2ts = repo_2_info.get('tool_shed', repo_2_info.get('tool_shed_url', None)) + if t1ts in t2ts or t2ts in t1ts: + return True + return False + + +def merge_repository_changeset_revisions(repository_list): + """ + Each installed changeset revision of a tool is listed individually. + Merge revisions of the same tool into a list. + """ + repositories = {} + repo_key_template = "{tool_shed_url}|{name}|{owner}|{tool_panel_section_id}|{tool_panel_section_label}" + for repo in repository_list: + repo_key = repo_key_template.format(**repo) + if repo_key in repositories: + repositories[repo_key].extend(repo['revisions']) + else: + repositories[repo_key] = repo['revisions'] + new_repository_list = [] + for repo_key, changeset_revisions in repositories.items(): + changeset_revisions = list(set(changeset_revisions)) + tool_shed_url, name, owner, tool_panel_section_id, tool_panel_section_label = repo_key.split('|') + new_repository_list.append( + {'tool_shed_url': tool_shed_url, + 'name': name, + 'owner': owner, + 'tool_panel_section_id': tool_panel_section_id, + 'tool_panel_section_label': tool_panel_section_label, + 'revisions': changeset_revisions} + ) + return new_repository_list + + +def _parser(): + """Creates the parser object.""" + parent = get_common_args(login_required=True) + parser = ArgumentParser(parents=[parent], + formatter_class=ArgumentDefaultsHelpFormatter) + parser.add_argument("-o", "--output-file", + required=True, + dest="output", + help="tool_list.yml output file") + parser.add_argument("--include_tool_panel_id", + action="store_true", + help="Include tool_panel_id in tool_list.yml ? " + "Use this only if the tool panel id already exists. See " + "https://github.com/galaxyproject/ansible-galaxy-tools/blob/master/files/tool_list.yaml.sample") + parser.add_argument("--skip_tool_panel_name", + action="store_true", + help="Do not include tool_panel_name in tool_list.yml ?") + parser.add_argument("--skip_changeset_revision", + action="store_true", + help="Do not include the changeset revision when generating the tool list." + "Use this if you would like to use the list to update all the tools in" + "your galaxy instance using shed-install." + ) + parser.add_argument("--get_data_managers", + action="store_true", + help="Include the data managers in the tool list. Requires admin login details") + parser.add_argument("--get_all_tools", + action="store_true", + help="Get all tools and revisions, not just those which are present on the web ui." + "Requires login details.") + return parser + + +def get_repo_from_tool(tool): + """ + Get the minimum items required for re-installing a (list of) tools + """ + if not tool.get('tool_shed_repository', None): + # Tool or Data Manager not installed from a tool shed + return {} + tsr = tool['tool_shed_repository'] + repo = {'name': tsr['name'], + 'owner': tsr['owner'], + 'tool_shed_url': tsr['tool_shed'], + 'revisions': [tsr['changeset_revision']], + 'tool_panel_section_id': tool['panel_section_id'], + 'tool_panel_section_label': tool['panel_section_name']} + return repo + + +def _parse_cli_options(): + """ + Parse command line options, returning `parse_args` from `ArgumentParser`. + """ + parser = _parser() + return parser.parse_args() + + +def check_galaxy_version(gi): + version = gi.config.get_version() + if StrictVersion(version['version_major']) < StrictVersion('16.04'): + raise Exception('This script needs galaxy version 16.04 or newer') + + +def main(): + options = _parse_cli_options() + gi = get_galaxy_connection(options, login_required=False) + check_galaxy_version(gi) + gi_to_tool_yaml = GiToToolYaml( + gi=gi, + include_tool_panel_section_id=options.include_tool_panel_id, + skip_tool_panel_section_name=options.skip_tool_panel_name, + skip_changeset_revision=options.skip_changeset_revision, + get_data_managers=options.get_data_managers, + get_all_tools=options.get_all_tools) + gi_to_tool_yaml.write_to_yaml(options.output) + + +if __name__ == "__main__": + main()