2 new commits in galaxy-central: https://bitbucket.org/galaxy/galaxy-central/commits/b26dc879b09c/ Changeset: b26dc879b09c User: jmchilton Date: 2014-12-29 15:28:37+00:00 Summary: Abstract tool lineage handling out of ToolBox. Start work on infrastructure to support tool lineages not defined within the tool shed install model. Affected #: 5 files diff -r 68255ebe3f54500aa26db814c41f67f382731462 -r b26dc879b09c639b47c76cb97b067073a3c956e6 lib/galaxy/tools/__init__.py --- a/lib/galaxy/tools/__init__.py +++ b/lib/galaxy/tools/__init__.py @@ -53,6 +53,7 @@ from galaxy.tools.parser import get_tool_source from galaxy.tools.parser.xml import XmlPageSource from galaxy.tools.toolbox import tool_tag_manager +from galaxy.tools.toolbox.lineages import LineageMap from galaxy.util import listify, parse_xml, rst_to_html, string_as_bool, string_to_object from galaxy.tools.parameters.meta import expand_meta_parameters from galaxy.util.bunch import Bunch @@ -139,6 +140,7 @@ self.tool_panel = odict() self.index = 0 self.data_manager_tools = odict() + self.lineage_map = LineageMap( app ) # File that contains the XML section and tool tags from all tool panel config files integrated into a # single file that defines the tool panel layout. This file can be changed by the Galaxy administrator # (in a way similar to the single tool_conf.xml file in the past) to alter the layout of the tool panel. @@ -371,8 +373,8 @@ log.debug( "Loaded tool id: %s, version: %s into tool panel.." % ( tool.id, tool.version ) ) else: # We are in the process of installing the tool. - tool_version = self.__get_tool_version( tool_id ) - tool_lineage_ids = tool_version.get_version_ids( self.app, reverse=True ) + tool_lineage = self.lineage_map.get( tool_id ) + tool_lineage_ids = tool_lineage.get_version_ids( reverse=True ) for lineage_id in tool_lineage_ids: if lineage_id in self.tools_by_id: loaded_version_key = 'tool_%s' % lineage_id @@ -512,9 +514,9 @@ return self.tools_by_id[ tool_id ] #exact tool id match not found, or all versions requested, search for other options, e.g. migrated tools or different versions rval = [] - tv = self.__get_tool_version( tool_id ) - if tv: - tool_version_ids = tv.get_version_ids( self.app ) + tool_lineage = self.lineage_map.get( tool_id ) + if tool_lineage: + tool_version_ids = tool_lineage.get_version_ids( ) for tool_version_id in tool_version_ids: if tool_version_id in self.tools_by_id: rval.append( self.tools_by_id[ tool_version_id ] ) @@ -560,9 +562,9 @@ def get_loaded_tools_by_lineage( self, tool_id ): """Get all loaded tools associated by lineage to the tool whose id is tool_id.""" - tv = self.__get_tool_version( tool_id ) - if tv: - tool_version_ids = tv.get_version_ids( self.app ) + tool_lineage = self.lineage_map.get( tool_id ) + if tool_lineage: + tool_version_ids = tool_lineage.get_version_ids( ) available_tool_versions = [] for tool_version_id in tool_version_ids: if tool_version_id in self.tools_by_id: @@ -574,12 +576,6 @@ return [ tool ] return [] - def __get_tool_version( self, tool_id ): - """Return a ToolVersion if one exists for the tool_id""" - return self.app.install_model.context.query( self.app.install_model.ToolVersion ) \ - .filter( self.app.install_model.ToolVersion.table.c.tool_id == tool_id ) \ - .first() - def tools( self ): return self.tools_by_id.iteritems() @@ -745,12 +741,10 @@ tool.guid = guid tool.version = elem.find( "version" ).text # Make sure the tool has a tool_version. - if not self.__get_tool_version( tool.id ): - tool_version = self.app.install_model.ToolVersion( tool_id=tool.id, tool_shed_repository=tool_shed_repository ) - self.app.install_model.context.add( tool_version ) - self.app.install_model.context.flush() + tool_lineage = self.lineage_map.register( tool, tool_shed_repository=tool_shed_repository ) # Load the tool's lineage ids. - tool.lineage_ids = tool.tool_version.get_version_ids( self.app ) + tool.lineage = tool_lineage + tool.lineage_ids = tool_lineage.get_version_ids( ) self.tool_tag_manager.handle_tags( tool.id, elem ) self.__add_tool( tool, load_panel_dict, panel_dict ) # Always load the tool into the integrated_panel_dict, or it will not be included in the integrated_tool_panel.xml file. @@ -1493,14 +1487,6 @@ return [] @property - def tool_version_ids( self ): - # If we have versions, return a list of their tool_ids. - tool_version = self.tool_version - if tool_version: - return tool_version.get_version_ids( self.app ) - return [] - - @property def tool_shed_repository( self ): # If this tool is included in an installed tool shed repository, return it. if self.tool_shed: diff -r 68255ebe3f54500aa26db814c41f67f382731462 -r b26dc879b09c639b47c76cb97b067073a3c956e6 lib/galaxy/tools/toolbox/lineages/__init__.py --- /dev/null +++ b/lib/galaxy/tools/toolbox/lineages/__init__.py @@ -0,0 +1,5 @@ +from .factory import LineageMap +from .interface import ToolLineage + + +__all__ = ["LineageMap", "ToolLineage"] diff -r 68255ebe3f54500aa26db814c41f67f382731462 -r b26dc879b09c639b47c76cb97b067073a3c956e6 lib/galaxy/tools/toolbox/lineages/factory.py --- /dev/null +++ b/lib/galaxy/tools/toolbox/lineages/factory.py @@ -0,0 +1,28 @@ +from .tool_shed import ToolShedLineage + + +class LineageMap(object): + """ Map each unique tool id to a lineage object. + """ + + def __init__(self, app): + self.lineage_map = {} + self.app = app + + def register(self, tool, **kwds): + tool_id = tool.id + if tool_id not in self.lineage_map: + tool_shed_repository = kwds.get("tool_shed_repository", None) + lineage = ToolShedLineage.from_tool(self.app, tool, tool_shed_repository) + self.lineage_map[tool_id] = lineage + return self.lineage_map[tool_id] + + def get(self, tool_id): + if tool_id not in self.lineage_map: + lineage = ToolShedLineage.from_tool_id( self.app, tool_id ) + if lineage: + self.lineage_map[tool_id] = lineage + + return self.lineage_map.get(tool_id, None) + +__all__ = ["LineageMap"] diff -r 68255ebe3f54500aa26db814c41f67f382731462 -r b26dc879b09c639b47c76cb97b067073a3c956e6 lib/galaxy/tools/toolbox/lineages/interface.py --- /dev/null +++ b/lib/galaxy/tools/toolbox/lineages/interface.py @@ -0,0 +1,14 @@ +from abc import ABCMeta +from abc import abstractmethod + + +class ToolLineage(object): + """ + """ + __metaclass__ = ABCMeta + + @abstractmethod + def get_version_ids( self, reverse=False ): + """ Return an ordered list of lineages in this chain, from + oldest to newest. + """ diff -r 68255ebe3f54500aa26db814c41f67f382731462 -r b26dc879b09c639b47c76cb97b067073a3c956e6 lib/galaxy/tools/toolbox/lineages/tool_shed.py --- /dev/null +++ b/lib/galaxy/tools/toolbox/lineages/tool_shed.py @@ -0,0 +1,43 @@ +from .interface import ToolLineage + +from galaxy.model.tool_shed_install import ToolVersion + + +class ToolShedLineage(ToolLineage): + """ Representation of tool lineage derived from tool shed repository + installations. """ + + def __init__(self, app, tool_version): + self.app = app + self.tool_version_id = tool_version.id + + @staticmethod + def from_tool( app, tool, tool_shed_repository ): + # Make sure the tool has a tool_version. + if not get_install_tool_version( app, tool.id ): + tool_version = ToolVersion( tool_id=tool.id, tool_shed_repository=tool_shed_repository ) + app.install_model.context.add( tool_version ) + app.install_model.context.flush() + return ToolShedLineage( app, tool.tool_version ) + + @staticmethod + def from_tool_id( app, tool_id ): + tool_version = get_install_tool_version( app, tool_id ) + if tool_version: + return ToolShedLineage( app, tool_version ) + else: + return None + + def get_version_ids( self, reverse=False ): + tool_version = self.app.install_model.context.query( ToolVersion ).get( self.tool_version_id ) + return tool_version.get_version_ids( self.app, reverse=reverse ) + + +def get_install_tool_version( app, tool_id ): + return app.install_model.context.query( + app.install_model.ToolVersion + ).filter( + app.install_model.ToolVersion.table.c.tool_id == tool_id + ).first() + +__all__ = [ "ToolShedLineage" ] https://bitbucket.org/galaxy/galaxy-central/commits/806202db57a7/ Changeset: 806202db57a7 User: jmchilton Date: 2014-12-29 15:28:37+00:00 Summary: Abstract out higher-level helpers in ToolBox for lineage reasoning. Reduces code duplication slightly and simplifies __add_tool_to_tool_panel (cyclomatic complexity reduced from 20 to 14). Affected #: 1 file diff -r b26dc879b09c639b47c76cb97b067073a3c956e6 -r 806202db57a7502c2aa5476f2db46f7aae75f439 lib/galaxy/tools/__init__.py --- a/lib/galaxy/tools/__init__.py +++ b/lib/galaxy/tools/__init__.py @@ -325,20 +325,13 @@ panel_dict = panel_component.elems else: panel_dict = panel_component - already_loaded = False - loaded_version_key = None - lineage_id = None - for lineage_id in tool.lineage_ids: - if lineage_id in self.tools_by_id: - loaded_version_key = 'tool_%s' % lineage_id - if loaded_version_key in panel_dict: - already_loaded = True - break - if already_loaded: - if tool.lineage_ids.index( tool_id ) > tool.lineage_ids.index( lineage_id ): + related_tool = self._lineage_in_panel( panel_dict, tool=tool ) + if related_tool: + if self._newer_tool( tool, related_tool ): + lineage_id = "tool_%s" % related_tool.id + index = panel_dict.keys().index( lineage_id ) + del panel_dict[ lineage_id ] key = 'tool_%s' % tool.id - index = panel_dict.keys().index( loaded_version_key ) - del panel_dict[ loaded_version_key ] panel_dict.insert( index, key, tool ) log.debug( "Loaded tool id: %s, version: %s into tool panel." % ( tool.id, tool.version ) ) else: @@ -374,12 +367,7 @@ else: # We are in the process of installing the tool. tool_lineage = self.lineage_map.get( tool_id ) - tool_lineage_ids = tool_lineage.get_version_ids( reverse=True ) - for lineage_id in tool_lineage_ids: - if lineage_id in self.tools_by_id: - loaded_version_key = 'tool_%s' % lineage_id - if loaded_version_key in panel_dict: - already_loaded = True + already_loaded = self._lineage_in_panel( panel_dict, tool_lineage=tool_lineage ) is not None if not already_loaded: # If the tool is not defined in integrated_tool_panel.xml, append it to the tool panel. panel_dict[ key ] = tool @@ -1193,6 +1181,27 @@ return rval + def _lineage_in_panel( self, panel_dict, tool=None, tool_lineage=None ): + """ If tool with same lineage already in panel (or section) - find + and return it. Otherwise return None. + """ + if tool_lineage is None: + assert tool is not None + tool_lineage = tool.lineage + lineage_ids = tool_lineage.get_version_ids( reverse=True ) + for lineage_id in lineage_ids: + if lineage_id in self.tools_by_id: + loaded_version_key = 'tool_%s' % lineage_id + if loaded_version_key in panel_dict: + return panel_dict[ loaded_version_key ] + return None + + def _newer_tool( self, tool1, tool2 ): + """ Return True if tool1 is considered "newer" given its own lineage + description. + """ + return tool1.lineage_ids.index( tool1.id ) > tool1.lineage_ids.index( tool2.id ) + def _filter_for_panel( item, filters, context ): """ 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.