11#!/usr/bin/env python
22"""Tool to extract a tool list from galaxy."""
33
4-
54from argparse import ArgumentDefaultsHelpFormatter
65from argparse import ArgumentParser
76from distutils .version import StrictVersion
87
98import yaml
109from bioblend .galaxy .tools import ToolClient
10+ from bioblend .galaxy .toolshed import ToolShedClient
1111
1212from . import get_galaxy_connection
1313from .common_parser import get_common_args
@@ -59,16 +59,15 @@ def __init__(self, gi,
5959 include_tool_panel_section_id = False ,
6060 skip_tool_panel_section_name = True ,
6161 skip_changeset_revision = False ,
62- get_data_managers = False ):
62+ get_data_managers = False ,
63+ get_all_tools = False ):
6364 self .gi = gi
65+
6466 self .include_tool_panel_section_id = include_tool_panel_section_id
6567 self .skip_tool_panel_section_name = skip_tool_panel_section_name
6668 self .skip_changeset_revision = skip_changeset_revision
6769 self .get_data_managers = get_data_managers
68- self .repository_list = self .get_repositories ()
69- self .repository_list = self .merge_tool_changeset_revisions ()
70- self .filter_section_name_or_id_or_changeset ()
71- self .tool_list = {"tools" : self .repository_list }
70+ self .get_all_tools = get_all_tools
7271
7372 @property
7473 def toolbox (self ):
@@ -86,7 +85,8 @@ def installed_tool_list(self):
8685 tool_client = ToolClient (self .gi )
8786 return tool_client .get_tools ()
8887
89- def get_repositories (self ):
88+ @property
89+ def repository_list (self ):
9090 """
9191 Toolbox elements returned by api/tools may be of class ToolSection or Tool.
9292 Parse these accordingly to get a list of repositories.
@@ -104,54 +104,107 @@ def record_repo(tool_elem):
104104 for tool in self .installed_tool_list :
105105 if tool .get ("model_class" ) == 'DataManagerTool' :
106106 repositories .append (get_repo_from_tool (tool ))
107+
108+ if self .get_all_tools :
109+ tools_with_panel = repositories [:]
110+ tsc = ToolShedClient (self .gi )
111+ repos = tsc .get_repositories ()
112+ # Hereafter follows a gruesomely ineffecient algorithm.
113+ # The for loop and if statement are needed to retrieve tool_panel
114+ # section labels and ids.
115+ # If someone knows a more effecient way around this problem it
116+ # will be greatly appreciated.
117+ for repo in repos :
118+ if not repo ['deleted' ]:
119+ for repo_with_panel in tools_with_panel :
120+ tool_panel_section_id = None
121+ tool_panel_section_label = None
122+ if the_same_repository (repo_with_panel , repo , check_revision = False ):
123+ tool_panel_section_id = repo_with_panel .get ('tool_panel_section_id' )
124+ tool_panel_section_label = repo_with_panel .get ('tool_panel_section_label' )
125+ break
126+ repositories .append (
127+ dict (name = repo .get ('name' ),
128+ owner = repo .get ('owner' ),
129+ tool_shed_url = repo .get ('tool_shed' ),
130+ revisions = [repo .get ('changeset_revision' )],
131+ tool_panel_section_label = tool_panel_section_label ,
132+ tool_panel_section_id = tool_panel_section_id )
133+ )
107134 return repositories
108135
109- def merge_tool_changeset_revisions (self ):
110- """
111- Each installed changeset revision of a tool is listed individually.
112- Merge revisions of the same tool into a list.
113- """
114- repositories = {}
115- repo_key_template = "{tool_shed_url}|{name}|{owner}|{tool_panel_section_id}|{tool_panel_section_label}"
116- for tool in self .repository_list :
117- repo_key = repo_key_template .format (** tool )
118- if repo_key in repositories :
119- repositories [repo_key ].extend (tool ['revisions' ])
120- else :
121- repositories [repo_key ] = tool ['revisions' ]
122- new_repository_list = []
123- for repo_key , changeset_revisions in repositories .items ():
124- changeset_revisions = list (set (changeset_revisions ))
125- tool_shed_url , name , owner , tool_panel_section_id , tool_panel_section_label = repo_key .split ('|' )
126- new_repository_list .append (
127- {'tool_shed_url' : tool_shed_url ,
128- 'name' : name ,
129- 'owner' : owner ,
130- 'tool_panel_section_id' : tool_panel_section_id ,
131- 'tool_panel_section_label' : tool_panel_section_label ,
132- 'revisions' : changeset_revisions }
133- )
134- return new_repository_list
135-
136- def filter_section_name_or_id_or_changeset (self ):
137- repo_list = []
138- for repo in self .repository_list :
136+ @property
137+ def tool_list (self ):
138+ repo_list = self .repository_list
139+ repo_list = merge_repository_changeset_revisions (repo_list )
140+ repo_list = self .filter_section_name_or_id_or_changeset (repo_list )
141+ return {"tools" : repo_list }
142+
143+ def filter_section_name_or_id_or_changeset (self , repository_list ):
144+ new_repo_list = []
145+ for repo in repository_list :
139146 if self .skip_tool_panel_section_name :
140147 del repo ['tool_panel_section_label' ]
141148 if not self .include_tool_panel_section_id :
142149 del repo ['tool_panel_section_id' ]
143150 if self .skip_changeset_revision :
144151 del repo ['revisions' ]
145- repo_list .append (repo )
146- self . repository_list = repo_list
152+ new_repo_list .append (repo )
153+ return new_repo_list
147154
148155 def write_to_yaml (self , output_file ):
149156 with open (output_file , "w" ) as output :
150157 output .write (yaml .safe_dump (self .tool_list , default_flow_style = False ))
151158
152159
160+ def the_same_repository (repo_1_info , repo_2_info , check_revision = True ):
161+ """
162+ Given two dicts containing info about repositories, determine if they are the same
163+ repository.
164+ Each of the dicts must have the following keys: `changeset_revisions`( if check revisions is true), `name`, `owner`, and
165+ (either `tool_shed` or `tool_shed_url`).
166+ """
167+ # Sort from most unique to least unique for fast comparison.
168+ if not check_revision or repo_1_info .get ('changeset_revision' ) == repo_2_info .get ('changeset_revision' ):
169+ if repo_1_info .get ('name' ) == repo_2_info .get ('name' ):
170+ if repo_1_info .get ('owner' ) == repo_2_info .get ('owner' ):
171+ t1ts = repo_1_info .get ('tool_shed' , repo_1_info .get ('tool_shed_url' , None ))
172+ t2ts = repo_2_info .get ('tool_shed' , repo_2_info .get ('tool_shed_url' , None ))
173+ if t1ts in t2ts or t2ts in t1ts :
174+ return True
175+ return False
176+
177+
178+ def merge_repository_changeset_revisions (repository_list ):
179+ """
180+ Each installed changeset revision of a tool is listed individually.
181+ Merge revisions of the same tool into a list.
182+ """
183+ repositories = {}
184+ repo_key_template = "{tool_shed_url}|{name}|{owner}|{tool_panel_section_id}|{tool_panel_section_label}"
185+ for repo in repository_list :
186+ repo_key = repo_key_template .format (** repo )
187+ if repo_key in repositories :
188+ repositories [repo_key ].extend (repo ['revisions' ])
189+ else :
190+ repositories [repo_key ] = repo ['revisions' ]
191+ new_repository_list = []
192+ for repo_key , changeset_revisions in repositories .items ():
193+ changeset_revisions = list (set (changeset_revisions ))
194+ tool_shed_url , name , owner , tool_panel_section_id , tool_panel_section_label = repo_key .split ('|' )
195+ new_repository_list .append (
196+ {'tool_shed_url' : tool_shed_url ,
197+ 'name' : name ,
198+ 'owner' : owner ,
199+ 'tool_panel_section_id' : tool_panel_section_id ,
200+ 'tool_panel_section_label' : tool_panel_section_label ,
201+ 'revisions' : changeset_revisions }
202+ )
203+ return new_repository_list
204+
205+
153206def _parser ():
154- ''' Creates the parser object.'''
207+ """ Creates the parser object."""
155208 parent = get_common_args (login_required = True )
156209 parser = ArgumentParser (parents = [parent ],
157210 formatter_class = ArgumentDefaultsHelpFormatter )
@@ -175,7 +228,11 @@ def _parser():
175228 )
176229 parser .add_argument ("--get_data_managers" ,
177230 action = "store_true" ,
178- help = "Include the data managers in the tool list. Requires login details" )
231+ help = "Include the data managers in the tool list. Requires admin login details" )
232+ parser .add_argument ("--get_all_tools" ,
233+ action = "store_true" ,
234+ help = "Get all tools and revisions, not just those which are present on the web ui."
235+ "Requires login details." )
179236 return parser
180237
181238
@@ -218,7 +275,8 @@ def main():
218275 include_tool_panel_section_id = options .include_tool_panel_id ,
219276 skip_tool_panel_section_name = options .skip_tool_panel_name ,
220277 skip_changeset_revision = options .skip_changeset_revision ,
221- get_data_managers = options .get_data_managers )
278+ get_data_managers = options .get_data_managers ,
279+ get_all_tools = options .get_all_tools )
222280 gi_to_tool_yaml .write_to_yaml (options .output )
223281
224282
0 commit comments