1 new commit in galaxy-central: https://bitbucket.org/galaxy/galaxy-central/changeset/0bdae741e4e2/ changeset: 0bdae741e4e2 user: greg date: 2012-01-17 20:31:06 summary: Enhance the process used by objects to retrieve tools from the tools_by_id dictionary. This allows for workflows that were built with tools originally included in the Galaxy distribution but later moved to the tool shed to function correctly if the tools are installed from the tool shed using Galaxy's update manager. In addition, workflows that were built using locally developed and hosted tools, but the tools were included in a tool shed repository, removed from the local instance, and then installed from the tool shed to function correctly. This approach works for the rerun button on history items as well. affected #: 20 files diff -r c858c99fec4c021aa5def2ed72b6898d1ac322ef -r 0bdae741e4e20f8617f0b36c8b8bce42c766692e lib/galaxy/model/__init__.py --- a/lib/galaxy/model/__init__.py +++ b/lib/galaxy/model/__init__.py @@ -156,7 +156,7 @@ dict of tool parameter values. """ param_dict = dict( [ ( p.name, p.value ) for p in self.parameters ] ) - tool = app.toolbox.tools_by_id[self.tool_id] + tool = app.toolbox.get_tool( self.tool_id ) param_dict = tool.params_from_strings( param_dict, app, ignore_errors=ignore_errors ) return param_dict def check_if_output_datasets_deleted( self ): @@ -228,7 +228,7 @@ dict of tool parameter values. """ param_dict = dict( [ ( p.name, p.value ) for p in self.parent_job.parameters ] ) - tool = app.toolbox.tools_by_id[self.tool_id] + tool = app.toolbox.get_tool( self.tool_id ) param_dict = tool.params_from_strings( param_dict, app ) return param_dict diff -r c858c99fec4c021aa5def2ed72b6898d1ac322ef -r 0bdae741e4e20f8617f0b36c8b8bce42c766692e lib/galaxy/tool_shed/install_manager.py --- a/lib/galaxy/tool_shed/install_manager.py +++ b/lib/galaxy/tool_shed/install_manager.py @@ -4,6 +4,7 @@ shed. Tools included in tool_shed_install.xml that have already been installed will not be re-installed. """ +from galaxy.tools import ToolSection from galaxy.util.shed_util import * log = logging.getLogger( __name__ ) diff -r c858c99fec4c021aa5def2ed72b6898d1ac322ef -r 0bdae741e4e20f8617f0b36c8b8bce42c766692e lib/galaxy/tools/__init__.py --- a/lib/galaxy/tools/__init__.py +++ b/lib/galaxy/tools/__init__.py @@ -98,6 +98,44 @@ self.load_section_tag_set( elem, self.tool_panel, tool_path ) elif elem.tag == 'label': self.load_label_tag_set( elem, self.tool_panel ) + def get_tool( self, tool_id, tool_version=None ): + # Attempt to locate the tool in our in-memory dictionary. + if tool_id in self.tools_by_id: + tool = self.tools_by_id[ tool_id ] + if tool_version and tool.version == tool_version: + return tool + else: + return tool + # Handle the case where the tool was used when the tool was included in the Galaxy distribution, + # but now the tool is contained in an installed tool shed repository. In this case, the original + # tool id can be mapped to the new tool id, which is the tool's guid in the tool shed repository. + # This scenarios can occur in workflows and in a history item when the rerun icon is clicked. + # The weakness here is that workflows currently handle only tool ids and not versions. + tool_id_guid_map = self.__get_tool_id_guid_map( tool_id, tool_version=tool_version ) + if tool_id_guid_map: + guid = tool_id_guid_map.guid + if guid in self.tools_by_id: + return self.tools_by_id[ guid ] + # Handle the case where a proprietary tool was initially developed and hosted in a local Galaxy + # instance, but the developer later uploaded the tool to a Galaxy tool shed, removed the original + # tool from the local Galaxy instance and installed the tool's repository from the tool shed. + for k, tool in self.tools_by_id.items(): + if tool_id == tool.old_id: + if tool_version and tool.version == tool_version: + return tool + else: + return tool + return None + def __get_tool_id_guid_map( self, tool_id, tool_version=None ): + if tool_version: + return self.sa_session.query( self.app.model.ToolIdGuidMap ) \ + .filter( and_( self.app.model.ToolIdGuidMap.table.c.tool_id == tool_id, + self.app.model.ToolIdGuidMap.table.c.tool_version == tool_version ) ) \ + .first() + else: + return self.sa_session.query( self.app.model.ToolIdGuidMap ) \ + .filter( self.app.model.ToolIdGuidMap.table.c.tool_id == tool_id ) \ + .first() def __get_tool_shed_repository( self, tool_shed, name, owner, installed_changeset_revision ): return self.sa_session.query( self.app.model.ToolShedRepository ) \ .filter( and_( self.app.model.ToolShedRepository.table.c.tool_shed == tool_shed, @@ -192,7 +230,7 @@ self.tools_by_id[ tool.id ] = tool key = 'tool_' + tool.id panel_dict[ key ] = tool - log.debug( "Loaded tool: %s %s" % ( tool.id, tool.version ) ) + log.debug( "Loaded tool id: %s, version: %s: %s" % ( tool.id, tool.version ) ) except: log.exception( "error reading tool from path: %s" % path ) def load_workflow_tag_set( self, elem, panel_dict ): diff -r c858c99fec4c021aa5def2ed72b6898d1ac322ef -r 0bdae741e4e20f8617f0b36c8b8bce42c766692e lib/galaxy/visualization/tracks/visual_analytics.py --- a/lib/galaxy/visualization/tracks/visual_analytics.py +++ b/lib/galaxy/visualization/tracks/visual_analytics.py @@ -44,7 +44,7 @@ # assert job is not None, 'Requested job has not been loaded.' if not job: return {} - tool = trans.app.toolbox.tools_by_id.get( job.tool_id, None ) + tool = trans.app.toolbox.get_tool( job.tool_id ) # TODO: could use this assertion to provide more information. # assert tool is not None, 'Requested tool has not been loaded.' if not tool: diff -r c858c99fec4c021aa5def2ed72b6898d1ac322ef -r 0bdae741e4e20f8617f0b36c8b8bce42c766692e lib/galaxy/web/api/workflows.py --- a/lib/galaxy/web/api/workflows.py +++ b/lib/galaxy/web/api/workflows.py @@ -171,7 +171,7 @@ for i, step in enumerate( workflow.steps ): job = None if step.type == 'tool' or step.type is None: - tool = self.app.toolbox.tools_by_id[ step.tool_id ] + tool = self.app.toolbox.get_tool[ step.tool_id ] def callback( input, value, prefixed_name, prefixed_label ): if isinstance( input, DataToolParameter ): if prefixed_name in step.input_connections_by_name: diff -r c858c99fec4c021aa5def2ed72b6898d1ac322ef -r 0bdae741e4e20f8617f0b36c8b8bce42c766692e lib/galaxy/web/controllers/async.py --- a/lib/galaxy/web/controllers/async.py +++ b/lib/galaxy/web/controllers/async.py @@ -42,7 +42,7 @@ # initialize the tool toolbox = self.get_toolbox() - tool = toolbox.tools_by_id.get(tool_id, '') + tool = toolbox.get_tool( tool_id ) if not tool: return "Tool with id %s not found" % tool_id diff -r c858c99fec4c021aa5def2ed72b6898d1ac322ef -r 0bdae741e4e20f8617f0b36c8b8bce42c766692e lib/galaxy/web/controllers/dataset.py --- a/lib/galaxy/web/controllers/dataset.py +++ b/lib/galaxy/web/controllers/dataset.py @@ -1116,7 +1116,7 @@ try: # Load the tool toolbox = self.get_toolbox() - tool = toolbox.tools_by_id.get( job.tool_id, None ) + tool = toolbox.get_tool( job.tool_id ) assert tool is not None, 'Requested tool has not been loaded.' params_objects = job.get_param_values( trans.app ) except: diff -r c858c99fec4c021aa5def2ed72b6898d1ac322ef -r 0bdae741e4e20f8617f0b36c8b8bce42c766692e lib/galaxy/web/controllers/history.py --- a/lib/galaxy/web/controllers/history.py +++ b/lib/galaxy/web/controllers/history.py @@ -613,7 +613,7 @@ #.add_input( "file", "Archived History File", "archive_file", value=None, error=None ) ) # Run job to do import. - history_imp_tool = trans.app.toolbox.tools_by_id[ '__IMPORT_HISTORY__' ] + history_imp_tool = trans.app.toolbox.get_tool( '__IMPORT_HISTORY__' ) incoming = { '__ARCHIVE_SOURCE__' : archive_source, '__ARCHIVE_TYPE__' : archive_type } history_imp_tool.execute( trans, incoming=incoming ) return trans.show_message( "Importing history from '%s'. \ @@ -669,7 +669,7 @@ % ( { 'n' : history.name, 's' : url_for( action="export_archive", id=id, qualified=True ) } ) ) # Run job to do export. - history_exp_tool = trans.app.toolbox.tools_by_id[ '__EXPORT_HISTORY__' ] + history_exp_tool = trans.app.toolbox.get_tool( '__EXPORT_HISTORY__' ) params = { 'history_to_export' : history, 'compress' : gzip, diff -r c858c99fec4c021aa5def2ed72b6898d1ac322ef -r 0bdae741e4e20f8617f0b36c8b8bce42c766692e lib/galaxy/web/controllers/library_common.py --- a/lib/galaxy/web/controllers/library_common.py +++ b/lib/galaxy/web/controllers/library_common.py @@ -965,7 +965,7 @@ def upload_dataset( self, trans, cntrller, library_id, folder_id, replace_dataset=None, **kwd ): # Set up the traditional tool state/params tool_id = 'upload1' - tool = trans.app.toolbox.tools_by_id[ tool_id ] + tool = trans.app.toolbox.get_tool( tool_id ) state = tool.new_state( trans ) errors = tool.update_state( trans, tool.inputs_by_page[0], state.inputs, kwd ) tool_params = state.inputs diff -r c858c99fec4c021aa5def2ed72b6898d1ac322ef -r 0bdae741e4e20f8617f0b36c8b8bce42c766692e lib/galaxy/web/controllers/root.py --- a/lib/galaxy/web/controllers/root.py +++ b/lib/galaxy/web/controllers/root.py @@ -39,7 +39,7 @@ filter( self.app.model.Job.user==trans.user ). \ order_by( self.app.model.Job.create_time.desc() ): tool_id = row[0] - a_tool = toolbox.tools_by_id.get( tool_id, None ) + a_tool = toolbox.get_tool( tool_id ) if a_tool and not a_tool.hidden and a_tool not in recent_tools: recent_tools.append( a_tool ) ## TODO: make number of recently used tools a user preference. @@ -78,7 +78,7 @@ def tool_help( self, trans, id ): """Return help page for tool identified by 'id' if available""" toolbox = self.get_toolbox() - tool = toolbox.tools_by_id.get(id, '') + tool = toolbox.get_tool( id ) yield "<html><body>" if not tool: yield "Unknown tool id '%d'" % id @@ -179,7 +179,7 @@ job_hda = job_hda.copied_from_history_dataset_association force_history_refresh = False if job_hda.creating_job_associations: - tool = trans.app.toolbox.tools_by_id.get( job_hda.creating_job_associations[ 0 ].job.tool_id, None ) + tool = trans.app.toolbox.get_tool( job_hda.creating_job_associations[ 0 ].job.tool_id ) if tool: force_history_refresh = tool.force_history_refresh if not job_hda.visible: diff -r c858c99fec4c021aa5def2ed72b6898d1ac322ef -r 0bdae741e4e20f8617f0b36c8b8bce42c766692e lib/galaxy/web/controllers/tool_runner.py --- a/lib/galaxy/web/controllers/tool_runner.py +++ b/lib/galaxy/web/controllers/tool_runner.py @@ -49,7 +49,7 @@ else: tool_ids = [ tool_id ] for tool_id in tool_ids: - tool = toolbox.tools_by_id.get( tool_id, None ) + tool = toolbox.get_tool( tool_id ) if tool: break # No tool matching the tool id, display an error (shouldn't happen) @@ -112,7 +112,7 @@ try: # Load the tool toolbox = self.get_toolbox() - tool = toolbox.tools_by_id.get( tool_id, None ) + tool = toolbox.get_tool( tool_id ) assert tool is not None, 'Requested tool has not been loaded.' except: #this is expected, so not an exception @@ -202,7 +202,7 @@ else: library_bunch = None return upload_common.new_upload( trans, cntrller, ud, library_bunch=library_bunch, state=trans.app.model.HistoryDatasetAssociation.states.UPLOAD ) - tool = self.get_toolbox().tools_by_id.get( tool_id, None ) + tool = self.get_toolbox().get_tool( tool_id ) if not tool: return False # bad tool_id nonfile_params = util.Params( kwd, sanitize=False ) diff -r c858c99fec4c021aa5def2ed72b6898d1ac322ef -r 0bdae741e4e20f8617f0b36c8b8bce42c766692e lib/galaxy/web/controllers/tracks.py --- a/lib/galaxy/web/controllers/tracks.py +++ b/lib/galaxy/web/controllers/tracks.py @@ -787,7 +787,7 @@ # # Execute tool. # - tool = trans.app.toolbox.tools_by_id.get( tool_id, None ) + tool = trans.app.toolbox.get_tool( tool_id ) if not tool: return messages.NO_TOOL @@ -829,7 +829,7 @@ # have priority. # original_job = get_dataset_job( original_dataset ) - tool = trans.app.toolbox.tools_by_id.get( original_job.tool_id, None ) + tool = trans.app.toolbox.get_tool( original_job.tool_id ) if not tool: return messages.NO_TOOL tool_params = dict( [ ( p.name, p.value ) for p in original_job.parameters ] ) diff -r c858c99fec4c021aa5def2ed72b6898d1ac322ef -r 0bdae741e4e20f8617f0b36c8b8bce42c766692e lib/galaxy/web/controllers/user.py --- a/lib/galaxy/web/controllers/user.py +++ b/lib/galaxy/web/controllers/user.py @@ -925,7 +925,7 @@ filter( self.app.model.History.user==trans.user ). \ order_by( self.app.model.Job.create_time.desc() ).limit(1) tool_id = query[0][0] # Get first element in first row of query. - tool = self.get_toolbox().tools_by_id[ tool_id ] + tool = self.get_toolbox().get_tool( tool_id ) # Return tool info. tool_info = { diff -r c858c99fec4c021aa5def2ed72b6898d1ac322ef -r 0bdae741e4e20f8617f0b36c8b8bce42c766692e lib/galaxy/web/controllers/workflow.py --- a/lib/galaxy/web/controllers/workflow.py +++ b/lib/galaxy/web/controllers/workflow.py @@ -1306,16 +1306,7 @@ for job_id in job_ids: assert job_id in jobs_by_id, "Attempt to create workflow with job not connected to current history" job = jobs_by_id[ job_id ] - try: - tool = trans.app.toolbox.tools_by_id[ job.tool_id ] - except KeyError, e: - # Handle the case where the workflow requires a tool not available in the local Galaxy instance. - # The id value of tools installed from a Galaxy tool shed is a guid, but these tool's old_id - # attribute should contain what we're looking for. - for available_tool_id, available_tool in trans.app.toolbox.tools_by_id.items(): - if job.tool_id == available_tool.old_id: - tool = available_tool - break + tool = trans.app.toolbox.get_tool( job.tool_id ) param_values = job.get_param_values( trans.app ) associations = cleanup_param_values( tool.inputs, param_values ) # Doing it this way breaks dynamic parameters, backed out temporarily. @@ -1482,16 +1473,7 @@ # Execute module job = None if step.type == 'tool' or step.type is None: - try: - tool = trans.app.toolbox.tools_by_id[ step.tool_id ] - except KeyError, e: - # Handle the case where the workflow requires a tool not available in the local Galaxy instance. - # The id value of tools installed from a Galaxy tool shed is a guid, but these tool's old_id - # attribute should contain what we're looking for. - for available_tool_id, available_tool in trans.app.toolbox.tools_by_id.items(): - if step.tool_id == available_tool.old_id: - tool = available_tool - break + tool = trans.app.toolbox.get_tool( step.tool_id ) input_values = step.state.inputs # Connect up def callback( input, value, prefixed_name, prefixed_label ): diff -r c858c99fec4c021aa5def2ed72b6898d1ac322ef -r 0bdae741e4e20f8617f0b36c8b8bce42c766692e lib/galaxy/workflow/modules.py --- a/lib/galaxy/workflow/modules.py +++ b/lib/galaxy/workflow/modules.py @@ -166,17 +166,7 @@ def __init__( self, trans, tool_id ): self.trans = trans self.tool_id = tool_id - try: - self.tool = trans.app.toolbox.tools_by_id[ tool_id ] - except KeyError, e: - # Handle the case where the workflow requires a tool not available in the local Galaxy instance. - self.tool = None - # The id value of tools installed from a Galaxy tool shed is a guid, but - # these tool's old_id attribute should contain what we're looking for. - for available_tool_id, available_tool in trans.app.toolbox.tools_by_id.items(): - if tool_id == available_tool.old_id: - self.tool = available_tool - break + self.tool = trans.app.toolbox.get_tool( tool_id ) self.post_job_actions = {} self.workflow_outputs = [] self.state = None @@ -206,12 +196,14 @@ tool_id = step.tool_id install_tool_id = None if trans.app.toolbox and tool_id not in trans.app.toolbox.tools_by_id: - # The id value of tools installed from a Galaxy tool shed is a guid, but - # these tool's old_id attribute should contain what we're looking for. - for available_tool_id, available_tool in trans.app.toolbox.tools_by_id.items(): - if tool_id == available_tool.old_id: - install_tool_id = available_tool_id - break + # Handle the case where the tool was used when the tool was included in the Galaxy distribution, + # but now the tool is contained in an installed tool shed repository. In this case, the original + # tool id can be mapped to the new tool id, which is the tool's guid in the tool shed repository. + tool_id_guid_map = trans.sa_session.query( trans.model.ToolIdGuidMap ) \ + .filter( trans.model.ToolIdGuidMap.table.c.tool_id == tool_id ) \ + .first() + if tool_id_guid_map: + install_tool_id = tool_id_guid_map.guid if ( trans.app.toolbox and tool_id in trans.app.toolbox.tools_by_id ) or install_tool_id: module = Class( trans, tool_id ) module.state = DefaultToolState() diff -r c858c99fec4c021aa5def2ed72b6898d1ac322ef -r 0bdae741e4e20f8617f0b36c8b8bce42c766692e templates/history/display_structured.mako --- a/templates/history/display_structured.mako +++ b/templates/history/display_structured.mako @@ -98,8 +98,9 @@ <div class="tool toolForm"><% - if job.tool_id in trans.app.toolbox.tools_by_id: - tool_name = trans.app.toolbox.tools_by_id[job.tool_id].name + tool = trans.app.toolbox.get_tool( job.tool_id ) + if tool: + tool_name = tool.name else: tool_name = "Unknown tool with id '%s'" % job.tool_id %> diff -r c858c99fec4c021aa5def2ed72b6898d1ac322ef -r 0bdae741e4e20f8617f0b36c8b8bce42c766692e templates/workflow/build_from_current_history.mako --- a/templates/workflow/build_from_current_history.mako +++ b/templates/workflow/build_from_current_history.mako @@ -103,7 +103,7 @@ cls += " toolFormDisabled" disabled = True else: - tool = app.toolbox.tools_by_id.get( job.tool_id, None ) + tool = app.toolbox.get_tool( job.tool_id ) if tool: tool_name = tool.name if tool is None or not( tool.is_workflow_compatible ): diff -r c858c99fec4c021aa5def2ed72b6898d1ac322ef -r 0bdae741e4e20f8617f0b36c8b8bce42c766692e templates/workflow/display.mako --- a/templates/workflow/display.mako +++ b/templates/workflow/display.mako @@ -83,15 +83,7 @@ <tr><td> %if step.type == 'tool' or step.type is None: <% - try: - tool = trans.app.toolbox.tools_by_id[ step.tool_id ] - except KeyError, e: - # The id value of tools installed from a Galaxy tool shed is a guid, but - # these tool's old_id attribute should contain what we're looking for. - for available_tool_id, available_tool in trans.app.toolbox.tools_by_id.items(): - if step.tool_id == available_tool.old_id: - tool = available_tool - break + tool = trans.app.toolbox.get_tool( step.tool_id ) %><div class="toolForm"><div class="toolFormTitle">Step ${int(step.order_index)+1}: ${tool.name}</div> diff -r c858c99fec4c021aa5def2ed72b6898d1ac322ef -r 0bdae741e4e20f8617f0b36c8b8bce42c766692e templates/workflow/run.mako --- a/templates/workflow/run.mako +++ b/templates/workflow/run.mako @@ -364,15 +364,7 @@ %for i, step in enumerate( steps ): %if step.type == 'tool' or step.type is None: <% - try: - tool = trans.app.toolbox.tools_by_id[ step.tool_id ] - except KeyError, e: - # The id value of tools installed from a Galaxy tool shed is a guid, but - # these tool's old_id attribute should contain what we're looking for. - for available_tool_id, available_tool in trans.app.toolbox.tools_by_id.items(): - if step.tool_id == available_tool.old_id: - tool = available_tool - break + tool = trans.app.toolbox.get_tool( step.tool_id ) %><input type="hidden" name="${step.id}|tool_state" value="${step.state.encode( tool, app )}"><div class="toolForm"> diff -r c858c99fec4c021aa5def2ed72b6898d1ac322ef -r 0bdae741e4e20f8617f0b36c8b8bce42c766692e test/functional/test_toolbox.py --- a/test/functional/test_toolbox.py +++ b/test/functional/test_toolbox.py @@ -149,7 +149,7 @@ # Push all the toolbox tests to module level G = globals() for i, tool_id in enumerate( toolbox.tools_by_id ): - tool = toolbox.tools_by_id[ tool_id ] + tool = toolbox.get_tool( tool_id ) if tool.tests: # Create a new subclass of ToolTestCase dynamically adding methods # names test_tool_XXX that run each test defined in the tool. Repository URL: https://bitbucket.org/galaxy/galaxy-central/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email.