5 new commits in galaxy-central: https://bitbucket.org/galaxy/galaxy-central/commits/c118476b5823/ Changeset: c118476b5823 User: jgoecks Date: 2014-07-21 16:19:14 Summary: Use jquery to remove event handler. Affected #: 1 file diff -r cbca66cc16bfed165f3b38399857ad0b85d14489 -r c118476b5823c676267dbe5d48f7105711e3c15d static/scripts/viz/trackster.js --- a/static/scripts/viz/trackster.js +++ b/static/scripts/viz/trackster.js @@ -356,7 +356,7 @@ buttons: { "Cancel": function() { Galaxy.modal.hide(); }, "Leave without Saving" : function() { - window.onbeforeunload = undefined; + $(window).off('beforeunload'); window.location = galaxy_config.root + 'visualization'; }, "Save" : function() { https://bitbucket.org/galaxy/galaxy-central/commits/bca25a3bc9c7/ Changeset: bca25a3bc9c7 User: jgoecks Date: 2014-07-21 16:26:18 Summary: Trackster: remove bottom label track because it is redundant. Affected #: 1 file diff -r c118476b5823c676267dbe5d48f7105711e3c15d -r bca25a3bc9c7618eb37fb467ae32564fa213aac5 static/scripts/viz/trackster/tracks.js --- a/static/scripts/viz/trackster/tracks.js +++ b/static/scripts/viz/trackster/tracks.js @@ -885,8 +885,6 @@ }); }); }); - // Another label track at bottom - this.nav_labeltrack = $("<div/>").addClass("nav-labeltrack").appendTo(this.bottom_container); // Navigation at top this.nav_container = $("<div/>").addClass("trackster-nav-container").prependTo(this.top_container); this.nav = $("<div/>").addClass("trackster-nav").appendTo(this.nav_container); @@ -1042,7 +1040,7 @@ // Dragging in the top label track allows selecting a region to zoom in on selected region. this.top_labeltrack.bind( "dragstart", function( e, d ) { return $("<div/>").addClass('zoom-area').css( - "height", view.browser_content_div.height() + view.top_labeltrack.height() + view.nav_labeltrack.height() + 1 + "height", view.browser_content_div.height() + view.top_labeltrack.height() + 1 ).appendTo( $(this) ); }).bind( "drag", function( e, d ) { $( d.proxy ).css({ left: Math.min( e.pageX, d.startX ) - view.container.offset().left, width: Math.abs( e.pageX - d.startX ) }); @@ -1091,7 +1089,6 @@ */ this.add_label_track( new LabelTrack( this, { content_div: this.top_labeltrack } ) ); - this.add_label_track( new LabelTrack( this, { content_div: this.nav_labeltrack } ) ); $(window).bind("resize", function() { // Stop previous timer. https://bitbucket.org/galaxy/galaxy-central/commits/f9b47a91b7f2/ Changeset: f9b47a91b7f2 User: jgoecks Date: 2014-07-21 16:27:44 Summary: Trackster: some fixes for vertical position element. Affected #: 1 file diff -r bca25a3bc9c7618eb37fb467ae32564fa213aac5 -r f9b47a91b7f2611c87c9dc7a0ceafc733f6bc181 static/scripts/viz/trackster/tracks.js --- a/static/scripts/viz/trackster/tracks.js +++ b/static/scripts/viz/trackster/tracks.js @@ -1062,11 +1062,9 @@ view.request_redraw(); }); + // FIXME: this is still wonky for embedded visualizations. + /* // For vertical alignment, track mouse with simple line. - // Fixes needed for this to work: - // (a) make work with embedded visualizations; - // (b) seems to get stuck on tile overlaps. - /* var mouse_tracker_div = $('<div/>').addClass('mouse-pos').appendTo(parent_element); // Show tracker only when hovering over view. @@ -1075,9 +1073,8 @@ mouse_tracker_div.show(); parent_element.mousemove(function(e) { mouse_tracker_div.css({ - // -1 makes it appear next to the mouse w/o obscuring clicking - // and dragging on view elements. - left: e.pageX - 1 + // -1 makes line appear next to the mouse w/o preventing mouse actions. + left: e.pageX - parent_element.offset().left - 1 }); }); }, https://bitbucket.org/galaxy/galaxy-central/commits/972a80267009/ Changeset: 972a80267009 User: jgoecks Date: 2014-07-21 19:23:41 Summary: Trackster: do not reset overview when changing chromosome. Affected #: 1 file diff -r f9b47a91b7f2611c87c9dc7a0ceafc733f6bc181 -r 972a80267009126e558ba14142df48b897db48c8 static/scripts/viz/trackster/tracks.js --- a/static/scripts/viz/trackster/tracks.js +++ b/static/scripts/viz/trackster/tracks.js @@ -1287,7 +1287,6 @@ } } - view.reset_overview(); view.request_redraw(); } }, https://bitbucket.org/galaxy/galaxy-central/commits/e9de99ef7710/ Changeset: e9de99ef7710 User: jgoecks Date: 2014-07-21 19:42:14 Summary: Automated merge Affected #: 19 files diff -r 972a80267009126e558ba14142df48b897db48c8 -r e9de99ef77105d221df55771724ca56b86485a4b lib/galaxy/webapps/galaxy/api/tool_shed_repositories.py --- a/lib/galaxy/webapps/galaxy/api/tool_shed_repositories.py +++ b/lib/galaxy/webapps/galaxy/api/tool_shed_repositories.py @@ -413,12 +413,12 @@ # Make sure the current user's API key proves he is an admin user in this Galaxy instance. if not trans.user_is_admin(): raise HTTPForbidden( detail='You are not authorized to reset metadata on repositories installed into this Galaxy instance.' ) - query = suc.get_query_for_setting_metadata_on_repositories( trans, my_writable=False, order=False ) + irmm = InstalledRepositoryMetadataManager( trans.app ) + query = irmm.get_query_for_setting_metadata_on_repositories( order=False ) # Now reset metadata on all remaining repositories. for repository in query: repository_id = trans.security.encode_id( repository.id ) try: - irmm = InstalledRepositoryMetadataManager( trans.app ) invalid_file_tups, metadata_dict = irmm.reset_all_metadata_on_installed_repository( repository_id ) if invalid_file_tups: message = tool_util.generate_message_for_invalid_tools( trans.app, diff -r 972a80267009126e558ba14142df48b897db48c8 -r e9de99ef77105d221df55771724ca56b86485a4b lib/galaxy/webapps/galaxy/controllers/admin_toolshed.py --- a/lib/galaxy/webapps/galaxy/controllers/admin_toolshed.py +++ b/lib/galaxy/webapps/galaxy/controllers/admin_toolshed.py @@ -30,6 +30,7 @@ from tool_shed.galaxy_install.metadata.installed_repository_metadata_manager import InstalledRepositoryMetadataManager from tool_shed.galaxy_install.repair_repository_manager import RepairRepositoryManager from tool_shed.galaxy_install.repository_dependencies import repository_dependency_manager +from tool_shed.galaxy_install.tools import tool_panel_manager log = logging.getLogger( __name__ ) @@ -244,10 +245,10 @@ if kwd.get( 'deactivate_or_uninstall_repository_button', False ): if tool_shed_repository.includes_tools_for_display_in_tool_panel: # Handle tool panel alterations. - tool_util.remove_from_tool_panel( trans.app, - tool_shed_repository, - shed_tool_conf, - uninstall=remove_from_disk_checked ) + tpm = tool_panel_manager.ToolPanelManager( trans.app ) + tpm.remove_from_tool_panel( tool_shed_repository, + shed_tool_conf, + uninstall=remove_from_disk_checked ) if tool_shed_repository.includes_data_managers: data_manager_util.remove_from_data_manager( trans.app, tool_shed_repository ) if tool_shed_repository.includes_datatypes: @@ -1336,13 +1337,14 @@ # its repository dependencies. includes_tool_dependencies = tool_shed_repository.includes_tool_dependencies if tool_shed_repository.includes_tools_for_display_in_tool_panel: + tpm = tool_panel_manager.ToolPanelManager( trans.app ) # Handle the selected tool panel location for loading tools included in the tool shed repository. tool_section, tool_panel_section_key = \ - tool_util.handle_tool_panel_selection( toolbox=trans.app.toolbox, - metadata=metadata, - no_changes_checked=no_changes_checked, - tool_panel_section_id=tool_panel_section_id, - new_tool_panel_section_label=new_tool_panel_section_label ) + tpm.handle_tool_panel_selection( toolbox=trans.app.toolbox, + metadata=metadata, + no_changes_checked=no_changes_checked, + tool_panel_section_id=tool_panel_section_id, + new_tool_panel_section_label=new_tool_panel_section_label ) if tool_section is not None: # Just in case the tool_section.id differs from tool_panel_section_id, which it shouldn't... tool_panel_section_id = str( tool_section.id ) @@ -1706,13 +1708,13 @@ @web.expose @web.require_admin def reset_metadata_on_selected_installed_repositories( self, trans, **kwd ): + irmm = InstalledRepositoryMetadataManager( trans.app ) if 'reset_metadata_on_selected_repositories_button' in kwd: - irmm = InstalledRepositoryMetadataManager( trans.app ) message, status = irmm.reset_metadata_on_selected_repositories( trans.user, **kwd ) else: message = kwd.get( 'message', '' ) status = kwd.get( 'status', 'done' ) - repositories_select_field = suc.build_repository_ids_select_field( trans ) + repositories_select_field = irmm.build_repository_ids_select_field( trans ) return trans.fill_template( '/admin/tool_shed_repository/reset_metadata_on_selected_repositories.mako', repositories_select_field=repositories_select_field, message=message, @@ -1942,19 +1944,19 @@ updating_installed_repository=True, persist=True ) if 'tools' in metadata_dict: + tpm = tool_panel_manager.ToolPanelManager( trans.app ) tool_panel_dict = metadata_dict.get( 'tool_panel_section', None ) if tool_panel_dict is None: tool_panel_dict = suc.generate_tool_panel_dict_from_shed_tool_conf_entries( trans.app, repository ) repository_tools_tups = suc.get_repository_tools_tups( trans.app, metadata_dict ) - tool_util.add_to_tool_panel( app=trans.app, - repository_name=str( repository.name ), - repository_clone_url=repository_clone_url, - changeset_revision=str( repository.installed_changeset_revision ), - repository_tools_tups=repository_tools_tups, - owner=str( repository.owner ), - shed_tool_conf=shed_tool_conf, - tool_panel_dict=tool_panel_dict, - new_install=False ) + tpm.add_to_tool_panel( repository_name=str( repository.name ), + repository_clone_url=repository_clone_url, + changeset_revision=str( repository.installed_changeset_revision ), + repository_tools_tups=repository_tools_tups, + owner=str( repository.owner ), + shed_tool_conf=shed_tool_conf, + tool_panel_dict=tool_panel_dict, + new_install=False ) # Add new Data Manager entries if 'data_manager' in metadata_dict: new_data_managers = data_manager_util.install_data_managers( trans.app, diff -r 972a80267009126e558ba14142df48b897db48c8 -r e9de99ef77105d221df55771724ca56b86485a4b lib/galaxy/webapps/tool_shed/api/repositories.py --- a/lib/galaxy/webapps/tool_shed/api/repositories.py +++ b/lib/galaxy/webapps/tool_shed/api/repositories.py @@ -392,7 +392,8 @@ my_writable = True handled_repository_ids = [] repository_ids = [] - query = suc.get_query_for_setting_metadata_on_repositories( trans, my_writable=my_writable, order=False ) + rmm = repository_metadata_manager.RepositoryMetadataManager( trans.app, trans.user ) + query = rmm.get_query_for_setting_metadata_on_repositories( my_writable=my_writable, order=False ) # Make sure repositories of type tool_dependency_definition are first in the list. for repository in query: if repository.type == rt_util.TOOL_DEPENDENCY_DEFINITION and repository.id not in handled_repository_ids: @@ -426,13 +427,12 @@ This param can be used as an alternative to the above encoded_ids_to_skip. """ - def handle_repository( trans, repository, results ): + def handle_repository( trans, rmm, repository, results ): log.debug( "Resetting metadata on repository %s" % str( repository.name ) ) repository_id = trans.security.encode_id( repository.id ) try: - rmm = repository_metadata_manager.RepositoryMetadataManager( trans.app ) invalid_file_tups, metadata_dict = \ - rmm.reset_all_metadata_on_repository_in_tool_shed( trans.user, repository_id ) + rmm.reset_all_metadata_on_repository_in_tool_shed( repository_id ) if invalid_file_tups: message = tool_util.generate_message_for_invalid_tools( trans.app, invalid_file_tups, @@ -451,7 +451,7 @@ status = '%s : %s' % ( str( repository.name ), message ) results[ 'repository_status' ].append( status ) return results - + rmm = repository_metadata_manager.RepositoryMetadataManager( trans.app, trans.user ) start_time = strftime( "%Y-%m-%d %H:%M:%S" ) results = dict( start_time=start_time, repository_status=[], @@ -473,7 +473,7 @@ my_writable = util.asbool( payload.get( 'my_writable', False ) ) else: my_writable = True - query = suc.get_query_for_setting_metadata_on_repositories( trans, my_writable=my_writable, order=False ) + query = rmm.get_query_for_setting_metadata_on_repositories( my_writable=my_writable, order=False ) # First reset metadata on all repositories of type repository_dependency_definition. for repository in query: encoded_id = trans.security.encode_id( repository.id ) @@ -481,7 +481,7 @@ log.debug( "Skipping repository with id %s because it is in encoded_ids_to_skip %s" % \ ( str( repository.id ), str( encoded_ids_to_skip ) ) ) elif repository.type == rt_util.TOOL_DEPENDENCY_DEFINITION and repository.id not in handled_repository_ids: - results = handle_repository( trans, repository, results ) + results = handle_repository( trans, rmm, repository, results ) # Now reset metadata on all remaining repositories. for repository in query: encoded_id = trans.security.encode_id( repository.id ) @@ -489,7 +489,7 @@ log.debug( "Skipping repository with id %s because it is in encoded_ids_to_skip %s" % \ ( str( repository.id ), str( encoded_ids_to_skip ) ) ) elif repository.type != rt_util.TOOL_DEPENDENCY_DEFINITION and repository.id not in handled_repository_ids: - results = handle_repository( trans, repository, results ) + results = handle_repository( trans, rmm, repository, results ) stop_time = strftime( "%Y-%m-%d %H:%M:%S" ) results[ 'stop_time' ] = stop_time return json.dumps( results, sort_keys=True, indent=4 ) @@ -511,10 +511,9 @@ results = dict( start_time=start_time, repository_status=[] ) try: - rmm = repository_metadata_manager.RepositoryMetadataManager( trans.app ) + rmm = repository_metadata_manager.RepositoryMetadataManager( trans.app, trans.user ) invalid_file_tups, metadata_dict = \ - rmm.reset_all_metadata_on_repository_in_tool_shed( trans.user, - trans.security.encode_id( repository.id ) ) + rmm.reset_all_metadata_on_repository_in_tool_shed( trans.security.encode_id( repository.id ) ) if invalid_file_tups: message = tool_util.generate_message_for_invalid_tools( trans.app, invalid_file_tups, diff -r 972a80267009126e558ba14142df48b897db48c8 -r e9de99ef77105d221df55771724ca56b86485a4b lib/galaxy/webapps/tool_shed/controllers/admin.py --- a/lib/galaxy/webapps/tool_shed/controllers/admin.py +++ b/lib/galaxy/webapps/tool_shed/controllers/admin.py @@ -348,13 +348,16 @@ @web.expose @web.require_admin def reset_metadata_on_selected_repositories_in_tool_shed( self, trans, **kwd ): + rmm = repository_metadata_manager.RepositoryMetadataManager( trans.app, trans.user ) if 'reset_metadata_on_selected_repositories_button' in kwd: - rmm = repository_metadata_manager.RepositoryMetadataManager( trans.app ) - message, status = rmm.reset_metadata_on_selected_repositories( trans.user, **kwd ) + message, status = rmm.reset_metadata_on_selected_repositories( **kwd ) else: message = util.restore_text( kwd.get( 'message', '' ) ) status = kwd.get( 'status', 'done' ) - repositories_select_field = suc.build_repository_ids_select_field( trans ) + repositories_select_field = rmm.build_repository_ids_select_field( name='repository_ids', + multiple=True, + display='checkboxes', + my_writable=False ) return trans.fill_template( '/webapps/tool_shed/common/reset_metadata_on_selected_repositories.mako', repositories_select_field=repositories_select_field, message=message, diff -r 972a80267009126e558ba14142df48b897db48c8 -r e9de99ef77105d221df55771724ca56b86485a4b lib/galaxy/webapps/tool_shed/controllers/hg.py --- a/lib/galaxy/webapps/tool_shed/controllers/hg.py +++ b/lib/galaxy/webapps/tool_shed/controllers/hg.py @@ -48,8 +48,8 @@ repo = hg.repository( ui.ui(), repository.repo_path( trans.app ) ) update_repository( repo, ctx_rev=None ) # Set metadata using the repository files on disk. - rmm = repository_metadata_manager.RepositoryMetadataManager( trans.app ) - error_message, status = rmm.set_repository_metadata( trans.request.host, trans.user, repository ) + rmm = repository_metadata_manager.RepositoryMetadataManager( trans.app, trans.user ) + error_message, status = rmm.set_repository_metadata( trans.request.host, repository ) if status == 'ok' and error_message: log.debug( "Successfully reset metadata on repository %s owned by %s, but encountered problem: %s" % \ ( str( repository.name ), str( repository.user.username ), error_message ) ) diff -r 972a80267009126e558ba14142df48b897db48c8 -r e9de99ef77105d221df55771724ca56b86485a4b lib/galaxy/webapps/tool_shed/controllers/repository.py --- a/lib/galaxy/webapps/tool_shed/controllers/repository.py +++ b/lib/galaxy/webapps/tool_shed/controllers/repository.py @@ -2753,9 +2753,9 @@ def reset_all_metadata( self, trans, id, **kwd ): """Reset all metadata on the complete changelog for a single repository in the tool shed.""" # This method is called only from the ~/templates/webapps/tool_shed/repository/manage_repository.mako template. - rmm = repository_metadata_manager.RepositoryMetadataManager( trans.app ) + rmm = repository_metadata_manager.RepositoryMetadataManager( trans.app, trans.user ) invalid_file_tups, metadata_dict = \ - rmm.reset_all_metadata_on_repository_in_tool_shed( trans.user, id, **kwd ) + rmm.reset_all_metadata_on_repository_in_tool_shed( id, **kwd ) if invalid_file_tups: repository = suc.get_repository_in_tool_shed( trans.app, id ) message = tool_util.generate_message_for_invalid_tools( trans.app, @@ -2774,13 +2774,16 @@ @web.expose def reset_metadata_on_my_writable_repositories_in_tool_shed( self, trans, **kwd ): + rmm = repository_metadata_manager.RepositoryMetadataManager( trans.app, trans.user ) if 'reset_metadata_on_selected_repositories_button' in kwd: - rmm = repository_metadata_manager.RepositoryMetadataManager( trans.app ) - message, status = rmm.reset_metadata_on_selected_repositories( trans.user, **kwd ) + message, status = rmm.reset_metadata_on_selected_repositories( **kwd ) else: message = kwd.get( 'message', '' ) status = kwd.get( 'status', 'done' ) - repositories_select_field = suc.build_repository_ids_select_field( trans, my_writable=True ) + repositories_select_field = rmm.build_repository_ids_select_field( name='repository_ids', + multiple=True, + display='checkboxes', + my_writable=True ) return trans.fill_template( '/webapps/tool_shed/common/reset_metadata_on_selected_repositories.mako', repositories_select_field=repositories_select_field, message=message, @@ -2840,9 +2843,8 @@ if tip == repository.tip( trans.app ): message += 'No changes to repository. ' else: - rmm = repository_metadata_manager.RepositoryMetadataManager( trans.app ) + rmm = repository_metadata_manager.RepositoryMetadataManager( trans.app, trans.user ) status, error_message = rmm.set_repository_metadata_due_to_new_tip( trans.request.host, - trans.user, repository, **kwd ) if error_message: diff -r 972a80267009126e558ba14142df48b897db48c8 -r e9de99ef77105d221df55771724ca56b86485a4b lib/galaxy/webapps/tool_shed/controllers/upload.py --- a/lib/galaxy/webapps/tool_shed/controllers/upload.py +++ b/lib/galaxy/webapps/tool_shed/controllers/upload.py @@ -262,10 +262,9 @@ ( len( files_to_remove ), upload_point ) else: message += " %d files were removed from the repository root. " % len( files_to_remove ) - rmm = repository_metadata_manager.RepositoryMetadataManager( trans.app ) + rmm = repository_metadata_manager.RepositoryMetadataManager( trans.app, trans.user ) status, error_message = \ rmm.set_repository_metadata_due_to_new_tip( trans.request.host, - trans.user, repository, content_alert_str=content_alert_str, **kwd ) diff -r 972a80267009126e558ba14142df48b897db48c8 -r e9de99ef77105d221df55771724ca56b86485a4b lib/tool_shed/capsule/capsule_manager.py --- a/lib/tool_shed/capsule/capsule_manager.py +++ b/lib/tool_shed/capsule/capsule_manager.py @@ -727,9 +727,8 @@ results_dict[ 'ok' ] = False results_dict[ 'error_message' ] += error_message try: - rmm = repository_metadata_manager.RepositoryMetadataManager( self.app ) + rmm = repository_metadata_manager.RepositoryMetadataManager( self.app, self.user ) status, error_message = rmm.set_repository_metadata_due_to_new_tip( self.host, - self.user, repository, content_alert_str=content_alert_str ) if error_message: diff -r 972a80267009126e558ba14142df48b897db48c8 -r e9de99ef77105d221df55771724ca56b86485a4b lib/tool_shed/galaxy_install/install_manager.py --- a/lib/tool_shed/galaxy_install/install_manager.py +++ b/lib/tool_shed/galaxy_install/install_manager.py @@ -33,6 +33,7 @@ from tool_shed.galaxy_install.tool_dependencies.recipe.install_environment import InstallEnvironment from tool_shed.galaxy_install.tool_dependencies.recipe.recipe_manager import StepManager from tool_shed.galaxy_install.tool_dependencies.recipe.recipe_manager import TagManager +from tool_shed.galaxy_install.tools import tool_panel_manager log = logging.getLogger( __name__ ) @@ -535,7 +536,8 @@ self.app.config.shed_tool_data_table_config, persist=True ) if 'tools' in metadata_dict: - tool_panel_dict = tool_util.generate_tool_panel_dict_for_new_install( metadata_dict[ 'tools' ], tool_section ) + tpm = tool_panel_manager.ToolPanelManager( self.app ) + tool_panel_dict = tpm.generate_tool_panel_dict_for_new_install( metadata_dict[ 'tools' ], tool_section ) sample_files = metadata_dict.get( 'sample_files', [] ) tool_index_sample_files = tool_util.get_tool_index_sample_files( sample_files ) tool_util.copy_sample_files( self.app, tool_index_sample_files, tool_path=tool_path ) @@ -555,16 +557,18 @@ sample_files_copied ) # Copy remaining sample files included in the repository to the ~/tool-data directory of the # local Galaxy instance. - tool_util.copy_sample_files( self.app, sample_files, tool_path=tool_path, sample_files_copied=sample_files_copied ) - tool_util.add_to_tool_panel( app=self.app, - repository_name=tool_shed_repository.name, - repository_clone_url=repository_clone_url, - changeset_revision=tool_shed_repository.installed_changeset_revision, - repository_tools_tups=repository_tools_tups, - owner=tool_shed_repository.owner, - shed_tool_conf=shed_tool_conf, - tool_panel_dict=tool_panel_dict, - new_install=True ) + tool_util.copy_sample_files( self.app, + sample_files, + tool_path=tool_path, + sample_files_copied=sample_files_copied ) + tpm.add_to_tool_panel( repository_name=tool_shed_repository.name, + repository_clone_url=repository_clone_url, + changeset_revision=tool_shed_repository.installed_changeset_revision, + repository_tools_tups=repository_tools_tups, + owner=tool_shed_repository.owner, + shed_tool_conf=shed_tool_conf, + tool_panel_dict=tool_panel_dict, + new_install=True ) if 'data_manager' in metadata_dict: new_data_managers = data_manager_util.install_data_managers( self.app, self.app.config.shed_data_manager_config_file, @@ -644,10 +648,11 @@ tool_shed_url = installation_dict[ 'tool_shed_url' ] # Handle contained tools. if includes_tools_for_display_in_tool_panel and ( new_tool_panel_section_label or tool_panel_section_id ): + tpm = tool_panel_manager.ToolPanelManager( self.app ) tool_panel_section_key, tool_section = \ - tool_util.handle_tool_panel_section( self.app.toolbox, - tool_panel_section_id=tool_panel_section_id, - new_tool_panel_section_label=new_tool_panel_section_label ) + tpm.handle_tool_panel_section( self.app.toolbox, + tool_panel_section_id=tool_panel_section_id, + new_tool_panel_section_label=new_tool_panel_section_label ) else: tool_panel_section_key = None tool_section = None diff -r 972a80267009126e558ba14142df48b897db48c8 -r e9de99ef77105d221df55771724ca56b86485a4b lib/tool_shed/galaxy_install/installed_repository_manager.py --- a/lib/tool_shed/galaxy_install/installed_repository_manager.py +++ b/lib/tool_shed/galaxy_install/installed_repository_manager.py @@ -11,11 +11,11 @@ from tool_shed.util import datatype_util from tool_shed.util import shed_util_common as suc from tool_shed.util import tool_dependency_util -from tool_shed.util import tool_util from tool_shed.util import xml_util from galaxy.model.orm import and_ from tool_shed.galaxy_install.repository_dependencies import repository_dependency_manager +from tool_shed.galaxy_install.tools import tool_panel_manager log = logging.getLogger( __name__ ) @@ -80,19 +80,19 @@ repository.deleted = False repository.status = self.install_model.ToolShedRepository.installation_status.INSTALLED if repository.includes_tools_for_display_in_tool_panel: + tpm = tool_panel_manager.ToolPanelManager( self.app ) metadata = repository.metadata repository_tools_tups = suc.get_repository_tools_tups( self.app, metadata ) # Reload tools into the appropriate tool panel section. tool_panel_dict = repository.metadata[ 'tool_panel_section' ] - tool_util.add_to_tool_panel( self.app, - repository.name, - repository_clone_url, - repository.installed_changeset_revision, - repository_tools_tups, - repository.owner, - shed_tool_conf, - tool_panel_dict, - new_install=False ) + tpm.add_to_tool_panel( repository.name, + repository_clone_url, + repository.installed_changeset_revision, + repository_tools_tups, + repository.owner, + shed_tool_conf, + tool_panel_dict, + new_install=False ) if repository.includes_data_managers: tp, data_manager_relative_install_dir = repository.get_tool_relative_path( self.app ) # Hack to add repository.name here, which is actually the root of the installed repository diff -r 972a80267009126e558ba14142df48b897db48c8 -r e9de99ef77105d221df55771724ca56b86485a4b lib/tool_shed/galaxy_install/metadata/installed_repository_metadata_manager.py --- a/lib/tool_shed/galaxy_install/metadata/installed_repository_metadata_manager.py +++ b/lib/tool_shed/galaxy_install/metadata/installed_repository_metadata_manager.py @@ -3,6 +3,7 @@ from galaxy import util from galaxy.util import inflector +from galaxy.web.form_builder import SelectField from tool_shed.metadata import metadata_generator @@ -19,6 +20,32 @@ super( InstalledRepositoryMetadataManager, self ).__init__( app ) self.app = app + def build_repository_ids_select_field( self, name='repository_ids', multiple=True, display='checkboxes' ): + """Generate the current list of repositories for resetting metadata.""" + repositories_select_field = SelectField( name=name, multiple=multiple, display=display ) + query = self.get_query_for_setting_metadata_on_repositories( order=True ) + for repository in query: + owner = str( repository.owner ) + option_label = '%s (%s)' % ( str( repository.name ), owner ) + option_value = '%s' % self.app.security.encode_id( repository.id ) + repositories_select_field.add_option( option_label, option_value ) + return repositories_select_field + + def get_query_for_setting_metadata_on_repositories( self, order=True ): + """ + Return a query containing repositories for resetting metadata. The order parameter + is used for displaying the list of repositories ordered alphabetically for display on + a page. When called from the Galaxy API, order is False. + """ + if order: + return self.app.install_model.context.query( self.app.install_model.ToolShedRepository ) \ + .filter( self.app.install_model.ToolShedRepository.table.c.uninstalled == False ) \ + .order_by( self.app.install_model.ToolShedRepository.table.c.name, + self.app.install_model.ToolShedRepository.table.c.owner ) + else: + return self.app.install_model.context.query( self.app.install_model.ToolShedRepository ) \ + .filter( self.app.install_model.ToolShedRepository.table.c.uninstalled == False ) + def reset_all_metadata_on_installed_repository( self, id ): """Reset all metadata on a single tool shed repository installed into a Galaxy instance.""" invalid_file_tups = [] diff -r 972a80267009126e558ba14142df48b897db48c8 -r e9de99ef77105d221df55771724ca56b86485a4b lib/tool_shed/galaxy_install/repair_repository_manager.py --- a/lib/tool_shed/galaxy_install/repair_repository_manager.py +++ b/lib/tool_shed/galaxy_install/repair_repository_manager.py @@ -5,13 +5,14 @@ from tool_shed.galaxy_install import install_manager from tool_shed.galaxy_install.repository_dependencies import repository_dependency_manager +from tool_shed.galaxy_install.tools import tool_panel_manager from tool_shed.util import common_util from tool_shed.util import container_util from tool_shed.util import shed_util_common as suc from tool_shed.util import repository_maintenance_util from tool_shed.util import tool_dependency_util -from tool_shed.util import tool_util + class RepairRepositoryManager(): @@ -119,10 +120,11 @@ tool_panel_section_id = section_dict[ 'id' ] tool_panel_section_name = section_dict[ 'name' ] if tool_panel_section_id: + tpm = tool_panel_manager.ToolPanelManager( self.app ) tool_panel_section_key, tool_panel_section = \ - tool_util.get_or_create_tool_section( self.app.toolbox, - tool_panel_section_id=tool_panel_section_id, - new_tool_panel_section_label=tool_panel_section_name ) + tpm.get_or_create_tool_section( self.app.toolbox, + tool_panel_section_id=tool_panel_section_id, + new_tool_panel_section_label=tool_panel_section_name ) else: tool_dependencies = None repo_info_dict = repository_maintenance_util.create_repo_info_dict( app=self.app, @@ -156,15 +158,17 @@ log.debug( error_message ) repair_dict [ repository.name ] = error_message elif repository.status not in [ self.app.install_model.ToolShedRepository.installation_status.INSTALLED ]: - shed_tool_conf, tool_path, relative_install_dir = suc.get_tool_panel_config_tool_path_install_dir( self.app, repository ) + shed_tool_conf, tool_path, relative_install_dir = \ + suc.get_tool_panel_config_tool_path_install_dir( self.app, repository ) # Reset the repository attributes to the New state for installation. if metadata: + tpm = tool_panel_manager.ToolPanelManager( self.app ) tool_section, tool_panel_section_key = \ - tool_util.handle_tool_panel_selection( self.app.toolbox, - metadata, - no_changes_checked=True, - tool_panel_section_id=None, - new_tool_panel_section_label=None ) + tpm.handle_tool_panel_selection( self.app.toolbox, + metadata, + no_changes_checked=True, + tool_panel_section_id=None, + new_tool_panel_section_label=None ) else: # The tools will be loaded outside of any sections in the tool panel. tool_panel_section_key = None diff -r 972a80267009126e558ba14142df48b897db48c8 -r e9de99ef77105d221df55771724ca56b86485a4b lib/tool_shed/galaxy_install/repository_dependencies/repository_dependency_manager.py --- a/lib/tool_shed/galaxy_install/repository_dependencies/repository_dependency_manager.py +++ b/lib/tool_shed/galaxy_install/repository_dependencies/repository_dependency_manager.py @@ -10,11 +10,12 @@ from galaxy.util import asbool +from tool_shed.galaxy_install.tools import tool_panel_manager + from tool_shed.util import common_util from tool_shed.util import container_util from tool_shed.util import encoding_util from tool_shed.util import shed_util_common as suc -from tool_shed.util import tool_util log = logging.getLogger( __name__ ) @@ -216,19 +217,20 @@ if can_update_db_record: # The database record for the tool shed repository currently being processed can be updated. # Get the repository metadata to see where it was previously located in the tool panel. + tpm = tool_panel_manager.ToolPanelManager( self.app ) if repository_db_record and repository_db_record.metadata: tool_section, tool_panel_section_key = \ - tool_util.handle_tool_panel_selection( toolbox=self.app.toolbox, - metadata=repository_db_record.metadata, - no_changes_checked=no_changes_checked, - tool_panel_section_id=tool_panel_section_id, - new_tool_panel_section_label=new_tool_panel_section_label ) + tpm.handle_tool_panel_selection( toolbox=self.app.toolbox, + metadata=repository_db_record.metadata, + no_changes_checked=no_changes_checked, + tool_panel_section_id=tool_panel_section_id, + new_tool_panel_section_label=new_tool_panel_section_label ) else: # We're installing a new tool shed repository that does not yet have a database record. tool_panel_section_key, tool_section = \ - tool_util.handle_tool_panel_section( self.app.toolbox, - tool_panel_section_id=tool_panel_section_id, - new_tool_panel_section_label=new_tool_panel_section_label ) + tpm.handle_tool_panel_section( self.app.toolbox, + tool_panel_section_id=tool_panel_section_id, + new_tool_panel_section_label=new_tool_panel_section_label ) tool_shed_repository = \ suc.create_or_update_tool_shed_repository( app=self.app, name=name, diff -r 972a80267009126e558ba14142df48b897db48c8 -r e9de99ef77105d221df55771724ca56b86485a4b lib/tool_shed/galaxy_install/tool_migration_manager.py --- a/lib/tool_shed/galaxy_install/tool_migration_manager.py +++ b/lib/tool_shed/galaxy_install/tool_migration_manager.py @@ -14,6 +14,7 @@ from tool_shed.galaxy_install import install_manager from tool_shed.galaxy_install.metadata.installed_repository_metadata_manager import InstalledRepositoryMetadataManager +from tool_shed.galaxy_install.tools import tool_panel_manager from tool_shed.util import basic_util from tool_shed.util import common_util @@ -30,23 +31,31 @@ class ToolMigrationManager( object ): - def __init__( self, app, latest_migration_script_number, tool_shed_install_config, migrated_tools_config, install_dependencies ): + def __init__( self, app, latest_migration_script_number, tool_shed_install_config, migrated_tools_config, + install_dependencies ): """ - Check tool settings in tool_shed_install_config and install all repositories that are not already installed. The tool - panel configuration file is the received migrated_tools_config, which is the reserved file named migrated_tools_conf.xml. + Check tool settings in tool_shed_install_config and install all repositories + that are not already installed. The tool panel configuration file is the received + migrated_tools_config, which is the reserved file named migrated_tools_conf.xml. """ self.app = app self.toolbox = self.app.toolbox self.migrated_tools_config = migrated_tools_config - # If install_dependencies is True but tool_dependency_dir is not set, do not attempt to install but print informative error message. + self.tpm = tool_panel_manager.ToolPanelManager( self.app ) + # If install_dependencies is True but tool_dependency_dir is not set, do not attempt + # to install but print informative error message. if install_dependencies and app.config.tool_dependency_dir is None: - message = 'You are attempting to install tool dependencies but do not have a value for "tool_dependency_dir" set in your universe_wsgi.ini ' - message += 'file. Set this location value to the path where you want tool dependencies installed and rerun the migration script.' + message = 'You are attempting to install tool dependencies but do not have a value ' + message += 'for "tool_dependency_dir" set in your universe_wsgi.ini file. Set this ' + message += 'location value to the path where you want tool dependencies installed and ' + message += 'rerun the migration script.' raise Exception( message ) - # Get the local non-shed related tool panel configs (there can be more than one, and the default name is tool_conf.xml). + # Get the local non-shed related tool panel configs (there can be more than one, and the + # default name is tool_conf.xml). self.proprietary_tool_confs = self.non_shed_tool_panel_configs self.proprietary_tool_panel_elems = self.get_proprietary_tool_panel_elems( latest_migration_script_number ) - # Set the location where the repositories will be installed by retrieving the tool_path setting from migrated_tools_config. + # Set the location where the repositories will be installed by retrieving the tool_path + # setting from migrated_tools_config. tree, error_message = xml_util.parse_xml( migrated_tools_config ) if tree is None: print error_message @@ -66,21 +75,24 @@ self.tool_shed = common_util.remove_protocol_and_port_from_tool_shed_url( self.tool_shed_url ) self.repository_owner = common_util.REPOSITORY_OWNER index, self.shed_config_dict = suc.get_shed_tool_conf_dict( app, self.migrated_tools_config ) - # Since tool migration scripts can be executed any number of times, we need to make sure the appropriate tools are defined in - # tool_conf.xml. If no tools associated with the migration stage are defined, no repositories will be installed on disk. - # The default behavior is that the tool shed is down. + # Since tool migration scripts can be executed any number of times, we need to + # make sure the appropriate tools are defined in tool_conf.xml. If no tools + # associated with the migration stage are defined, no repositories will be installed + # on disk. The default behavior is that the tool shed is down. tool_shed_accessible = False tool_panel_configs = common_util.get_non_shed_tool_panel_configs( app ) if tool_panel_configs: # The missing_tool_configs_dict contents are something like: # {'emboss_antigenic.xml': [('emboss', '5.0.0', 'package', '\nreadme blah blah blah\n')]} - tool_shed_accessible, missing_tool_configs_dict = common_util.check_for_missing_tools( app, - tool_panel_configs, - latest_migration_script_number ) + tool_shed_accessible, missing_tool_configs_dict = \ + common_util.check_for_missing_tools( app, + tool_panel_configs, + latest_migration_script_number ) else: - # It doesn't matter if the tool shed is accessible since there are no migrated tools defined in the local Galaxy instance, but - # we have to set the value of tool_shed_accessible to True so that the value of migrate_tools.version can be correctly set in - # the database. + # It doesn't matter if the tool shed is accessible since there are no migrated + # tools defined in the local Galaxy instance, but we have to set the value of + # tool_shed_accessible to True so that the value of migrate_tools.version can + # be correctly set in the database. tool_shed_accessible = True missing_tool_configs_dict = odict() if tool_shed_accessible: @@ -93,15 +105,18 @@ if missing_tool_configs_dict: for proprietary_tool_conf in self.proprietary_tool_confs: # Create a backup of the tool configuration in the un-migrated state. - shutil.copy( proprietary_tool_conf, '%s-pre-stage-%04d' % ( proprietary_tool_conf, latest_migration_script_number ) ) + shutil.copy( proprietary_tool_conf, '%s-pre-stage-%04d' % ( proprietary_tool_conf, + latest_migration_script_number ) ) for repository_elem in root: # Make sure we have a valid repository tag. if self.__is_valid_repository_tag( repository_elem ): - # Get all repository dependencies for the repository defined by the current repository_elem. Repository dependency - # definitions contained in tool shed repositories with migrated tools must never define a relationship to a repository - # dependency that contains a tool. The repository dependency can only contain items that are not loaded into the Galaxy - # tool panel (e.g., tool dependency definitions, custom datatypes, etc). This restriction must be followed down the - # entire dependency hierarchy. + # Get all repository dependencies for the repository defined by the + # current repository_elem. Repository dependency definitions contained + # in tool shed repositories with migrated tools must never define a + # relationship to a repository dependency that contains a tool. The + # repository dependency can only contain items that are not loaded into + # the Galaxy tool panel (e.g., tool dependency definitions, custom datatypes, + # etc). This restriction must be followed down the entire dependency hierarchy. name = repository_elem.get( 'name' ) changeset_revision = repository_elem.get( 'changeset_revision' ) tool_shed_accessible, repository_dependencies_dict = \ @@ -110,30 +125,38 @@ name, self.repository_owner, changeset_revision ) - # Make sure all repository dependency records exist (as tool_shed_repository table rows) in the Galaxy database. - created_tool_shed_repositories = self.create_or_update_tool_shed_repository_records( name, - changeset_revision, - repository_dependencies_dict ) + # Make sure all repository dependency records exist (as tool_shed_repository + # table rows) in the Galaxy database. + created_tool_shed_repositories = \ + self.create_or_update_tool_shed_repository_records( name, + changeset_revision, + repository_dependencies_dict ) # Order the repositories for proper installation. This process is similar to the # process used when installing tool shed repositories, but does not handle managing # tool panel sections and other components since repository dependency definitions # contained in tool shed repositories with migrated tools must never define a relationship # to a repository dependency that contains a tool. - ordered_tool_shed_repositories = self.order_repositories_for_installation( created_tool_shed_repositories, - repository_dependencies_dict ) + ordered_tool_shed_repositories = \ + self.order_repositories_for_installation( created_tool_shed_repositories, + repository_dependencies_dict ) for tool_shed_repository in ordered_tool_shed_repositories: - is_repository_dependency = self.__is_repository_dependency( name, changeset_revision, tool_shed_repository ) + is_repository_dependency = self.__is_repository_dependency( name, + changeset_revision, + tool_shed_repository ) self.install_repository( repository_elem, tool_shed_repository, install_dependencies, is_repository_dependency=is_repository_dependency ) else: - message = "\nNo tools associated with migration stage %s are defined in your " % str( latest_migration_script_number ) - message += "file%s named %s,\nso no repositories will be installed on disk.\n" % ( plural, file_names ) + message = "\nNo tools associated with migration stage %s are defined in your " % \ + str( latest_migration_script_number ) + message += "file%s named %s,\nso no repositories will be installed on disk.\n" % \ + ( plural, file_names ) print message else: - message = "\nThe main Galaxy tool shed is not currently available, so skipped migration stage %s.\n" % str( latest_migration_script_number ) + message = "\nThe main Galaxy tool shed is not currently available, so skipped migration stage %s.\n" % \ + str( latest_migration_script_number ) message += "Try again later.\n" print message @@ -354,16 +377,21 @@ repo_install_dir = relative_install_dir if not is_repository_dependency: for tool_elem in repository_elem: - # The tool_elem looks something like this: <tool id="EMBOSS: antigenic1" version="5.0.0" file="emboss_antigenic.xml" /> + # The tool_elem looks something like this: + # <tool id="EMBOSS: antigenic1" version="5.0.0" file="emboss_antigenic.xml" /> tool_config = tool_elem.get( 'file' ) guid = self.get_guid( repository_clone_url, relative_install_dir, tool_config ) # See if tool_config is defined inside of a section in self.proprietary_tool_panel_elems. is_displayed, tool_sections = self.get_containing_tool_sections( tool_config ) if is_displayed: tool_panel_dict_for_tool_config = \ - tool_util.generate_tool_panel_dict_for_tool_config( guid, tool_config, tool_sections=tool_sections ) + self.tpm.generate_tool_panel_dict_for_tool_config( guid, + tool_config, + tool_sections=tool_sections ) # The tool-panel_dict has the following structure. - # {<Tool guid> : [{ tool_config : <tool_config_file>, id: <ToolSection id>, version : <ToolSection version>, + # {<Tool guid> : [{ tool_config : <tool_config_file>, + # id: <ToolSection id>, + # version : <ToolSection version>, # name : <TooSection name>}]} for k, v in tool_panel_dict_for_tool_config.items(): tool_panel_dict_for_display[ k ] = v @@ -433,15 +461,14 @@ tool_path=self.tool_path, sample_files_copied=sample_files_copied ) if not is_repository_dependency: - tool_util.add_to_tool_panel( self.app, - tool_shed_repository.name, - repository_clone_url, - tool_shed_repository.installed_changeset_revision, - repository_tools_tups, - self.repository_owner, - self.migrated_tools_config, - tool_panel_dict=tool_panel_dict_for_display, - new_install=True ) + self.tpm.add_to_tool_panel( tool_shed_repository.name, + repository_clone_url, + tool_shed_repository.installed_changeset_revision, + repository_tools_tups, + self.repository_owner, + self.migrated_tools_config, + tool_panel_dict=tool_panel_dict_for_display, + new_install=True ) if install_dependencies and tool_dependencies and has_tool_dependencies: # Install tool dependencies. suc.update_tool_shed_repository_status( self.app, diff -r 972a80267009126e558ba14142df48b897db48c8 -r e9de99ef77105d221df55771724ca56b86485a4b lib/tool_shed/galaxy_install/tools/tool_panel_manager.py --- /dev/null +++ b/lib/tool_shed/galaxy_install/tools/tool_panel_manager.py @@ -0,0 +1,465 @@ +import logging +import os + +import galaxy.tools +from galaxy.tools.search import ToolBoxSearch +from xml.etree import ElementTree as XmlET + +from tool_shed.util import basic_util +from tool_shed.util import common_util +from tool_shed.util import shed_util_common as suc +from tool_shed.util import xml_util + +log = logging.getLogger( __name__ ) + + +class ToolPanelManager( object ): + + def __init__( self, app ): + self.app = app + + def add_to_shed_tool_config( self, shed_tool_conf_dict, elem_list ): + # A tool shed repository is being installed so change the shed_tool_conf file. Parse the + # config file to generate the entire list of config_elems instead of using the in-memory list + # since it will be a subset of the entire list if one or more repositories have been deactivated. + shed_tool_conf = shed_tool_conf_dict[ 'config_filename' ] + tool_path = shed_tool_conf_dict[ 'tool_path' ] + config_elems = [] + tree, error_message = xml_util.parse_xml( shed_tool_conf ) + if tree: + root = tree.getroot() + for elem in root: + config_elems.append( elem ) + # Add the elements to the in-memory list of config_elems. + for elem_entry in elem_list: + config_elems.append( elem_entry ) + # Persist the altered shed_tool_config file. + suc.config_elems_to_xml_file( self.app, config_elems, shed_tool_conf, tool_path ) + + def add_to_tool_panel( self, repository_name, repository_clone_url, changeset_revision, repository_tools_tups, owner, + shed_tool_conf, tool_panel_dict, new_install=True ): + """A tool shed repository is being installed or updated so handle tool panel alterations accordingly.""" + # We need to change the in-memory version and the file system version of the shed_tool_conf file. + index, shed_tool_conf_dict = suc.get_shed_tool_conf_dict( self.app, shed_tool_conf ) + tool_path = shed_tool_conf_dict[ 'tool_path' ] + # Generate the list of ElementTree Element objects for each section or tool. + elem_list = self.generate_tool_panel_elem_list( repository_name, + repository_clone_url, + changeset_revision, + tool_panel_dict, + repository_tools_tups, + owner=owner ) + if new_install: + # Add the new elements to the shed_tool_conf file on disk. + self.add_to_shed_tool_config( shed_tool_conf_dict, elem_list ) + # Use the new elements to add entries to the + config_elems = shed_tool_conf_dict[ 'config_elems' ] + for config_elem in elem_list: + # Add the new elements to the in-memory list of config_elems. + config_elems.append( config_elem ) + # Load the tools into the in-memory tool panel. + if config_elem.tag == 'section': + self.app.toolbox.load_section_tag_set( config_elem, tool_path, load_panel_dict=True ) + elif config_elem.tag == 'workflow': + self.app.toolbox.load_workflow_tag_set( config_elem, + self.app.toolbox.tool_panel, + self.app.toolbox.integrated_tool_panel, + load_panel_dict=True ) + elif config_elem.tag == 'tool': + guid = config_elem.get( 'guid' ) + self.app.toolbox.load_tool_tag_set( config_elem, + self.app.toolbox.tool_panel, + self.app.toolbox.integrated_tool_panel, + tool_path, + load_panel_dict=True, + guid=guid ) + # Replace the old list of in-memory config_elems with the new list for this shed_tool_conf_dict. + shed_tool_conf_dict[ 'config_elems' ] = config_elems + self.app.toolbox.shed_tool_confs[ index ] = shed_tool_conf_dict + if self.app.config.update_integrated_tool_panel: + # Write the current in-memory version of the integrated_tool_panel.xml file to disk. + self.app.toolbox.write_integrated_tool_panel_config_file() + self.app.toolbox_search = ToolBoxSearch( self.app.toolbox ) + + def generate_tool_panel_dict_for_new_install( self, tool_dicts, tool_section=None ): + """ + When installing a repository that contains tools, all tools must currently be defined + within the same tool section in the tool panel or outside of any sections. + """ + tool_panel_dict = {} + if tool_section: + section_id = tool_section.id + section_name = tool_section.name + section_version = tool_section.version or '' + else: + section_id = '' + section_name = '' + section_version = '' + for tool_dict in tool_dicts: + if tool_dict.get( 'add_to_tool_panel', True ): + guid = tool_dict[ 'guid' ] + tool_config = tool_dict[ 'tool_config' ] + tool_section_dict = dict( tool_config=tool_config, id=section_id, name=section_name, version=section_version ) + if guid in tool_panel_dict: + tool_panel_dict[ guid ].append( tool_section_dict ) + else: + tool_panel_dict[ guid ] = [ tool_section_dict ] + return tool_panel_dict + + def generate_tool_panel_dict_for_tool_config( self, guid, tool_config, tool_sections=None ): + """ + Create a dictionary of the following type for a single tool config file name. + The intent is to call this method for every tool config in a repository and + append each of these as entries to a tool panel dictionary for the repository. + This enables each tool to be loaded into a different section in the tool panel. + {<Tool guid> : + [{ tool_config : <tool_config_file>, + id: <ToolSection id>, + version : <ToolSection version>, + name : <TooSection name>}]} + """ + tool_panel_dict = {} + file_name = basic_util.strip_path( tool_config ) + tool_section_dicts = self. generate_tool_section_dicts( tool_config=file_name, + tool_sections=tool_sections ) + tool_panel_dict[ guid ] = tool_section_dicts + return tool_panel_dict + + def generate_tool_panel_elem_list( self, repository_name, repository_clone_url, changeset_revision, + tool_panel_dict, repository_tools_tups, owner='' ): + """Generate a list of ElementTree Element objects for each section or tool.""" + elem_list = [] + tool_elem = None + cleaned_repository_clone_url = common_util.remove_protocol_and_user_from_clone_url( repository_clone_url ) + if not owner: + owner = suc.get_repository_owner( cleaned_repository_clone_url ) + tool_shed = cleaned_repository_clone_url.split( '/repos/' )[ 0 ].rstrip( '/' ) + for guid, tool_section_dicts in tool_panel_dict.items(): + for tool_section_dict in tool_section_dicts: + tool_section = None + inside_section = False + section_in_elem_list = False + if tool_section_dict[ 'id' ]: + inside_section = True + # Create a new section element only if we haven't already created it. + for index, elem in enumerate( elem_list ): + if elem.tag == 'section': + section_id = elem.get( 'id', None ) + if section_id == tool_section_dict[ 'id' ]: + section_in_elem_list = True + tool_section = elem + break + if tool_section is None: + tool_section = self.generate_tool_section_element_from_dict( tool_section_dict ) + # Find the tuple containing the current guid from the list of repository_tools_tups. + for repository_tool_tup in repository_tools_tups: + tool_file_path, tup_guid, tool = repository_tool_tup + if tup_guid == guid: + break + if inside_section: + tool_elem = suc.generate_tool_elem( tool_shed, + repository_name, + changeset_revision, + owner, + tool_file_path, + tool, + tool_section ) + else: + tool_elem = suc.generate_tool_elem( tool_shed, + repository_name, + changeset_revision, + owner, + tool_file_path, + tool, + None ) + if inside_section: + if section_in_elem_list: + elem_list[ index ] = tool_section + else: + elem_list.append( tool_section ) + else: + elem_list.append( tool_elem ) + return elem_list + + def generate_tool_section_dicts( self, tool_config=None, tool_sections=None ): + tool_section_dicts = [] + if tool_config is None: + tool_config = '' + if tool_sections: + for tool_section in tool_sections: + # The value of tool_section will be None if the tool is displayed outside + # of any sections in the tool panel. + if tool_section: + section_id = tool_section.id or '' + section_version = tool_section.version or '' + section_name = tool_section.name or '' + else: + section_id = '' + section_version = '' + section_name = '' + tool_section_dicts.append( dict( tool_config=tool_config, + id=section_id, + version=section_version, + name=section_name ) ) + else: + tool_section_dicts.append( dict( tool_config=tool_config, id='', version='', name='' ) ) + return tool_section_dicts + + def generate_tool_section_element_from_dict( self, tool_section_dict ): + # The value of tool_section_dict looks like the following. + # { id: <ToolSection id>, version : <ToolSection version>, name : <TooSection name>} + if tool_section_dict[ 'id' ]: + # Create a new tool section. + tool_section = XmlET.Element( 'section' ) + tool_section.attrib[ 'id' ] = tool_section_dict[ 'id' ] + tool_section.attrib[ 'name' ] = tool_section_dict[ 'name' ] + tool_section.attrib[ 'version' ] = tool_section_dict[ 'version' ] + else: + tool_section = None + return tool_section + + def get_or_create_tool_section( self, toolbox, tool_panel_section_id, new_tool_panel_section_label=None ): + tool_panel_section_key = str( tool_panel_section_id ) + if tool_panel_section_key in toolbox.tool_panel: + # Appending a tool to an existing section in toolbox.tool_panel + tool_section = toolbox.tool_panel[ tool_panel_section_key ] + log.debug( "Appending to tool panel section: %s" % str( tool_section.name ) ) + else: + # Appending a new section to toolbox.tool_panel + if new_tool_panel_section_label is None: + # This might add an ugly section label to the tool panel, but, oh well... + new_tool_panel_section_label = tool_panel_section_id + elem = XmlET.Element( 'section' ) + elem.attrib[ 'name' ] = new_tool_panel_section_label + elem.attrib[ 'id' ] = tool_panel_section_id + elem.attrib[ 'version' ] = '' + tool_section = galaxy.tools.ToolSection( elem ) + toolbox.tool_panel[ tool_panel_section_key ] = tool_section + log.debug( "Loading new tool panel section: %s" % str( tool_section.name ) ) + return tool_panel_section_key, tool_section + + def handle_tool_panel_section( self, toolbox, tool_panel_section_id=None, new_tool_panel_section_label=None ): + """Return a ToolSection object retrieved from the current in-memory tool_panel.""" + # If tool_panel_section_id is received, the section exists in the tool panel. In this + # case, the value of the received tool_panel_section_id must be the id retrieved from a + # tool panel config (e.g., tool_conf.xml, which may have getext). If new_tool_panel_section_label + # is received, a new section will be added to the tool panel. + if new_tool_panel_section_label: + section_id = str( new_tool_panel_section_label.lower().replace( ' ', '_' ) ) + tool_panel_section_key, tool_section = \ + self.get_or_create_tool_section( toolbox, + tool_panel_section_id=section_id, + new_tool_panel_section_label=new_tool_panel_section_label ) + elif tool_panel_section_id: + tool_panel_section_key = str( tool_panel_section_id ) + tool_section = toolbox.tool_panel[ tool_panel_section_key ] + else: + return None, None + return tool_panel_section_key, tool_section + + def handle_tool_panel_selection( self, toolbox, metadata, no_changes_checked, tool_panel_section_id, + new_tool_panel_section_label ): + """ + Handle the selected tool panel location for loading tools included in tool shed + repositories when installing or reinstalling them. + """ + # Get the location in the tool panel in which each tool was originally loaded. + tool_section = None + tool_panel_section_key = None + if 'tools' in metadata: + # This forces everything to be loaded into the same section (or no section) + # in the tool panel. + if no_changes_checked: + # Make sure the no_changes check box overrides the new_tool_panel_section_label + # if the user checked the check box and entered something into the field. + new_tool_panel_section_label = None + if 'tool_panel_section' in metadata: + tool_panel_dict = metadata[ 'tool_panel_section' ] + if not tool_panel_dict: + tool_panel_dict = self.generate_tool_panel_dict_for_new_install( metadata[ 'tools' ] ) + else: + tool_panel_dict = self.generate_tool_panel_dict_for_new_install( metadata[ 'tools' ] ) + if tool_panel_dict: + # The tool_panel_dict is empty when tools exist but are not installed into a tool panel section. + tool_section_dicts = tool_panel_dict[ tool_panel_dict.keys()[ 0 ] ] + tool_section_dict = tool_section_dicts[ 0 ] + original_section_id = tool_section_dict[ 'id' ] + original_section_name = tool_section_dict[ 'name' ] + if original_section_id: + tool_panel_section_key, tool_section = \ + self.get_or_create_tool_section( toolbox, + tool_panel_section_id=original_section_id, + new_tool_panel_section_label=new_tool_panel_section_label ) + else: + # The user elected to change the tool panel section to contain the tools. + tool_panel_section_key, tool_section = \ + self.handle_tool_panel_section( toolbox, + tool_panel_section_id=tool_panel_section_id, + new_tool_panel_section_label=new_tool_panel_section_label ) + return tool_section, tool_panel_section_key + + def remove_from_shed_tool_config( self, shed_tool_conf_dict, guids_to_remove ): + # A tool shed repository is being uninstalled so change the shed_tool_conf file. + # Parse the config file to generate the entire list of config_elems instead of + # using the in-memory list since it will be a subset of the entire list if one + # or more repositories have been deactivated. + shed_tool_conf = shed_tool_conf_dict[ 'config_filename' ] + tool_path = shed_tool_conf_dict[ 'tool_path' ] + config_elems = [] + tree, error_message = xml_util.parse_xml( shed_tool_conf ) + if tree: + root = tree.getroot() + for elem in root: + config_elems.append( elem ) + config_elems_to_remove = [] + for config_elem in config_elems: + if config_elem.tag == 'section': + tool_elems_to_remove = [] + for tool_elem in config_elem: + if tool_elem.get( 'guid' ) in guids_to_remove: + tool_elems_to_remove.append( tool_elem ) + for tool_elem in tool_elems_to_remove: + # Remove all of the appropriate tool sub-elements from the section element. + config_elem.remove( tool_elem ) + if len( config_elem ) < 1: + # Keep a list of all empty section elements so they can be removed. + config_elems_to_remove.append( config_elem ) + elif config_elem.tag == 'tool': + if config_elem.get( 'guid' ) in guids_to_remove: + config_elems_to_remove.append( config_elem ) + for config_elem in config_elems_to_remove: + config_elems.remove( config_elem ) + # Persist the altered in-memory version of the tool config. + suc.config_elems_to_xml_file( self.app, config_elems, shed_tool_conf, tool_path ) + + def remove_from_tool_panel( self, repository, shed_tool_conf, uninstall ): + """ + A tool shed repository is being deactivated or uninstalled, so handle tool panel + alterations accordingly. + """ + # Determine where the tools are currently defined in the tool panel and store this + # information so the tools can be displayed in the same way when the repository is + # activated or reinstalled. + tool_panel_dict = suc.generate_tool_panel_dict_from_shed_tool_conf_entries( self.app, repository ) + repository.metadata[ 'tool_panel_section' ] = tool_panel_dict + self.app.install_model.context.add( repository ) + self.app.install_model.context.flush() + # Create a list of guids for all tools that will be removed from the in-memory tool panel + # and config file on disk. + guids_to_remove = [ k for k in tool_panel_dict.keys() ] + # Remove the tools from the toolbox's tools_by_id dictionary. + for guid_to_remove in guids_to_remove: + if guid_to_remove in self.app.toolbox.tools_by_id: + del self.app.toolbox.tools_by_id[ guid_to_remove ] + index, shed_tool_conf_dict = suc.get_shed_tool_conf_dict( self.app, shed_tool_conf ) + if uninstall: + # Remove from the shed_tool_conf file on disk. + self.remove_from_shed_tool_config( shed_tool_conf_dict, guids_to_remove ) + config_elems = shed_tool_conf_dict[ 'config_elems' ] + config_elems_to_remove = [] + for config_elem in config_elems: + if config_elem.tag == 'section': + # Get the section key for the in-memory tool panel. + section_key = str( config_elem.get( "id" ) ) + # Generate the list of tool elements to remove. + tool_elems_to_remove = [] + for tool_elem in config_elem: + if tool_elem.get( 'guid' ) in guids_to_remove: + tool_elems_to_remove.append( tool_elem ) + for tool_elem in tool_elems_to_remove: + if tool_elem in config_elem: + # Remove the tool sub-element from the section element. + config_elem.remove( tool_elem ) + # Remove the tool from the section in the in-memory tool panel. + if section_key in self.app.toolbox.tool_panel: + tool_section = self.app.toolbox.tool_panel[ section_key ] + guid = tool_elem.get( 'guid' ) + tool_key = 'tool_%s' % str( guid ) + # Get the list of versions of this tool that are currently available in the toolbox. + available_tool_versions = self.app.toolbox.get_loaded_tools_by_lineage( guid ) + if tool_key in tool_section.elems: + if available_tool_versions: + available_tool_versions.reverse() + replacement_tool_key = None + replacement_tool_version = None + # Since we are going to remove the tool from the section, replace it with the + # newest loaded version of the tool. + for available_tool_version in available_tool_versions: + available_tool_section_id, available_tool_section_name = available_tool_version.get_panel_section() + if available_tool_version.id in tool_section.elems.keys() or section_key == available_tool_section_id: + replacement_tool_key = 'tool_%s' % str( available_tool_version.id ) + replacement_tool_version = available_tool_version + break + if replacement_tool_key and replacement_tool_version: + # Get the index of the tool_key in the tool_section. + for tool_section_elems_index, key in enumerate( tool_section.elems.keys() ): + if key == tool_key: + break + # Remove the tool from the tool section. + del tool_section.elems[ tool_key ] + # Add the replacement tool at the same location in the tool section. + tool_section.elems.insert( tool_section_elems_index, + replacement_tool_key, + replacement_tool_version ) + else: + del tool_section.elems[ tool_key ] + else: + del tool_section.elems[ tool_key ] + if uninstall: + # Remove the tool from the section in the in-memory integrated tool panel. + if section_key in self.app.toolbox.integrated_tool_panel: + tool_section = self.app.toolbox.integrated_tool_panel[ section_key ] + tool_key = 'tool_%s' % str( tool_elem.get( 'guid' ) ) + if tool_key in tool_section.elems: + del tool_section.elems[ tool_key ] + if len( config_elem ) < 1: + # Keep a list of all empty section elements so they can be removed. + config_elems_to_remove.append( config_elem ) + elif config_elem.tag == 'tool': + guid = config_elem.get( 'guid' ) + if guid in guids_to_remove: + tool_key = 'tool_%s' % str( config_elem.get( 'guid' ) ) + # Get the list of versions of this tool that are currently available in the toolbox. + available_tool_versions = self.app.toolbox.get_loaded_tools_by_lineage( guid ) + if tool_key in self.app.toolbox.tool_panel: + if available_tool_versions: + available_tool_versions.reverse() + replacement_tool_key = None + replacement_tool_version = None + # Since we are going to remove the tool from the section, replace it with + # the newest loaded version of the tool. + for available_tool_version in available_tool_versions: + available_tool_section_id, available_tool_section_name = available_tool_version.get_panel_section() + if available_tool_version.id in self.app.toolbox.tool_panel.keys() or not available_tool_section_id: + replacement_tool_key = 'tool_%s' % str( available_tool_version.id ) + replacement_tool_version = available_tool_version + break + if replacement_tool_key and replacement_tool_version: + # Get the index of the tool_key in the tool_section. + for tool_panel_index, key in enumerate( self.app.toolbox.tool_panel.keys() ): + if key == tool_key: + break + # Remove the tool from the tool panel. + del self.app.toolbox.tool_panel[ tool_key ] + # Add the replacement tool at the same location in the tool panel. + self.app.toolbox.tool_panel.insert( tool_panel_index, + replacement_tool_key, + replacement_tool_version ) + else: + del self.app.toolbox.tool_panel[ tool_key ] + else: + del self.app.toolbox.tool_panel[ tool_key ] + if uninstall: + if tool_key in self.app.toolbox.integrated_tool_panel: + del self.app.toolbox.integrated_tool_panel[ tool_key ] + config_elems_to_remove.append( config_elem ) + for config_elem in config_elems_to_remove: + # Remove the element from the in-memory list of elements. + config_elems.remove( config_elem ) + # Update the config_elems of the in-memory shed_tool_conf_dict. + shed_tool_conf_dict[ 'config_elems' ] = config_elems + self.app.toolbox.shed_tool_confs[ index ] = shed_tool_conf_dict + self.app.toolbox_search = ToolBoxSearch( self.app.toolbox ) + if uninstall and self.app.config.update_integrated_tool_panel: + # Write the current in-memory version of the integrated_tool_panel.xml file to disk. + self.app.toolbox.write_integrated_tool_panel_config_file() diff -r 972a80267009126e558ba14142df48b897db48c8 -r e9de99ef77105d221df55771724ca56b86485a4b lib/tool_shed/metadata/repository_metadata_manager.py --- a/lib/tool_shed/metadata/repository_metadata_manager.py +++ b/lib/tool_shed/metadata/repository_metadata_manager.py @@ -2,11 +2,13 @@ import os import tempfile +from galaxy import util from galaxy.util import inflector -from galaxy import util +from galaxy.web.form_builder import SelectField from tool_shed.metadata import metadata_generator from tool_shed.repository_types.metadata import TipOnly +from tool_shed.repository_types import util as rt_util from tool_shed.util import basic_util from tool_shed.util import common_util @@ -20,9 +22,10 @@ class RepositoryMetadataManager( metadata_generator.MetadataGenerator ): - def __init__( self, app ): + def __init__( self, app, user ): super( RepositoryMetadataManager, self ).__init__( app ) self.app = app + self.user = user # Repository metadata comparisons for changeset revisions. self.EQUAL = 'equal' self.NO_METADATA = 'no metadata' @@ -47,6 +50,18 @@ self.sa_session.add( repository_metadata ) self.sa_session.flush() + def build_repository_ids_select_field( self, name='repository_ids', multiple=True, display='checkboxes', + my_writable=False ): + """Generate the current list of repositories for resetting metadata.""" + repositories_select_field = SelectField( name=name, multiple=multiple, display=display ) + query = self.get_query_for_setting_metadata_on_repositories( my_writable=my_writable, order=True ) + for repository in query: + owner = str( repository.user.username ) + option_label = '%s (%s)' % ( str( repository.name ), owner ) + option_value = '%s' % self.app.security.encode_id( repository.id ) + repositories_select_field.add_option( option_label, option_value ) + return repositories_select_field + def clean_repository_metadata( self, id, changeset_revisions ): # Delete all repository_metadata records associated with the repository that have # a changeset_revision that is not in changeset_revisions. We sometimes see multiple @@ -458,6 +473,54 @@ # The tool did not change through all of the changeset revisions. return old_id + def get_query_for_setting_metadata_on_repositories( self, my_writable=False, order=True ): + """ + Return a query containing repositories for resetting metadata. The order parameter + is used for displaying the list of repositories ordered alphabetically for display on + a page. When called from the Tool Shed API, order is False. + """ + # When called from the Tool Shed API, the metadata is reset on all repositories of types + # repository_suite_definition and tool_dependency_definition in addition to other selected + # repositories. + if my_writable: + username = self.user.username + clause_list = [] + for repository in self.sa_session.query( self.app.model.Repository ) \ + .filter( self.app.model.Repository.table.c.deleted == False ): + # Always reset metadata on all repositories of types repository_suite_definition and + # tool_dependency_definition. + if repository.type in [ rt_util.REPOSITORY_SUITE_DEFINITION, rt_util.TOOL_DEPENDENCY_DEFINITION ]: + clause_list.append( self.app.model.Repository.table.c.id == repository.id ) + else: + allow_push = repository.allow_push( self.app ) + if allow_push: + # Include all repositories that are writable by the current user. + allow_push_usernames = allow_push.split( ',' ) + if username in allow_push_usernames: + clause_list.append( self.app.model.Repository.table.c.id == repository.id ) + if clause_list: + if order: + return self.sa_session.query( self.app.model.Repository ) \ + .filter( or_( *clause_list ) ) \ + .order_by( self.app.model.Repository.table.c.name, + self.app.model.Repository.table.c.user_id ) + else: + return self.sa_session.query( self.app.model.Repository ) \ + .filter( or_( *clause_list ) ) + else: + # Return an empty query. + return self.sa_session.query( self.app.model.Repository ) \ + .filter( self.app.model.Repository.table.c.id == -1 ) + else: + if order: + return self.sa_session.query( self.app.model.Repository ) \ + .filter( self.app.model.Repository.table.c.deleted == False ) \ + .order_by( self.app.model.Repository.table.c.name, + self.app.model.Repository.table.c.user_id ) + else: + return self.sa_session.query( self.app.model.Repository ) \ + .filter( self.app.model.Repository.table.c.deleted == False ) + def new_datatypes_metadata_required( self, repository_metadata, metadata_dict ): """ Compare the last saved metadata for each datatype in the repository with the new metadata @@ -732,13 +795,13 @@ # repository_metadata table record is not needed. return False - def reset_all_metadata_on_repository_in_tool_shed( self, user, id ): + def reset_all_metadata_on_repository_in_tool_shed( self, id ): """Reset all metadata on a single repository in a tool shed.""" repository = suc.get_repository_in_tool_shed( self.app, id ) log.debug( "Resetting all metadata on repository: %s" % repository.name ) repo_dir = repository.repo_path( self.app ) repo = hg_util.get_repo_for_repository( self.app, repository=None, repo_path=repo_dir, create=False ) - repository_clone_url = common_util.generate_clone_url_for_repository_in_tool_shed( user, repository ) + repository_clone_url = common_util.generate_clone_url_for_repository_in_tool_shed( self.user, repository ) # The list of changeset_revisions refers to repository_metadata records that have been created # or updated. When the following loop completes, we'll delete all repository_metadata records # for this repository that do not have a changeset_revision value in this list. @@ -875,7 +938,7 @@ self.sa_session.add( repository_metadata ) self.sa_session.flush() - def reset_metadata_on_selected_repositories( self, user, **kwd ): + def reset_metadata_on_selected_repositories( self, **kwd ): """ Inspect the repository changelog to reset metadata for all appropriate changeset revisions. This method is called from both Galaxy and the Tool Shed. @@ -892,7 +955,7 @@ repository = suc.get_repository_in_tool_shed( self.app, repository_id ) owner = str( repository.user.username ) invalid_file_tups, metadata_dict = \ - self.reset_all_metadata_on_repository_in_tool_shed( user, repository_id ) + self.reset_all_metadata_on_repository_in_tool_shed( self.user, repository_id ) if invalid_file_tups: message = tool_util.generate_message_for_invalid_tools( self.app, invalid_file_tups, @@ -918,7 +981,7 @@ status = 'error' return message, status - def set_repository_metadata( self, host, user, repository, content_alert_str='', **kwd ): + def set_repository_metadata( self, host, repository, content_alert_str='', **kwd ): """ Set metadata using the repository's current disk files, returning specific error messages (if any) to alert the repository owner that the changeset has problems. @@ -926,7 +989,7 @@ message = '' status = 'done' encoded_id = self.app.security.encode_id( repository.id ) - repository_clone_url = common_util.generate_clone_url_for_repository_in_tool_shed( user, repository ) + repository_clone_url = common_util.generate_clone_url_for_repository_in_tool_shed( self.user, repository ) repo_dir = repository.repo_path( self.app ) repo = hg_util.get_repo_for_repository( self.app, repository=None, repo_path=repo_dir, create=False ) metadata_dict, invalid_file_tups = \ @@ -1027,10 +1090,9 @@ tool_util.reset_tool_data_tables( self.app ) return message, status - def set_repository_metadata_due_to_new_tip( self, host, user, repository, content_alert_str=None, **kwd ): + def set_repository_metadata_due_to_new_tip( self, host, repository, content_alert_str=None, **kwd ): """Set metadata on the repository tip in the tool shed.""" error_message, status = self.set_repository_metadata( host, - user, repository, content_alert_str=content_alert_str, **kwd ) diff -r 972a80267009126e558ba14142df48b897db48c8 -r e9de99ef77105d221df55771724ca56b86485a4b lib/tool_shed/util/shed_util_common.py --- a/lib/tool_shed/util/shed_util_common.py +++ b/lib/tool_shed/util/shed_util_common.py @@ -84,20 +84,6 @@ '${host}' """ -def build_repository_ids_select_field( trans, name='repository_ids', multiple=True, display='checkboxes', my_writable=False ): - """Method called from both Galaxy and the Tool Shed to generate the current list of repositories for resetting metadata.""" - repositories_select_field = SelectField( name=name, multiple=multiple, display=display ) - query = get_query_for_setting_metadata_on_repositories( trans, my_writable=my_writable, order=True ) - for repository in query: - if trans.webapp.name == 'tool_shed': - owner = str( repository.user.username ) - else: - owner = str( repository.owner ) - option_label = '%s (%s)' % ( str( repository.name ), owner ) - option_value = '%s' % trans.security.encode_id( repository.id ) - repositories_select_field.add_option( option_label, option_value ) - return repositories_select_field - def build_tool_dependencies_select_field( app, tool_shed_repository, name, multiple=True, display='checkboxes', uninstalled_only=False ): """Method called from Galaxy to generate the current list of tool dependency ids for an installed tool shed repository.""" tool_dependencies_select_field = SelectField( name=name, multiple=multiple, display=display ) @@ -645,66 +631,6 @@ prior_import_or_install_required_dict[ encoded_repository_id ] = prior_import_or_install_ids return prior_import_or_install_required_dict -def get_query_for_setting_metadata_on_repositories( trans, my_writable=False, order=True ): - """ - Return a query containing repositories for resetting metadata. This method is called from both the - Tool Shed and Galaxy. The my_writable parameter is ignored unless called from the Tool Shed, and the - order parameter is used for displaying the list of repositories ordered alphabetically for display on - a page. When called from either the Tool Shed or Galaxy API, order is False. - """ - if trans.webapp.name == 'tool_shed': - # When called from the Tool Shed API, the metadata is reset on all repositories of types - # repository_suite_definition and tool_dependency_definition in addition to other selected - # repositories. - if my_writable: - username = trans.user.username - clause_list = [] - for repository in trans.sa_session.query( trans.model.Repository ) \ - .filter( trans.model.Repository.table.c.deleted == False ): - # Always reset metadata on all repositories of types repository_suite_definition and - # tool_dependency_definition. - if repository.type in [ rt_util.REPOSITORY_SUITE_DEFINITION, rt_util.TOOL_DEPENDENCY_DEFINITION ]: - clause_list.append( trans.model.Repository.table.c.id == repository.id ) - else: - allow_push = repository.allow_push( trans.app ) - if allow_push: - # Include all repositories that are writable by the current user. - allow_push_usernames = allow_push.split( ',' ) - if username in allow_push_usernames: - clause_list.append( trans.model.Repository.table.c.id == repository.id ) - if clause_list: - if order: - return trans.sa_session.query( trans.model.Repository ) \ - .filter( or_( *clause_list ) ) \ - .order_by( trans.model.Repository.table.c.name, - trans.model.Repository.table.c.user_id ) - else: - return trans.sa_session.query( trans.model.Repository ) \ - .filter( or_( *clause_list ) ) - else: - # Return an empty query. - return trans.sa_session.query( trans.model.Repository ) \ - .filter( trans.model.Repository.table.c.id == -1 ) - else: - if order: - return trans.sa_session.query( trans.model.Repository ) \ - .filter( trans.model.Repository.table.c.deleted == False ) \ - .order_by( trans.model.Repository.table.c.name, - trans.model.Repository.table.c.user_id ) - else: - return trans.sa_session.query( trans.model.Repository ) \ - .filter( trans.model.Repository.table.c.deleted == False ) - else: - # We're in Galaxy. - if order: - return trans.install_model.context.query( trans.install_model.ToolShedRepository ) \ - .filter( trans.install_model.ToolShedRepository.table.c.uninstalled == False ) \ - .order_by( trans.install_model.ToolShedRepository.table.c.name, - trans.install_model.ToolShedRepository.table.c.owner ) - else: - return trans.install_model.context.query( trans.install_model.ToolShedRepository ) \ - .filter( trans.install_model.ToolShedRepository.table.c.uninstalled == False ) - def get_repo_info_tuple_contents( repo_info_tuple ): """Take care in handling the repo_info_tuple as it evolves over time as new tool shed features are introduced.""" if len( repo_info_tuple ) == 6: diff -r 972a80267009126e558ba14142df48b897db48c8 -r e9de99ef77105d221df55771724ca56b86485a4b lib/tool_shed/util/tool_util.py --- a/lib/tool_shed/util/tool_util.py +++ b/lib/tool_shed/util/tool_util.py @@ -19,69 +19,6 @@ log = logging.getLogger( __name__ ) -def add_to_shed_tool_config( app, shed_tool_conf_dict, elem_list ): - # A tool shed repository is being installed so change the shed_tool_conf file. Parse the - # config file to generate the entire list of config_elems instead of using the in-memory list - # since it will be a subset of the entire list if one or more repositories have been deactivated. - shed_tool_conf = shed_tool_conf_dict[ 'config_filename' ] - tool_path = shed_tool_conf_dict[ 'tool_path' ] - config_elems = [] - tree, error_message = xml_util.parse_xml( shed_tool_conf ) - if tree: - root = tree.getroot() - for elem in root: - config_elems.append( elem ) - # Add the elements to the in-memory list of config_elems. - for elem_entry in elem_list: - config_elems.append( elem_entry ) - # Persist the altered shed_tool_config file. - suc.config_elems_to_xml_file( app, config_elems, shed_tool_conf, tool_path ) - -def add_to_tool_panel( app, repository_name, repository_clone_url, changeset_revision, repository_tools_tups, owner, - shed_tool_conf, tool_panel_dict, new_install=True ): - """A tool shed repository is being installed or updated so handle tool panel alterations accordingly.""" - # We need to change the in-memory version and the file system version of the shed_tool_conf file. - index, shed_tool_conf_dict = suc.get_shed_tool_conf_dict( app, shed_tool_conf ) - tool_path = shed_tool_conf_dict[ 'tool_path' ] - # Generate the list of ElementTree Element objects for each section or tool. - elem_list = generate_tool_panel_elem_list( repository_name, - repository_clone_url, - changeset_revision, - tool_panel_dict, - repository_tools_tups, - owner=owner ) - if new_install: - # Add the new elements to the shed_tool_conf file on disk. - add_to_shed_tool_config( app, shed_tool_conf_dict, elem_list ) - # Use the new elements to add entries to the - config_elems = shed_tool_conf_dict[ 'config_elems' ] - for config_elem in elem_list: - # Add the new elements to the in-memory list of config_elems. - config_elems.append( config_elem ) - # Load the tools into the in-memory tool panel. - if config_elem.tag == 'section': - app.toolbox.load_section_tag_set( config_elem, tool_path, load_panel_dict=True ) - elif config_elem.tag == 'workflow': - app.toolbox.load_workflow_tag_set( config_elem, - app.toolbox.tool_panel, - app.toolbox.integrated_tool_panel, - load_panel_dict=True ) - elif config_elem.tag == 'tool': - guid = config_elem.get( 'guid' ) - app.toolbox.load_tool_tag_set( config_elem, - app.toolbox.tool_panel, - app.toolbox.integrated_tool_panel, - tool_path, - load_panel_dict=True, - guid=guid ) - # Replace the old list of in-memory config_elems with the new list for this shed_tool_conf_dict. - shed_tool_conf_dict[ 'config_elems' ] = config_elems - app.toolbox.shed_tool_confs[ index ] = shed_tool_conf_dict - if app.config.update_integrated_tool_panel: - # Write the current in-memory version of the integrated_tool_panel.xml file to disk. - app.toolbox.write_integrated_tool_panel_config_file() - app.toolbox_search = ToolBoxSearch( app.toolbox ) - def build_shed_tool_conf_select_field( app ): """Build a SelectField whose options are the keys in app.toolbox.shed_tool_confs.""" options = [] @@ -192,142 +129,6 @@ message += "%s%s%s - %s%s" % ( bold_start, tool_file, bold_end, correction_msg, new_line ) return message -def generate_tool_panel_dict_for_new_install( tool_dicts, tool_section=None ): - """ - When installing a repository that contains tools, all tools must currently be defined - within the same tool section in the tool panel or outside of any sections. - """ - tool_panel_dict = {} - if tool_section: - section_id = tool_section.id - section_name = tool_section.name - section_version = tool_section.version or '' - else: - section_id = '' - section_name = '' - section_version = '' - for tool_dict in tool_dicts: - if tool_dict.get( 'add_to_tool_panel', True ): - guid = tool_dict[ 'guid' ] - tool_config = tool_dict[ 'tool_config' ] - tool_section_dict = dict( tool_config=tool_config, id=section_id, name=section_name, version=section_version ) - if guid in tool_panel_dict: - tool_panel_dict[ guid ].append( tool_section_dict ) - else: - tool_panel_dict[ guid ] = [ tool_section_dict ] - return tool_panel_dict - -def generate_tool_panel_dict_for_tool_config( guid, tool_config, tool_sections=None ): - """ - Create a dictionary of the following type for a single tool config file name. - The intent is to call this method for every tool config in a repository and - append each of these as entries to a tool panel dictionary for the repository. - This allows for each tool to be loaded into a different section in the tool panel. - {<Tool guid> : - [{ tool_config : <tool_config_file>, - id: <ToolSection id>, - version : <ToolSection version>, - name : <TooSection name>}]} - """ - tool_panel_dict = {} - file_name = basic_util.strip_path( tool_config ) - tool_section_dicts = generate_tool_section_dicts( tool_config=file_name, tool_sections=tool_sections ) - tool_panel_dict[ guid ] = tool_section_dicts - return tool_panel_dict - -def generate_tool_panel_elem_list( repository_name, repository_clone_url, changeset_revision, tool_panel_dict, - repository_tools_tups, owner='' ): - """Generate a list of ElementTree Element objects for each section or tool.""" - elem_list = [] - tool_elem = None - cleaned_repository_clone_url = common_util.remove_protocol_and_user_from_clone_url( repository_clone_url ) - if not owner: - owner = suc.get_repository_owner( cleaned_repository_clone_url ) - tool_shed = cleaned_repository_clone_url.split( '/repos/' )[ 0 ].rstrip( '/' ) - for guid, tool_section_dicts in tool_panel_dict.items(): - for tool_section_dict in tool_section_dicts: - tool_section = None - inside_section = False - section_in_elem_list = False - if tool_section_dict[ 'id' ]: - inside_section = True - # Create a new section element only if we haven't already created it. - for index, elem in enumerate( elem_list ): - if elem.tag == 'section': - section_id = elem.get( 'id', None ) - if section_id == tool_section_dict[ 'id' ]: - section_in_elem_list = True - tool_section = elem - break - if tool_section is None: - tool_section = generate_tool_section_element_from_dict( tool_section_dict ) - # Find the tuple containing the current guid from the list of repository_tools_tups. - for repository_tool_tup in repository_tools_tups: - tool_file_path, tup_guid, tool = repository_tool_tup - if tup_guid == guid: - break - if inside_section: - tool_elem = suc.generate_tool_elem( tool_shed, - repository_name, - changeset_revision, - owner, - tool_file_path, - tool, - tool_section ) - else: - tool_elem = suc.generate_tool_elem( tool_shed, - repository_name, - changeset_revision, - owner, - tool_file_path, - tool, - None ) - if inside_section: - if section_in_elem_list: - elem_list[ index ] = tool_section - else: - elem_list.append( tool_section ) - else: - elem_list.append( tool_elem ) - return elem_list - -def generate_tool_section_dicts( tool_config=None, tool_sections=None ): - tool_section_dicts = [] - if tool_config is None: - tool_config = '' - if tool_sections: - for tool_section in tool_sections: - # The value of tool_section will be None if the tool is displayed outside - # of any sections in the tool panel. - if tool_section: - section_id = tool_section.id or '' - section_version = tool_section.version or '' - section_name = tool_section.name or '' - else: - section_id = '' - section_version = '' - section_name = '' - tool_section_dicts.append( dict( tool_config=tool_config, - id=section_id, - version=section_version, - name=section_name ) ) - else: - tool_section_dicts.append( dict( tool_config=tool_config, id='', version='', name='' ) ) - return tool_section_dicts - -def generate_tool_section_element_from_dict( tool_section_dict ): - # The value of tool_section_dict looks like the following. - # { id: <ToolSection id>, version : <ToolSection version>, name : <TooSection name>} - if tool_section_dict[ 'id' ]: - # Create a new tool section. - tool_section = XmlET.Element( 'section' ) - tool_section.attrib[ 'id' ] = tool_section_dict[ 'id' ] - tool_section.attrib[ 'name' ] = tool_section_dict[ 'name' ] - tool_section.attrib[ 'version' ] = tool_section_dict[ 'version' ] - else: - tool_section = None - return tool_section - def get_headers( fname, sep, count=60, is_multi_byte=False ): """Returns a list with the first 'count' lines split by 'sep'.""" headers = [] @@ -341,26 +142,6 @@ break return headers -def get_or_create_tool_section( toolbox, tool_panel_section_id, new_tool_panel_section_label=None ): - tool_panel_section_key = str( tool_panel_section_id ) - if tool_panel_section_key in toolbox.tool_panel: - # Appending a tool to an existing section in toolbox.tool_panel - tool_section = toolbox.tool_panel[ tool_panel_section_key ] - log.debug( "Appending to tool panel section: %s" % str( tool_section.name ) ) - else: - # Appending a new section to toolbox.tool_panel - if new_tool_panel_section_label is None: - # This might add an ugly section label to the tool panel, but, oh well... - new_tool_panel_section_label = tool_panel_section_id - elem = XmlET.Element( 'section' ) - elem.attrib[ 'name' ] = new_tool_panel_section_label - elem.attrib[ 'id' ] = tool_panel_section_id - elem.attrib[ 'version' ] = '' - tool_section = galaxy.tools.ToolSection( elem ) - toolbox.tool_panel[ tool_panel_section_key ] = tool_section - log.debug( "Loading new tool panel section: %s" % str( tool_section.name ) ) - return tool_panel_section_key, tool_section - def get_tool_path_install_dir( partial_install_dir, shed_tool_conf_dict, tool_dict, config_elems ): for elem in config_elems: if elem.tag == 'tool': @@ -514,63 +295,6 @@ error = True return error, message -def handle_tool_panel_selection( toolbox, metadata, no_changes_checked, tool_panel_section_id, new_tool_panel_section_label ): - """ - Handle the selected tool panel location for loading tools included in tool shed repositories when installing - or reinstalling them. - """ - # Get the location in the tool panel in which each tool was originally loaded. - tool_section = None - tool_panel_section_key = None - if 'tools' in metadata: - # This forces everything to be loaded into the same section (or no section) in the tool panel. - if no_changes_checked: - # Make sure the no_changes check box overrides the new_tool_panel_section_label if the user checked the check - # box and entered something into the field. - new_tool_panel_section_label = None - if 'tool_panel_section' in metadata: - tool_panel_dict = metadata[ 'tool_panel_section' ] - if not tool_panel_dict: - tool_panel_dict = generate_tool_panel_dict_for_new_install( metadata[ 'tools' ] ) - else: - tool_panel_dict = generate_tool_panel_dict_for_new_install( metadata[ 'tools' ] ) - if tool_panel_dict: - # The tool_panel_dict is empty when tools exist but are not installed into a tool panel section. - tool_section_dicts = tool_panel_dict[ tool_panel_dict.keys()[ 0 ] ] - tool_section_dict = tool_section_dicts[ 0 ] - original_section_id = tool_section_dict[ 'id' ] - original_section_name = tool_section_dict[ 'name' ] - if original_section_id: - tool_panel_section_key, tool_section = \ - get_or_create_tool_section( toolbox, - tool_panel_section_id=original_section_id, - new_tool_panel_section_label=new_tool_panel_section_label ) - else: - # The user elected to change the tool panel section to contain the tools. - tool_panel_section_key, tool_section = handle_tool_panel_section( toolbox, - tool_panel_section_id=tool_panel_section_id, - new_tool_panel_section_label=new_tool_panel_section_label ) - return tool_section, tool_panel_section_key - -def handle_tool_panel_section( toolbox, tool_panel_section_id=None, new_tool_panel_section_label=None ): - """Return a ToolSection object retrieved from the current in-memory tool_panel.""" - # If tool_panel_section_id is received, the section exists in the tool panel. In this - # case, the value of the received tool_panel_section_id must be the id retrieved from a - # tool panel config (e.g., tool_conf.xml, which may have getext). If new_tool_panel_section_label - # is received, a new section will be added to the tool panel. - if new_tool_panel_section_label: - section_id = str( new_tool_panel_section_label.lower().replace( ' ', '_' ) ) - tool_panel_section_key, tool_section = \ - get_or_create_tool_section( toolbox, - tool_panel_section_id=section_id, - new_tool_panel_section_label=new_tool_panel_section_label ) - elif tool_panel_section_id: - tool_panel_section_key = str( tool_panel_section_id ) - tool_section = toolbox.tool_panel[ tool_panel_section_key ] - else: - return None, None - return tool_panel_section_key, tool_section - def handle_tool_versions( app, tool_version_dicts, tool_shed_repository ): """ Using the list of tool_version_dicts retrieved from the tool shed (one per changeset @@ -741,170 +465,6 @@ if isinstance( tool.tool_action, UploadToolAction ): app.toolbox.reload_tool_by_id( tool_id ) -def remove_from_shed_tool_config( app, shed_tool_conf_dict, guids_to_remove ): - # A tool shed repository is being uninstalled so change the shed_tool_conf file. - # Parse the config file to generate the entire list of config_elems instead of - # using the in-memory list since it will be a subset of the entire list if one - # or more repositories have been deactivated. - shed_tool_conf = shed_tool_conf_dict[ 'config_filename' ] - tool_path = shed_tool_conf_dict[ 'tool_path' ] - config_elems = [] - tree, error_message = xml_util.parse_xml( shed_tool_conf ) - if tree: - root = tree.getroot() - for elem in root: - config_elems.append( elem ) - config_elems_to_remove = [] - for config_elem in config_elems: - if config_elem.tag == 'section': - tool_elems_to_remove = [] - for tool_elem in config_elem: - if tool_elem.get( 'guid' ) in guids_to_remove: - tool_elems_to_remove.append( tool_elem ) - for tool_elem in tool_elems_to_remove: - # Remove all of the appropriate tool sub-elements from the section element. - config_elem.remove( tool_elem ) - if len( config_elem ) < 1: - # Keep a list of all empty section elements so they can be removed. - config_elems_to_remove.append( config_elem ) - elif config_elem.tag == 'tool': - if config_elem.get( 'guid' ) in guids_to_remove: - config_elems_to_remove.append( config_elem ) - for config_elem in config_elems_to_remove: - config_elems.remove( config_elem ) - # Persist the altered in-memory version of the tool config. - suc.config_elems_to_xml_file( app, config_elems, shed_tool_conf, tool_path ) - -def remove_from_tool_panel( app, repository, shed_tool_conf, uninstall ): - """ - A tool shed repository is being deactivated or uninstalled, so handle tool panel - alterations accordingly. - """ - # Determine where the tools are currently defined in the tool panel and store this - # information so the tools can be displayed in the same way when the repository is - # activated or reinstalled. - tool_panel_dict = suc.generate_tool_panel_dict_from_shed_tool_conf_entries( app, repository ) - repository.metadata[ 'tool_panel_section' ] = tool_panel_dict - app.install_model.context.add( repository ) - app.install_model.context.flush() - # Create a list of guids for all tools that will be removed from the in-memory tool panel - # and config file on disk. - guids_to_remove = [ k for k in tool_panel_dict.keys() ] - # Remove the tools from the toolbox's tools_by_id dictionary. - for guid_to_remove in guids_to_remove: - if guid_to_remove in app.toolbox.tools_by_id: - del app.toolbox.tools_by_id[ guid_to_remove ] - index, shed_tool_conf_dict = suc.get_shed_tool_conf_dict( app, shed_tool_conf ) - if uninstall: - # Remove from the shed_tool_conf file on disk. - remove_from_shed_tool_config( app, shed_tool_conf_dict, guids_to_remove ) - config_elems = shed_tool_conf_dict[ 'config_elems' ] - config_elems_to_remove = [] - for config_elem in config_elems: - if config_elem.tag == 'section': - # Get the section key for the in-memory tool panel. - section_key = str( config_elem.get( "id" ) ) - # Generate the list of tool elements to remove. - tool_elems_to_remove = [] - for tool_elem in config_elem: - if tool_elem.get( 'guid' ) in guids_to_remove: - tool_elems_to_remove.append( tool_elem ) - for tool_elem in tool_elems_to_remove: - if tool_elem in config_elem: - # Remove the tool sub-element from the section element. - config_elem.remove( tool_elem ) - # Remove the tool from the section in the in-memory tool panel. - if section_key in app.toolbox.tool_panel: - tool_section = app.toolbox.tool_panel[ section_key ] - guid = tool_elem.get( 'guid' ) - tool_key = 'tool_%s' % str( guid ) - # Get the list of versions of this tool that are currently available in the toolbox. - available_tool_versions = app.toolbox.get_loaded_tools_by_lineage( guid ) - if tool_key in tool_section.elems: - if available_tool_versions: - available_tool_versions.reverse() - replacement_tool_key = None - replacement_tool_version = None - # Since we are going to remove the tool from the section, replace it with the - # newest loaded version of the tool. - for available_tool_version in available_tool_versions: - available_tool_section_id, available_tool_section_name = available_tool_version.get_panel_section() - if available_tool_version.id in tool_section.elems.keys() or section_key == available_tool_section_id: - replacement_tool_key = 'tool_%s' % str( available_tool_version.id ) - replacement_tool_version = available_tool_version - break - if replacement_tool_key and replacement_tool_version: - # Get the index of the tool_key in the tool_section. - for tool_section_elems_index, key in enumerate( tool_section.elems.keys() ): - if key == tool_key: - break - # Remove the tool from the tool section. - del tool_section.elems[ tool_key ] - # Add the replacement tool at the same location in the tool section. - tool_section.elems.insert( tool_section_elems_index, - replacement_tool_key, - replacement_tool_version ) - else: - del tool_section.elems[ tool_key ] - else: - del tool_section.elems[ tool_key ] - if uninstall: - # Remove the tool from the section in the in-memory integrated tool panel. - if section_key in app.toolbox.integrated_tool_panel: - tool_section = app.toolbox.integrated_tool_panel[ section_key ] - tool_key = 'tool_%s' % str( tool_elem.get( 'guid' ) ) - if tool_key in tool_section.elems: - del tool_section.elems[ tool_key ] - if len( config_elem ) < 1: - # Keep a list of all empty section elements so they can be removed. - config_elems_to_remove.append( config_elem ) - elif config_elem.tag == 'tool': - guid = config_elem.get( 'guid' ) - if guid in guids_to_remove: - tool_key = 'tool_%s' % str( config_elem.get( 'guid' ) ) - # Get the list of versions of this tool that are currently available in the toolbox. - available_tool_versions = app.toolbox.get_loaded_tools_by_lineage( guid ) - if tool_key in app.toolbox.tool_panel: - if available_tool_versions: - available_tool_versions.reverse() - replacement_tool_key = None - replacement_tool_version = None - # Since we are going to remove the tool from the section, replace it with - # the newest loaded version of the tool. - for available_tool_version in available_tool_versions: - available_tool_section_id, available_tool_section_name = available_tool_version.get_panel_section() - if available_tool_version.id in app.toolbox.tool_panel.keys() or not available_tool_section_id: - replacement_tool_key = 'tool_%s' % str( available_tool_version.id ) - replacement_tool_version = available_tool_version - break - if replacement_tool_key and replacement_tool_version: - # Get the index of the tool_key in the tool_section. - for tool_panel_index, key in enumerate( app.toolbox.tool_panel.keys() ): - if key == tool_key: - break - # Remove the tool from the tool panel. - del app.toolbox.tool_panel[ tool_key ] - # Add the replacement tool at the same location in the tool panel. - app.toolbox.tool_panel.insert( tool_panel_index, replacement_tool_key, replacement_tool_version ) - else: - del app.toolbox.tool_panel[ tool_key ] - else: - del app.toolbox.tool_panel[ tool_key ] - if uninstall: - if tool_key in app.toolbox.integrated_tool_panel: - del app.toolbox.integrated_tool_panel[ tool_key ] - config_elems_to_remove.append( config_elem ) - for config_elem in config_elems_to_remove: - # Remove the element from the in-memory list of elements. - config_elems.remove( config_elem ) - # Update the config_elems of the in-memory shed_tool_conf_dict. - shed_tool_conf_dict[ 'config_elems' ] = config_elems - app.toolbox.shed_tool_confs[ index ] = shed_tool_conf_dict - app.toolbox_search = ToolBoxSearch( app.toolbox ) - if uninstall and app.config.update_integrated_tool_panel: - # Write the current in-memory version of the integrated_tool_panel.xml file to disk. - app.toolbox.write_integrated_tool_panel_config_file() - def reset_tool_data_tables( app ): # Reset the tool_data_tables to an empty dictionary. app.tool_data_tables.data_tables = {} 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.