diff --git a/lib/galaxy/datatypes/display_applications/application.py b/lib/galaxy/datatypes/display_applications/application.py index 9e733a595af..74c20e139e2 100644 --- a/lib/galaxy/datatypes/display_applications/application.py +++ b/lib/galaxy/datatypes/display_applications/application.py @@ -167,23 +167,21 @@ class PopulatedDisplayApplicationLink( object ): class DisplayApplication( object ): @classmethod def from_file( cls, filename, datatypes_registry ): - return cls.from_elem( parse_xml( filename ).getroot(), datatypes_registry ) + return cls.from_elem( parse_xml( filename ).getroot(), datatypes_registry, filename=filename ) @classmethod - def from_elem( cls, elem, datatypes_registry ): + def from_elem( cls, elem, datatypes_registry, filename=None ): + att_dict = cls._get_attributes_from_elem( elem ) + rval = DisplayApplication( att_dict['id'], att_dict['name'], datatypes_registry, att_dict['version'], filename=filename, elem=elem ) + rval._load_links_from_elem( elem ) + return rval + @classmethod + def _get_attributes_from_elem( cls, elem ): display_id = elem.get( 'id', None ) assert display_id, "ID tag is required for a Display Application" name = elem.get( 'name', display_id ) version = elem.get( 'version', None ) - rval = DisplayApplication( display_id, name, datatypes_registry, version ) - for link_elem in elem.findall( 'link' ): - link = DisplayApplicationLink.from_elem( link_elem, rval ) - if link: - rval.links[ link.id ] = link - for dynamic_links in elem.findall( 'dynamic_links' ): - for link in DynamicDisplayApplicationBuilder( dynamic_links, rval, datatypes_registry.build_sites ): - rval.links[ link.id ] = link - return rval - def __init__( self, display_id, name, datatypes_registry, version = None ): + return dict( id=display_id, name=name, version=version ) + def __init__( self, display_id, name, datatypes_registry, version = None, filename=None, elem=None ): self.id = display_id self.name = name self.datatypes_registry = datatypes_registry @@ -191,6 +189,16 @@ class DisplayApplication( object ): version = "1.0.0" self.version = version self.links = odict() + self._filename = filename + self._elem = elem + def _load_links_from_elem( self, elem ): + for link_elem in elem.findall( 'link' ): + link = DisplayApplicationLink.from_elem( link_elem, self ) + if link: + self.links[ link.id ] = link + for dynamic_links in elem.findall( 'dynamic_links' ): + for link in DynamicDisplayApplicationBuilder( dynamic_links, self, self.datatypes_registry.build_sites ): + self.links[ link.id ] = link def get_link( self, link_name, data, dataset_hash, user_hash, trans, app_kwds ): #returns a link object with data knowledge to generate links return PopulatedDisplayApplicationLink( self.links[ link_name ], data, dataset_hash, user_hash, trans, app_kwds ) @@ -200,3 +208,23 @@ class DisplayApplication( object ): if link_value.filter_by_dataset( data, trans ): filtered.links[link_name] = link_value return filtered + def reload( self ): + if self._filename: + elem = parse_xml( self._filename ).getroot() + elif self._elem: + elem = self._elem + else: + raise Exception( "Unable to reload DisplayApplication %s." % ( self.name ) ) + # All toolshed-specific attributes added by e.g the registry will remain + attr_dict = self._get_attributes_from_elem( elem ) + # We will not allow changing the id at this time (we'll need to fix several mappings upstream to handle this case) + assert attr_dict.get( 'id' ) == self.id, ValueError( "You cannot reload a Display application where the ID has changed. You will need to restart the server instead." ) + # clear old links + for key in self.links.keys(): + del self.links[key] + # Set new attributes + for key, value in attr_dict.iteritems(): + setattr( self, key, value ) + # Load new links + self._load_links_from_elem( elem ) + return self diff --git a/lib/galaxy/datatypes/registry.py b/lib/galaxy/datatypes/registry.py index 17089c2b8a1..e75585c321a 100644 --- a/lib/galaxy/datatypes/registry.py +++ b/lib/galaxy/datatypes/registry.py @@ -621,6 +621,26 @@ class Registry( object ): self.log.debug( "Adding inherited display application '%s' to datatype '%s'" % ( display_app.id, extension ) ) d_type1.add_display_application( display_app ) + def reload_display_applications( self, display_application_ids=None ): + """ + Reloads display applications: by id, or all if no ids provided + Returns tuple( [reloaded_ids], [failed_ids] ) + """ + if not display_application_ids: + display_application_ids = self.display_applications.keys() + elif not isinstance( display_application_ids, list ): + display_application_ids = [ display_application_ids ] + reloaded = [] + failed = [] + for display_application_id in display_application_ids: + try: + self.display_applications[ display_application_id ].reload() + reloaded.append( display_application_id ) + except Exception, e: + self.log.debug( 'Requested to reload display application "%s", but failed: %s.', display_application_id, e ) + failed.append( display_application_id ) + return ( reloaded, failed ) + def load_external_metadata_tool( self, toolbox ): """Adds a tool which is used to set external metadata""" # We need to be able to add a job to the queue to set metadata. The queue will currently only accept jobs with an associated diff --git a/lib/galaxy/webapps/galaxy/controllers/admin.py b/lib/galaxy/webapps/galaxy/controllers/admin.py index 90a7cfa2164..4cd3e556fb3 100644 --- a/lib/galaxy/webapps/galaxy/controllers/admin.py +++ b/lib/galaxy/webapps/galaxy/controllers/admin.py @@ -883,3 +883,21 @@ class AdminGalaxy( BaseUIController, Admin, AdminActions, UsesQuotaMixin, QuotaP message = escape( galaxy.util.restore_text( kwd.get( 'message', '' ) ) ) status = galaxy.util.restore_text( kwd.get( 'status', 'done' ) ) return trans.fill_template( 'admin/view_data_tables_registry.mako', message=message, status=status ) + + @web.expose + @web.require_admin + def display_applications( self, trans, **kwd ): + return trans.fill_template( 'admin/view_display_applications.mako', display_applications=trans.app.datatypes_registry.display_applications ) + + @web.expose + @web.require_admin + def reload_display_application( self, trans, **kwd ): + reloaded, failed = trans.app.datatypes_registry.reload_display_applications( kwd.get( 'id' ) ) + if not reloaded and failed: + return trans.show_error_message( 'Unable to reload any of the %i requested display applications ("%s").' % ( len( failed ), '", "'.join( failed ) ) ) + if failed: + return trans.show_warn_message( 'Reloaded %i display applications ("%s"), but failed to reload %i display applications ("%s").' + % ( len( reloaded ), '", "'.join( reloaded ), len( failed ), '", "'.join( failed ) ) ) + if not reloaded: + return trans.show_warn_message( 'You need to request at least one display application to reload.' ) + return trans.show_ok_message( 'Reloaded %i requested display applications ("%s").' % ( len( reloaded ), '", "'.join( reloaded ) ) ) diff --git a/templates/webapps/galaxy/admin/index.mako b/templates/webapps/galaxy/admin/index.mako index 7997bdf4588..f5e6fd7c486 100644 --- a/templates/webapps/galaxy/admin/index.mako +++ b/templates/webapps/galaxy/admin/index.mako @@ -75,6 +75,7 @@
View data types registry
View data tables registry
+
View display applications
View tool lineage
Download tool tarball
Reload a tool's configuration
diff --git a/templates/webapps/galaxy/admin/view_display_applications.mako b/templates/webapps/galaxy/admin/view_display_applications.mako new file mode 100644 index 00000000000..e9cf6cfd66f --- /dev/null +++ b/templates/webapps/galaxy/admin/view_display_applications.mako @@ -0,0 +1,48 @@ +<%inherit file="/base.mako"/> +<%namespace file="/message.mako" import="render_msg" /> + +%if message: + ${render_msg( message, status )} +%endif + +
+
There are currently ${len( display_applications )} + + display applications loaded.
+
+ + + + + + + + + + <% ctr = 0 %> + %for display_app in display_applications.values(): + %if ctr % 2 == 1: + + %else: + + %endif + + + + + + + + <% ctr += 1 %> + %endfor +
ReloadNameIDVersionLinksFilename
+ + + + ${ display_app.name | h }${ display_app.id | h }${ display_app.version | h }
    + %for link in display_app.links.values(): +
  • ${ link.name | h }
  • + %endfor +
${ display_app._filename | h }
+
+