commit/galaxy-central: greg: Improvements in the display of repository dependencies and contents in the tool shed.
1 new commit in galaxy-central: https://bitbucket.org/galaxy/galaxy-central/changeset/519b7df6d72a/ changeset: 519b7df6d72a user: greg date: 2012-11-26 16:15:45 summary: Improvements in the display of repository dependencies and contents in the tool shed. affected #: 14 files diff -r eea034b7cc625fa294fdd1e071d99defb40f67d3 -r 519b7df6d72a28689582e02879026c04b2214f2c lib/galaxy/util/shed_util.py --- a/lib/galaxy/util/shed_util.py +++ b/lib/galaxy/util/shed_util.py @@ -1050,23 +1050,6 @@ trans.sa_session.add( tool_dependency ) trans.sa_session.flush() return removed, error_message -def to_html_str( text ): - """Translates the characters in text to an html string""" - translated = [] - for c in text: - if c in VALID_CHARS: - translated.append( c ) - elif c in MAPPED_CHARS: - translated.append( MAPPED_CHARS[ c ] ) - elif c == ' ': - translated.append( ' ' ) - elif c == '\t': - translated.append( ' ' ) - elif c == '\n': - translated.append( '<br/>' ) - elif c not in [ '\r' ]: - translated.append( '' ) - return ''.join( translated ) def tool_shed_from_repository_clone_url( repository_clone_url ): return clean_repository_clone_url( repository_clone_url ).split( 'repos' )[ 0 ].rstrip( '/' ) def translate_string( raw_text, to_html=True ): diff -r eea034b7cc625fa294fdd1e071d99defb40f67d3 -r 519b7df6d72a28689582e02879026c04b2214f2c lib/galaxy/util/shed_util_common.py --- a/lib/galaxy/util/shed_util_common.py +++ b/lib/galaxy/util/shed_util_common.py @@ -1331,6 +1331,23 @@ except: file_name = fpath return file_name +def to_html_str( text ): + """Translates the characters in text to an html string""" + translated = [] + for c in text: + if c in VALID_CHARS: + translated.append( c ) + elif c in MAPPED_CHARS: + translated.append( MAPPED_CHARS[ c ] ) + elif c == ' ': + translated.append( ' ' ) + elif c == '\t': + translated.append( ' ' ) + elif c == '\n': + translated.append( '<br/>' ) + elif c not in [ '\r' ]: + translated.append( '' ) + return ''.join( translated ) def update_existing_tool_dependency( app, repository, original_dependency_dict, new_dependencies_dict ): """ Update an exsiting tool dependency whose definition was updated in a change set pulled by a Galaxy administrator when getting updates diff -r eea034b7cc625fa294fdd1e071d99defb40f67d3 -r 519b7df6d72a28689582e02879026c04b2214f2c lib/galaxy/webapps/community/controllers/common.py --- a/lib/galaxy/webapps/community/controllers/common.py +++ b/lib/galaxy/webapps/community/controllers/common.py @@ -1,11 +1,13 @@ -import os, string, socket, logging, simplejson, binascii, tempfile, filecmp +import os, string, socket, logging, simplejson, binascii, tempfile, filecmp, threading from time import strftime from datetime import * from galaxy.datatypes.checkers import * from galaxy.tools import * +from galaxy.util.odict import odict from galaxy.util.json import from_json_string, to_json_string from galaxy.util.hash_util import * from galaxy.util.shed_util_common import * +from galaxy.webapps.community.util.container_util import * from galaxy.web.base.controller import * from galaxy.web.base.controllers.admin import * from galaxy.webapps.community import model @@ -73,9 +75,6 @@ '${host}' """ -# String separator -STRSEP = '__ESEP__' - # States for passing messages SUCCESS, INFO, WARNING, ERROR = "done", "info", "warning", "error" @@ -105,6 +104,62 @@ trans.sa_session.flush() return item_rating +def build_repository_containers( repository, changeset_revision, repository_dependencies, repository_metadata ): + containers_dict = dict( datatypes=None, + invalid_tools=None, + repository_dependencies=None, + tool_dependencies=None, + valid_tools=None, + workflows=None ) + if repository_metadata: + metadata = repository_metadata.metadata + lock = threading.Lock() + lock.acquire( True ) + try: + folder_id = 0 + # Datatypes container. + if metadata and 'datatypes' in metadata: + datatypes = metadata[ 'datatypes' ] + folder_id, datatypes_root_folder = build_datatypes_folder( folder_id, datatypes ) + containers_dict[ 'datatypes' ] = datatypes_root_folder + # Invalid tools container. + if metadata and 'invalid_tools' in metadata: + invalid_tool_configs = metadata[ 'invalid_tools' ] + folder_id, invalid_tools_root_folder = build_invalid_tools_folder( folder_id, + invalid_tool_configs, + repository, + changeset_revision, + label='Invalid tools' ) + containers_dict[ 'invalid_tools' ] = invalid_tools_root_folder + # Repository dependencies container. + folder_id, repository_dependencies_root_folder = build_repository_dependencies_folder( repository, + changeset_revision, + folder_id, + repository_dependencies ) + if repository_dependencies_root_folder: + containers_dict[ 'repository_dependencies' ] = repository_dependencies_root_folder + # Tool dependencies container. + if metadata and 'tool_dependencies' in metadata: + tool_dependencies = metadata[ 'tool_dependencies' ] + folder_id, tool_dependencies_root_folder = build_tool_dependencies_folder( folder_id, tool_dependencies ) + containers_dict[ 'tool_dependencies' ] = tool_dependencies_root_folder + # Valid tools container. + if metadata and 'tools' in metadata: + valid_tools = metadata[ 'tools' ] + folder_id, valid_tools_root_folder = build_tools_folder( folder_id, valid_tools, repository, changeset_revision, label='Valid tools' ) + containers_dict[ 'valid_tools' ] = valid_tools_root_folder + # Workflows container. + if metadata and 'workflows' in metadata: + workflows = metadata[ 'workflows' ] + folder_id, workflows_root_folder = build_workflows_folder( folder_id, workflows, repository_metadata, label='Workflows' ) + containers_dict[ 'workflows' ] = workflows_root_folder + except Exception, e: + repository_dependencies_root_folder = None + tool_dependencies_root_folder = None + log.debug( "Exception in build_repository_containers: %s" % str( e ) ) + finally: + lock.release() + return containers_dict def add_tool_versions( trans, id, repository_metadata, changeset_revisions ): # Build a dictionary of { 'tool id' : 'parent tool id' } pairs for each tool in repository_metadata. metadata = repository_metadata.metadata @@ -183,18 +238,6 @@ else: tmp_filename = None return tmp_filename -def copy_file_from_manifest( repo, ctx, filename, dir ): - """Copy the latest version of the file named filename from the repository manifest to the directory to which dir refers.""" - for changeset in reversed_upper_bounded_changelog( repo, ctx ): - changeset_ctx = repo.changectx( changeset ) - fctx = get_file_context_from_ctx( changeset_ctx, filename ) - if fctx and fctx not in [ 'DELETED' ]: - file_path = os.path.join( dir, filename ) - fh = open( file_path, 'wb' ) - fh.write( fctx.data() ) - fh.close() - return file_path - return None def generate_tool_guid( trans, repository, tool ): """ Generate a guid for the received tool. The form of the guid is @@ -285,11 +328,28 @@ fh.close() return tmp_filename return None -def get_previous_downloadable_changset_revision( repository, repo, before_changeset_revision ): +def get_next_downloadable_changeset_revision( repository, repo, after_changeset_revision ): """ - Return the downloadable changeset_revision in the repository changelog just prior to the changeset to which before_changeset_revision - refers. If there isn't one, return the hash value of an empty repository changlog, INITIAL_CHANGELOG_HASH. + Return the installable changeset_revision in the repository changelog after to the changeset to which after_changeset_revision + refers. If there isn't one, return None. """ + changeset_revisions = get_ordered_downloadable_changeset_revisions( repository, repo ) + if len( changeset_revisions ) == 1: + changeset_revision = changeset_revisions[ 0 ] + if changeset_revision == after_changeset_revision: + return None + found_after_changeset_revision = False + for changeset in repo.changelog: + changeset_revision = str( repo.changectx( changeset ) ) + if found_after_changeset_revision: + if changeset_revision in downloadable_changeset_revisions: + return changeset_revision + elif not found_after_changeset_revision and changeset_revision == after_changeset_revision: + # We've found the changeset in the changelog for which we need to get the next downloadable changset. + found_after_changeset_revision = True + return None +def get_ordered_downloadable_changeset_revisions( repository, repo ): + """Return an ordered list of changeset_revisions defined by a repository changelog.""" changeset_tups = [] for repository_metadata in repository.downloadable_revisions: changeset_revision = repository_metadata.changeset_revision @@ -299,24 +359,30 @@ else: rev = '-1' changeset_tups.append( ( rev, changeset_revision ) ) - if len( changeset_tups ) == 1: - changeset_tup = changeset_tups[ 0 ] - current_changeset_revision = changeset_tup[ 1 ] - if current_changeset_revision == before_changeset_revision: + sorted_changeset_tups = sorted( changeset_tups ) + sorted_changeset_revisions = [ changeset_tup[ 1 ] for changeset_tup in sorted_changeset_tups ] + return sorted_changeset_revisions +def get_previous_downloadable_changset_revision( repository, repo, before_changeset_revision ): + """ + Return the installable changeset_revision in the repository changelog prior to the changeset to which before_changeset_revision + refers. If there isn't one, return the hash value of an empty repository changelog, INITIAL_CHANGELOG_HASH. + """ + changeset_revisions = get_ordered_downloadable_changeset_revisions( repository, repo ) + if len( changeset_revisions ) == 1: + changeset_revision = changeset_revisions[ 0 ] + if changeset_revision == before_changeset_revision: return INITIAL_CHANGELOG_HASH - return current_changeset_revision + return changeset_revision previous_changeset_revision = None - current_changeset_revision = None - for changeset_tup in sorted( changeset_tups ): - current_changeset_revision = changeset_tup[ 1 ] - if current_changeset_revision == before_changeset_revision: + for changeset_revision in changeset_revisions: + if changeset_revision == before_changeset_revision: if previous_changeset_revision: return previous_changeset_revision else: - # Return the hash value of an empty repository changlog - note that this will not be a valid changset revision. + # Return the hash value of an empty repository changelog - note that this will not be a valid changeset revision. return INITIAL_CHANGELOG_HASH else: - previous_changeset_revision = current_changeset_revision + previous_changeset_revision = changeset_revision def get_previous_repository_reviews( trans, repository, changeset_revision ): """Return an ordered dictionary of repository reviews up to and including the received changeset revision.""" repo = hg.repository( get_configured_ui(), repository.repo_path( trans.app ) ) @@ -332,6 +398,110 @@ previous_reviews_dict[ previous_changeset_revision ] = dict( changeset_revision_label=previous_changeset_revision_label, reviews=revision_reviews ) return previous_reviews_dict +def get_repository_by_name( trans, name ): + """Get a repository from the database via name""" + return trans.sa_session.query( trans.model.Repository ).filter_by( name=name ).one() +def get_repository_by_name_and_owner( trans, name, owner ): + """Get a repository from the database via name and owner""" + user = get_user_by_username( trans, owner ) + return trans.sa_session.query( trans.model.Repository ) \ + .filter( and_( trans.model.Repository.table.c.name == name, + trans.model.Repository.table.c.user_id == user.id ) ) \ + .first() +def get_repository_dependencies_for_changeset_revision( trans, repo, repository, repository_metadata, toolshed_base_url, repository_dependencies=None, + all_repository_dependencies=None ): + """ + Return a dictionary of all repositories upon which the contents of the received repository_metadata record depend. The dictionary keys + are name-spaced values consisting of tool_shed_base_url/repository_name/repository_owner/changeset_revision and the values are lists of + repository_dependency tuples consisting of ( tool_shed_base_url, repository_name, repository_owner, changeset_revision ). This is a + recursive method, so it ensures that all required repositories to the nth degree are returned. + """ + if all_repository_dependencies is None: + all_repository_dependencies = odict() + if repository_dependencies is None: + repository_dependencies = [] + metadata = repository_metadata.metadata + if metadata and 'repository_dependencies' in metadata: + repository_dependencies_root_key = generate_repository_dependencies_key_for_repository( repository, repository_metadata.changeset_revision ) + for repository_dependency in metadata[ 'repository_dependencies' ]: + if repository_dependency not in repository_dependencies: + repository_dependencies.append( repository_dependency ) + else: + repository_dependencies_root_key = None + if repository_dependencies: + repository_dependency = repository_dependencies.pop( 0 ) + tool_shed, name, owner, changeset_revision = repository_dependency + if repository_dependencies_root_key: + if repository_dependencies_root_key in all_repository_dependencies: + # See if this repository_dependency is contained in the list associated with the repository_dependencies_root_key. + all_repository_dependencies_val = all_repository_dependencies[ repository_dependencies_root_key ] + if repository_dependency not in all_repository_dependencies_val: + all_repository_dependencies_val.append( repository_dependency ) + all_repository_dependencies[ repository_dependencies_root_key ] = all_repository_dependencies_val + else: + # Insert this repository_dependency. + all_repository_dependencies[ repository_dependencies_root_key ] = [ repository_dependency ] + if tool_shed_is_this_tool_shed( tool_shed ): + # The repository is in the current tool shed. + required_repository = get_repository_by_name_and_owner( trans, name, owner ) + required_repository_metadata = get_repository_metadata_by_repository_id_changset_revision( trans, + trans.security.encode_id( required_repository.id ), + changeset_revision ) + if required_repository_metadata: + required_repo_dir = required_repository.repo_path( trans.app ) + required_repo = hg.repository( get_configured_ui(), required_repo_dir ) + else: + # The repository changeset_revision is no longer installable, so see if there's been an update. + required_repo_dir = required_repository.repo_path( trans.app ) + required_repo = hg.repository( get_configured_ui(), required_repo_dir ) + required_repository_metadata = get_next_downloadable_changeset_revision( required_repository, required_repo, changeset_revision ) + if required_repository_metadata: + # The required_repository_metadata changeset_revision is installable. + required_metadata = required_repository_metadata.metadata + if required_metadata: + return get_repository_dependencies_for_changeset_revision( trans=trans, + repo=required_repo, + repository=required_repository, + repository_metadata=required_repository_metadata, + toolshed_base_url=tool_shed, + repository_dependencies=repository_dependencies, + all_repository_dependencies=all_repository_dependencies ) + else: + # The repository is in a different tool shed, so build an url and send a request. + raise Exception( "Repository dependencies that refer to repositories in other tool sheds is not yet supported." ) + return all_repository_dependencies +def get_repository_metadata_by_id( trans, id ): + """Get repository metadata from the database""" + return trans.sa_session.query( trans.model.RepositoryMetadata ).get( trans.security.decode_id( id ) ) +def get_repository_metadata_by_repository_id( trans, id ): + """Get all metadata records for a specified repository.""" + return trans.sa_session.query( trans.model.RepositoryMetadata ) \ + .filter( trans.model.RepositoryMetadata.table.c.repository_id == trans.security.decode_id( id ) ) +def get_repository_metadata_by_repository_id_changset_revision( trans, id, changeset_revision ): + """Get a specified metadata record for a specified repository.""" + return trans.sa_session.query( trans.model.RepositoryMetadata ) \ + .filter( and_( trans.model.RepositoryMetadata.table.c.repository_id == trans.security.decode_id( id ), + trans.model.RepositoryMetadata.table.c.changeset_revision == changeset_revision ) ) \ + .first() +def get_repository_metadata_revisions_for_review( repository, reviewed=True ): + repository_metadata_revisions = [] + metadata_changeset_revision_hashes = [] + if reviewed: + for metadata_revision in repository.metadata_revisions: + metadata_changeset_revision_hashes.append( metadata_revision.changeset_revision ) + for review in repository.reviews: + if review.changeset_revision in metadata_changeset_revision_hashes: + rmcr_hashes = [ rmr.changeset_revision for rmr in repository_metadata_revisions ] + if review.changeset_revision not in rmcr_hashes: + repository_metadata_revisions.append( review.repository_metadata ) + else: + for review in repository.reviews: + if review.changeset_revision not in metadata_changeset_revision_hashes: + metadata_changeset_revision_hashes.append( review.changeset_revision ) + for metadata_revision in repository.metadata_revisions: + if metadata_revision.changeset_revision not in metadata_changeset_revision_hashes: + repository_metadata_revisions.append( metadata_revision ) + return repository_metadata_revisions def get_rev_label_changeset_revision_from_repository_metadata( trans, repository_metadata, repository=None ): if repository is None: repository = repository_metadata.repository @@ -359,42 +529,6 @@ for changeset in repo.changelog: reversed_changelog.insert( 0, changeset ) return reversed_changelog -def get_repository_by_name( trans, name ): - """Get a repository from the database via name""" - return trans.sa_session.query( trans.model.Repository ).filter_by( name=name ).one() -def get_repository_by_name_and_owner( trans, name, owner ): - """Get a repository from the database via name and owner""" - user = get_user_by_username( trans, owner ) - return trans.sa_session.query( trans.model.Repository ) \ - .filter( and_( trans.model.Repository.table.c.name == name, - trans.model.Repository.table.c.user_id == user.id ) ) \ - .first() -def get_repository_metadata_by_id( trans, id ): - """Get repository metadata from the database""" - return trans.sa_session.query( trans.model.RepositoryMetadata ).get( trans.security.decode_id( id ) ) -def get_repository_metadata_by_repository_id( trans, id ): - """Get all metadata records for a specified repository.""" - return trans.sa_session.query( trans.model.RepositoryMetadata ) \ - .filter( trans.model.RepositoryMetadata.table.c.repository_id == trans.security.decode_id( id ) ) -def get_repository_metadata_revisions_for_review( repository, reviewed=True ): - repository_metadata_revisions = [] - metadata_changeset_revision_hashes = [] - if reviewed: - for metadata_revision in repository.metadata_revisions: - metadata_changeset_revision_hashes.append( metadata_revision.changeset_revision ) - for review in repository.reviews: - if review.changeset_revision in metadata_changeset_revision_hashes: - rmcr_hashes = [ rmr.changeset_revision for rmr in repository_metadata_revisions ] - if review.changeset_revision not in rmcr_hashes: - repository_metadata_revisions.append( review.repository_metadata ) - else: - for review in repository.reviews: - if review.changeset_revision not in metadata_changeset_revision_hashes: - metadata_changeset_revision_hashes.append( review.changeset_revision ) - for metadata_revision in repository.metadata_revisions: - if metadata_revision.changeset_revision not in metadata_changeset_revision_hashes: - repository_metadata_revisions.append( metadata_revision ) - return repository_metadata_revisions def get_review( trans, id ): """Get a repository_review from the database via id""" return trans.sa_session.query( trans.model.RepositoryReview ).get( trans.security.decode_id( id ) ) @@ -693,6 +827,8 @@ id=trans.security.encode_id( repository.id ), message=error_message, status='error' ) ) +def tool_shed_is_this_tool_shed( toolshed_base_url ): + return toolshed_base_url.rstrip( '/' ) == str( url_for( '/', qualified=True ) ).rstrip( '/' ) def update_for_browsing( trans, repository, current_working_dir, commit_message='' ): # This method id deprecated, but we'll keep it around for a while in case we need it. The problem is that hg purge # is not supported by the mercurial API. diff -r eea034b7cc625fa294fdd1e071d99defb40f67d3 -r 519b7df6d72a28689582e02879026c04b2214f2c lib/galaxy/webapps/community/controllers/repository.py --- a/lib/galaxy/webapps/community/controllers/repository.py +++ b/lib/galaxy/webapps/community/controllers/repository.py @@ -1748,9 +1748,11 @@ add_id_to_name=False, downloadable=False ) revision_label = get_revision_label( trans, repository, repository.tip( trans.app ) ) + repository_metadata = None repository_metadata_id = None metadata = None is_malicious = False + repository_dependencies = [] if changeset_revision != INITIAL_CHANGELOG_HASH: repository_metadata = get_repository_metadata_by_changeset_revision( trans, id, changeset_revision ) if repository_metadata: @@ -1768,6 +1770,15 @@ repository_metadata_id = trans.security.encode_id( repository_metadata.id ) metadata = repository_metadata.metadata is_malicious = repository_metadata.malicious + if repository_metadata: + # Get a dictionary of all repositories upon which the contents of the current repository_metadata record depend. + repository_dependencies = get_repository_dependencies_for_changeset_revision( trans, + repo, + repository, + repository_metadata, + str( url_for( '/', qualified=True ) ).rstrip( '/' ), + repository_dependencies=None, + all_repository_dependencies=None ) if is_malicious: if trans.app.security_agent.can_push( trans.app, trans.user, repository ): message += malicious_error_can_push @@ -1787,6 +1798,7 @@ review_id = trans.security.encode_id( review.id ) else: review_id = None + containers_dict = build_repository_containers( repository, changeset_revision, repository_dependencies, repository_metadata ) return trans.fill_template( '/webapps/community/repository/manage_repository.mako', cntrller=cntrller, repo_name=repo_name, @@ -1796,6 +1808,7 @@ allow_push_select_field=allow_push_select_field, repo=repo, repository=repository, + containers_dict=containers_dict, repository_metadata_id=repository_metadata_id, changeset_revision=changeset_revision, reviewed_by_user=reviewed_by_user, @@ -1865,22 +1878,35 @@ message = util.restore_text( params.get( 'message', '' ) ) status = params.get( 'status', 'done' ) repository = get_repository_in_tool_shed( trans, repository_id ) + repo_dir = repository.repo_path( trans.app ) + repo = hg.repository( get_configured_ui(), repo_dir ) changeset_revision = util.restore_text( params.get( 'changeset_revision', repository.tip( trans.app ) ) ) repository_metadata = get_repository_metadata_by_changeset_revision( trans, repository_id, changeset_revision ) if repository_metadata: repository_metadata_id = trans.security.encode_id( repository_metadata.id ), metadata = repository_metadata.metadata + # Get a dictionary of all repositories upon which the contents of the current repository_metadata record depend. + repository_dependencies = get_repository_dependencies_for_changeset_revision( trans, + repo, + repository, + repository_metadata, + str( url_for( '/', qualified=True ) ).rstrip( '/' ), + repository_dependencies=None, + all_repository_dependencies=None ) else: repository_metadata_id = None metadata = None + repository_dependencies = None revision_label = get_revision_label( trans, repository, changeset_revision ) changeset_revision_select_field = build_changeset_revision_select_field( trans, repository, selected_value=changeset_revision, add_id_to_name=False, downloadable=False ) + containers_dict = build_repository_containers( repository, changeset_revision, repository_dependencies, repository_metadata ) return trans.fill_template( '/webapps/community/repository/preview_tools_in_changeset.mako', repository=repository, + containers_dict=containers_dict, repository_metadata_id=repository_metadata_id, changeset_revision=changeset_revision, revision_label=revision_label, @@ -2408,6 +2434,7 @@ email_alerts = from_json_string( repository.email_alerts ) else: email_alerts = [] + repository_dependencies = [] user = trans.user if user and params.get( 'receive_email_alerts_button', False ): flush_needed = False @@ -2434,8 +2461,16 @@ revision_label = get_revision_label( trans, repository, changeset_revision ) repository_metadata = get_repository_metadata_by_changeset_revision( trans, id, changeset_revision ) if repository_metadata: - repository_metadata_id = trans.security.encode_id( repository_metadata.id ), + repository_metadata_id = trans.security.encode_id( repository_metadata.id ) metadata = repository_metadata.metadata + # Get a dictionary of all repositories upon which the contents of the current repository_metadata record depend. + repository_dependencies = get_repository_dependencies_for_changeset_revision( trans, + repo, + repository, + repository_metadata, + str( url_for( '/', qualified=True ) ).rstrip( '/' ), + repository_dependencies=None, + all_repository_dependencies=None ) else: repository_metadata_id = None metadata = None @@ -2456,12 +2491,14 @@ review_id = trans.security.encode_id( review.id ) else: review_id = None + containers_dict = build_repository_containers( repository, changeset_revision, repository_dependencies, repository_metadata ) return trans.fill_template( '/webapps/community/repository/view_repository.mako', cntrller=cntrller, repo=repo, repository=repository, repository_metadata_id=repository_metadata_id, metadata=metadata, + containers_dict=containers_dict, avg_rating=avg_rating, display_reviews=display_reviews, num_ratings=num_ratings, diff -r eea034b7cc625fa294fdd1e071d99defb40f67d3 -r 519b7df6d72a28689582e02879026c04b2214f2c lib/galaxy/webapps/community/controllers/repository_review.py --- a/lib/galaxy/webapps/community/controllers/repository_review.py +++ b/lib/galaxy/webapps/community/controllers/repository_review.py @@ -7,6 +7,7 @@ from galaxy.model.orm import * from sqlalchemy.sql.expression import func from common import * +from galaxy.webapps.community.util.container_util import STRSEP from repository import RepositoryGrid from galaxy.util.shed_util_common import * from galaxy.util.odict import odict diff -r eea034b7cc625fa294fdd1e071d99defb40f67d3 -r 519b7df6d72a28689582e02879026c04b2214f2c lib/galaxy/webapps/community/controllers/workflow.py --- a/lib/galaxy/webapps/community/controllers/workflow.py +++ b/lib/galaxy/webapps/community/controllers/workflow.py @@ -151,7 +151,7 @@ changeset_revision=repository_metadata.changeset_revision, repository_metadata_id=repository_metadata_id, workflow_name=workflow_name, - metadata=repository_metadata, + metadata=repository_metadata.metadata, message=message, status=status ) @web.expose diff -r eea034b7cc625fa294fdd1e071d99defb40f67d3 -r 519b7df6d72a28689582e02879026c04b2214f2c lib/galaxy/webapps/community/util/container_util.py --- /dev/null +++ b/lib/galaxy/webapps/community/util/container_util.py @@ -0,0 +1,314 @@ +import logging +from galaxy.web import url_for + +log = logging.getLogger( __name__ ) + +# String separator +STRSEP = '__ESEP__' + +class Folder( object ): + """Container object.""" + def __init__( self, id=None, key=None, label=None ): + self.id = id + self.key = key + self.label = label + self.datatypes = [] + self.folders = [] + self.invalid_tools = [] + self.valid_tools = [] + self.tool_dependencies = [] + self.repository_dependencies = [] + self.workflows = [] + def contains_folder( self, folder ): + for index, contained_folder in enumerate( self.folders ): + if folder == contained_folder: + return index, contained_folder + return 0, None + +class Datatype( object ): + """Datatype object""" + def __init__( self, id=None, extension=None, type=None, mimetype=None, subclass=None ): + self.id = id + self.extension = extension + self.type = type + self.mimetype = mimetype + self.subclass = subclass + +class InvalidTool( object ): + """Invalid tool object""" + def __init__( self, id=None, tool_config=None, repository_id=None, changeset_revision=None ): + self.id = id + self.tool_config = tool_config + self.repository_id = repository_id + self.changeset_revision = changeset_revision + +class RepositoryDependency( object ): + """Repository dependency object""" + def __init__( self, id=None, toolshed=None, repository_name=None, repository_owner=None, changeset_revision=None ): + self.id = id + self.toolshed = toolshed + self.repository_name = repository_name + self.repository_owner = repository_owner + self.changeset_revision = changeset_revision + +class Tool( object ): + """Tool object""" + def __init__( self, id=None, tool_config=None, tool_id=None, name=None, description=None, version=None, requirements=None, + repository_id=None, changeset_revision=None ): + self.id = id + self.tool_config = tool_config + self.tool_id = tool_id + self.name = name + self.description = description + self.version = version + self.requirements = requirements + self.repository_id = repository_id + self.changeset_revision = changeset_revision + +class ToolDependency( object ): + """Tool dependency object""" + def __init__( self, id=None, name=None, version=None, type=None ): + self.id = id + self.name = name + self.version = version + self.type = type + +class Workflow( object ): + """Workflow object""" + def __init__( self, id=None, repository_metadata_id=None, workflow_name=None, steps=None, format_version=None, annotation=None ): + self.id = id + self.repository_metadata_id = repository_metadata_id + self.workflow_name = workflow_name + self.steps = steps + self.format_version = format_version + self.annotation = annotation + +def build_datatypes_folder( folder_id, datatypes, label='Datatypes' ): + """Return a folder hierarchy containing datatypes.""" + if datatypes: + datatype_id = 0 + folder_id += 1 + datatypes_root_folder = Folder( id=folder_id, key='root', label='root' ) + folder_id += 1 + folder = Folder( id=folder_id, key='datatypes', label=label ) + datatypes_root_folder.folders.append( folder ) + # Insert a header row. + datatype_id += 1 + datatype = Datatype( id=datatype_id, + extension='extension', + type='type', + mimetype='mimetype', + subclass='subclass' ) + folder.datatypes.append( datatype ) + for datatypes_dict in datatypes: + datatype_id += 1 + datatype = Datatype( id=datatype_id, + extension=datatypes_dict.get( 'extension', '' ), + type=datatypes_dict.get( 'dtype', '' ), + mimetype=datatypes_dict.get( 'mimetype', '' ), + subclass=datatypes_dict.get( 'subclass', '' ) ) + folder.datatypes.append( datatype ) + else: + datatypes_root_folder = None + return folder_id, datatypes_root_folder +def build_invalid_tools_folder( folder_id, invalid_tool_configs, repository, changeset_revision, label='Invalid tools' ): + """Return a folder hierarchy containing invalid tools.""" + if invalid_tool_configs: + invalid_tool_id = 0 + folder_id += 1 + invalid_tools_root_folder = Folder( id=folder_id, key='root', label='root' ) + folder_id += 1 + folder = Folder( id=folder_id, key='invalid_tools', label=label ) + invalid_tools_root_folder.folders.append( folder ) + for invalid_tool_config in invalid_tool_configs: + invalid_tool_id += 1 + invalid_tool = InvalidTool( id=invalid_tool_id, + tool_config=invalid_tool_config, + repository_id=repository.id, + changeset_revision=changeset_revision ) + folder.invalid_tools.append( invalid_tool ) + else: + invalid_tools_root_folder = None + return folder_id, invalid_tools_root_folder +def build_repository_dependencies_folder( repository, changeset_revision, folder_id, repository_dependencies, label='Repository dependencies' ): + """Return a folder hierarchy containing repository dependencies.""" + if repository_dependencies: + repository_dependency_id = 0 + folder_id += 1 + # Create the root folder. + repository_dependencies_root_folder = Folder( id=folder_id, key='root', label='root' ) + folder_id += 1 + # Create the Repository dependencies folder and add it to the root folder. + key = generate_repository_dependencies_key_for_repository( repository, changeset_revision ) + repository_dependencies_folder = Folder( id=folder_id, key=key, label=label ) + repository_dependencies_root_folder.folders.append( repository_dependencies_folder ) + # Process the repository dependencies. + for key, val in repository_dependencies.items(): + # Only create a new folder object if necessary. + folder = get_folder( repository_dependencies_root_folder, key ) + if not folder: + # Create a new folder. + folder_id += 1 + label = generate_repository_dependencies_folder_label_from_key( repository, changeset_revision, key ) + folder = Folder( id=folder_id, key=key, label=label ) + for repository_dependency_tup in val: + toolshed, name, owner, changeset_revision = repository_dependency_tup + if not is_folder( repository_dependencies.keys(), toolshed, name, owner, changeset_revision ): + # Create a new repository_dependency. + repository_dependency_id += 1 + repository_dependency = RepositoryDependency( id=repository_dependency_id, + toolshed=toolshed, + repository_name=name, + repository_owner=owner, + changeset_revision=changeset_revision ) + # Insert the repository_dependency into the folder. + folder.repository_dependencies.append( repository_dependency ) + if not get_folder( repository_dependencies_folder, key ): + # Insert the folder into the list. + repository_dependencies_folder.folders.append( folder ) + else: + repository_dependencies_root_folder = None + return folder_id, repository_dependencies_root_folder +def build_tools_folder( folder_id, tool_dicts, repository, changeset_revision, valid=True, label='Valid tools' ): + """Return a folder hierarchy containing valid tools.""" + if tool_dicts: + tool_id = 0 + folder_id += 1 + tools_root_folder = Folder( id=folder_id, key='root', label='root' ) + folder_id += 1 + folder = Folder( id=folder_id, key='tools', label=label ) + tools_root_folder.folders.append( folder ) + # Insert a header row. + tool_id += 1 + tool = Tool( id=tool_id, + tool_config='', + tool_id='', + name='Name', + description='Description', + version='Version', + requirements='', + repository_id='', + changeset_revision='' ) + folder.valid_tools.append( tool ) + for tool_dict in tool_dicts: + tool_id += 1 + if 'requirements' in tool_dict: + requirements = tool_dict[ 'requirements' ] + requirements_str = '' + for requirement_dict in requirements: + requirements_str += '%s (%s), ' % ( requirement_dict[ 'name' ], requirement_dict[ 'type' ] ) + requirements_str = requirements_str.rstrip( ', ' ) + else: + requirements_str = 'none' + tool = Tool( id=tool_id, + tool_config=tool_dict[ 'tool_config' ], + tool_id=tool_dict[ 'id' ], + name=tool_dict[ 'name' ], + description=tool_dict[ 'description' ], + version=tool_dict[ 'version' ], + requirements=requirements_str, + repository_id=repository.id, + changeset_revision=changeset_revision ) + folder.valid_tools.append( tool ) + else: + tools_root_folder = None + return folder_id, tools_root_folder +def build_tool_dependencies_folder( folder_id, tool_dependencies, label='Tool dependencies' ): + """Return a folder hierarchy containing tool dependencies.""" + if tool_dependencies: + tool_dependency_id = 0 + folder_id += 1 + tool_dependencies_root_folder = Folder( id=folder_id, key='root', label='root' ) + folder_id += 1 + folder = Folder( id=folder_id, key='tool_dependencies', label=label ) + tool_dependencies_root_folder.folders.append( folder ) + # Insert a header row. + tool_dependency_id += 1 + tool_dependency = ToolDependency( id=tool_dependency_id, + name='Name', + version='Version', + type='Type' ) + folder.tool_dependencies.append( tool_dependency ) + for dependency_key, requirements_dict in tool_dependencies.items(): + tool_dependency_id += 1 + if dependency_key == 'set_environment': + version = None + else: + version = requirements_dict[ 'version' ] + tool_dependency = ToolDependency( id=tool_dependency_id, + name=requirements_dict[ 'name' ], + version=version, + type=requirements_dict[ 'type' ] ) + folder.tool_dependencies.append( tool_dependency ) + else: + tool_dependencies_root_folder = None + return folder_id, tool_dependencies_root_folder +def build_workflows_folder( folder_id, workflows, repository_metadata, label='Workflows' ): + """Return a folder hierarchy containing invalid tools.""" + if workflows: + workflow_id = 0 + folder_id += 1 + workflows_root_folder = Folder( id=folder_id, key='root', label='root' ) + folder_id += 1 + folder = Folder( id=folder_id, key='workflows', label=label ) + workflows_root_folder.folders.append( folder ) + # Insert a header row. + workflow_id += 1 + workflow = Workflow( id=workflow_id, + repository_metadata_id=None, + workflow_name='Name', + steps='steps', + format_version='format-version', + annotation='annotation' ) + folder.workflows.append( workflow ) + for workflow_tup in workflows: + workflow_dict=workflow_tup[ 1 ] + steps = workflow_dict.get( 'steps', [] ) + if steps: + steps = str( len( steps ) ) + else: + steps = 'unknown' + workflow_id += 1 + workflow = Workflow( id=workflow_id, + repository_metadata_id=repository_metadata.id, + workflow_name=workflow_dict[ 'name' ], + steps=steps, + format_version=workflow_dict[ 'format-version' ], + annotation=workflow_dict[ 'annotation' ] ) + folder.workflows.append( workflow ) + else: + workflows_root_folder = None + return folder_id, workflows_root_folder +def generate_repository_dependencies_folder_label_from_key( repository, changeset_revision, key ): + """Return a repository dependency label based on the repository dependency key.""" + if key_is_current_repositorys_key( repository, changeset_revision, key ): + label = 'Repository dependencies' + else: + toolshed_base_url, name, owner, revision = get_components_from_key( key ) + label = "Repository <b>%s</b> revision <b>%s</b> owned by <b>%s</b>" % ( name, revision, owner ) + return label +def generate_repository_dependencies_key_for_repository( repository, changeset_revision ): + # FIXME: assumes tool shed is current tool shed since repository dependencies across tool sheds is not yet supported. + toolshed_base_url = str( url_for( '/', qualified=True ) ).rstrip( '/' ) + return '%s%s%s%s%s%s%s' % ( toolshed_base_url, STRSEP, repository.name, STRSEP, repository.user.username, STRSEP, changeset_revision ) +def get_folder( folder, key ): + if folder and folder.key == key: + return folder + for sub_folder in folder.folders: + return get_folder( sub_folder, key ) + return None +def get_components_from_key( key ): + # FIXME: assumes tool shed is current tool shed since repository dependencies across tool sheds is not yet supported. + items = key.split( STRSEP ) + toolshed_base_url = items[ 0 ] + repository_name = items[ 1 ] + repository_owner = items[ 2 ] + changeset_revision = items[ 3 ] + return toolshed_base_url, repository_name, repository_owner, changeset_revision +def is_folder( folder_keys, toolshed_base_url, repository_name, repository_owner, changeset_revision ): + key = '%s%s%s%s%s%s%s' % ( toolshed_base_url, STRSEP, repository_name, STRSEP, repository_owner, STRSEP, changeset_revision ) + return key in folder_keys +def key_is_current_repositorys_key( repository, changeset_revision, key ): + toolshed_base_url, repository_name, repository_owner, changeset_revision = get_components_from_key( key ) + return repository_name == repository.name and repository_owner == repository.user.username and repository_changeset_revision == changeset_revision + \ No newline at end of file diff -r eea034b7cc625fa294fdd1e071d99defb40f67d3 -r 519b7df6d72a28689582e02879026c04b2214f2c templates/webapps/community/repository/common.mako --- a/templates/webapps/community/repository/common.mako +++ b/templates/webapps/community/repository/common.mako @@ -75,6 +75,93 @@ </script></%def> +<%def name="dependency_javascripts()"> + <script type="text/javascript"> + var init_dependencies = function() { + var storage_id = "library-expand-state-${trans.security.encode_id(10000)}"; + var restore_folder_state = function() { + var state = $.jStorage.get(storage_id); + if (state) { + for (var id in state) { + if (state[id] === true) { + var row = $("#" + id), + index = row.parent().children().index(row); + row.addClass("expanded").show(); + row.siblings().filter("tr[parent='" + index + "']").show(); + } + } + } + }; + var save_folder_state = function() { + var state = {}; + $("tr.folderRow").each( function() { + var folder = $(this); + state[folder.attr("id")] = folder.hasClass("expanded"); + }); + $.jStorage.set(storage_id, state); + }; + $(".container-table").each(function() { + //var container_id = this.id.split( "-" )[0]; + //alert( container_id ); + var child_of_parent_cache = {}; + // Recursively fill in children and descendants of each row + var process_row = function(q, parents) { + // Find my index + var parent = q.parent(), + this_level = child_of_parent_cache[parent] || (child_of_parent_cache[parent] = parent.children()); + var index = this_level.index(q); + // Find my immediate children + var children = $(par_child_dict[index]); + // Recursively handle them + var descendants = children; + children.each( function() { + child_descendants = process_row( $(this), parents.add(q) ); + descendants = descendants.add(child_descendants); + }); + // Set up expand / hide link + var expand_fn = function() { + if ( q.hasClass("expanded") ) { + descendants.hide(); + descendants.removeClass("expanded"); + q.removeClass("expanded"); + } else { + children.show(); + q.addClass("expanded"); + } + save_folder_state(); + }; + $("." + q.attr("id") + "-click").click(expand_fn); + // return descendants for use by parent + return descendants; + } + // Initialize dict[parent_id] = rows_which_have_that_parent_id_as_parent_attr + var par_child_dict = {}, + no_parent = []; + $(this).find("tbody tr").each( function() { + if ( $(this).attr("parent")) { + var parent = $(this).attr("parent"); + if (par_child_dict[parent] !== undefined) { + par_child_dict[parent].push(this); + } else { + par_child_dict[parent] = [this]; + } + } else { + no_parent.push(this); + } + }); + $(no_parent).each( function() { + descendants = process_row( $(this), $([]) ); + descendants.hide(); + }); + }); + restore_folder_state(); + }; + $(function() { + init_dependencies(); + }); + </script> +</%def> + <%def name="render_clone_str( repository )"><% from galaxy.util.shed_util_common import generate_clone_url_for_repository_in_tool_shed @@ -83,272 +170,337 @@ hg clone <a href="${clone_str}">${clone_str}</a></%def> -<%def name="render_repository_items( repository_metadata_id, changeset_revision, metadata, can_set_metadata=False )"> - <% from galaxy.tool_shed.encoding_util import tool_shed_encode %> - %if metadata or can_set_metadata: +<%def name="render_folder( folder, folder_pad, parent=None, row_counter=None, is_root_folder=False )"> + <% + encoded_id = trans.security.encode_id( folder.id ) + + if is_root_folder: + pad = folder_pad + expander = h.url_for("/static/images/silk/resultset_bottom.png") + folder_img = h.url_for("/static/images/silk/folder_page.png") + else: + pad = folder_pad + 20 + expander = h.url_for("/static/images/silk/resultset_next.png") + folder_img = h.url_for("/static/images/silk/folder.png") + my_row = None + %> + %if not is_root_folder: + <% + if parent is None: + bg_str = 'bgcolor="#D8D8D8"' + else: + bg_str = '' + %> + <tr id="folder-${encoded_id}" ${bg_str} class="folderRow libraryOrFolderRow" + %if parent is not None: + parent="${parent}" + style="display: none;" + %endif + > + <% + col_span_str = '' + if folder.datatypes: + label = folder.label + col_span_str = 'colspan="4"' + elif folder.label == 'Repository dependencies': + label = "%s<i> - this repository requires installation of these additional repositories</i>" % folder.label + elif folder.repository_dependencies: + label = folder.label + elif folder.invalid_tools: + label = "%s<i> - click the tool config file name to see why the tool is invalid</i>" % folder.label + elif folder.tool_dependencies: + label = "%s<i> - this repository's tools require installation of these dependencies</i>" % folder.label + col_span_str = 'colspan="3"' + elif folder.valid_tools: + label = "%s<i> - click the name to preview the tool and use the pop-up menu to inspect all metadata</i>" % folder.label + col_span_str = 'colspan="3"' + elif folder.workflows: + label = folder.label + col_span_str = 'colspan="4"' + %> + <td ${col_span_str} style="padding-left: ${folder_pad}px;"> + <span class="expandLink folder-${encoded_id}-click"> + <div style="float: left; margin-left: 2px;" class="expandLink folder-${encoded_id}-click"> + <a class="folder-${encoded_id}-click" href="javascript:void(0);"> + ${label} + </a> + </div> + </span> + <td> + </tr> + <% + my_row = row_counter.count + row_counter.increment() + %> + %endif + %for sub_folder in folder.folders: + ${render_folder( sub_folder, pad, parent=my_row, row_counter=row_counter, is_root_folder=False )} + %endfor + %for repository_dependency in folder.repository_dependencies: + ${render_repository_dependency( repository_dependency, pad, my_row, row_counter )} + %endfor + %for index, tool_dependency in enumerate( folder.tool_dependencies ): + <% row_is_header = index == 0 %> + ${render_tool_dependency( tool_dependency, pad, my_row, row_counter, row_is_header )} + %endfor + %if folder.valid_tools: + %for index, tool in enumerate( folder.valid_tools ): + <% row_is_header = index == 0 %> + ${render_tool( tool, pad, my_row, row_counter, row_is_header )} + %endfor + %endif + %for invalid_tool in folder.invalid_tools: + ${render_invalid_tool( invalid_tool, pad, my_row, row_counter )} + %endfor + %if folder.workflows: + %for index, workflow in enumerate( folder.workflows ): + <% row_is_header = index == 0 %> + ${render_workflow( workflow, pad, my_row, row_counter, row_is_header )} + %endfor + %endif + %if folder.datatypes: + %for index, datatype in enumerate( folder.datatypes ): + <% row_is_header = index == 0 %> + ${render_datatype( datatype, pad, my_row, row_counter, row_is_header )} + %endfor + %endif +</%def> + +<%def name="render_datatype( datatype, pad, parent, row_counter, row_is_header=False )"> + <% + encoded_id = trans.security.encode_id( datatype.id ) + if row_is_header: + cell_type = 'th' + else: + cell_type = 'td' + %> + <tr class="datasetRow" + %if parent is not None: + parent="${parent}" + %endif + id="libraryItem-${encoded_id}"> + <${cell_type} style="padding-left: ${pad+20}px;">${datatype.extension | h}</${cell_type}> + <${cell_type}>${datatype.type | h}</${cell_type}> + <${cell_type}>${datatype.mimetype | h}</${cell_type}> + <${cell_type}>${datatype.subclass | h}</${cell_type}> + </tr> + <% + my_row = row_counter.count + row_counter.increment() + %> +</%def> + +<%def name="render_invalid_tool( invalid_tool, pad, parent, row_counter, valid=True )"> + <% encoded_id = trans.security.encode_id( invalid_tool.id ) %> + <tr class="datasetRow" + %if parent is not None: + parent="${parent}" + %endif + id="libraryItem-${encoded_id}"> + <td style="padding-left: ${pad+20}px;"> + <a class="view-info" href="${h.url_for( controller='repository', action='load_invalid_tool', repository_id=trans.security.encode_id( invalid_tool.repository_id ), tool_config=invalid_tool.tool_config, changeset_revision=invalid_tool.changeset_revision )}"> + ${invalid_tool.tool_config | h} + </a> + </td> + </tr> + <% + my_row = row_counter.count + row_counter.increment() + %> +</%def> + +<%def name="render_repository_dependency( repository_dependency, pad, parent, row_counter )"> + + <% encoded_id = trans.security.encode_id( repository_dependency.id ) %> + <tr class="datasetRow" + %if parent is not None: + parent="${parent}" + %endif + id="libraryItem-${encoded_id}"> + ##<td style="padding-left: ${pad+20}px;">${repository_dependency.toolshed | h}</td> + <td style="padding-left: ${pad+20}px;">Repository <b>${repository_dependency.repository_name | h}</b> revision <b>${repository_dependency.changeset_revision | h}</b> owned by <b>${repository_dependency.repository_owner | h}</b></td> + </tr> + <% + my_row = row_counter.count + row_counter.increment() + %> +</%def> + +<%def name="render_tool( tool, pad, parent, row_counter, row_is_header )"> + <% + encoded_id = trans.security.encode_id( tool.id ) + if row_is_header: + cell_type = 'th' + else: + cell_type = 'td' + %> + <tr class="datasetRow" + %if parent is not None: + parent="${parent}" + %endif + id="libraryItem-${encoded_id}"> + %if row_is_header: + <th style="padding-left: ${pad+20}px;">${tool.name | h}</th> + %else: + <td style="padding-left: ${pad+20}px;"> + <div style="float:left;" class="menubutton split popup" id="tool-${encoded_id}-popup"> + <a class="view-info" href="${h.url_for( controller='repository', action='display_tool', repository_id=trans.security.encode_id( tool.repository_id ), tool_config=tool.tool_config, changeset_revision=tool.changeset_revision )}">${tool.name | h}</a> + </div> + <div popupmenu="tool-${encoded_id}-popup"> + <a class="action-button" href="${h.url_for( controller='repository', action='view_tool_metadata', repository_id=trans.security.encode_id( tool.repository_id ), changeset_revision=tool.changeset_revision, tool_id=tool.tool_id )}">View tool metadata</a> + </div> + </td> + %endif + <${cell_type}>${tool.description | h}</${cell_type}> + <${cell_type}>${tool.version | h}</${cell_type}> + ##<${cell_type}>${tool.requirements | h}</${cell_type}> + </tr> + <% + my_row = row_counter.count + row_counter.increment() + %> +</%def> + +<%def name="render_tool_dependency( tool_dependency, pad, parent, row_counter, row_is_header )"> + <% + encoded_id = trans.security.encode_id( tool_dependency.id ) + if row_is_header: + cell_type = 'th' + else: + cell_type = 'td' + %> + <tr class="datasetRow" + %if parent is not None: + parent="${parent}" + %endif + id="libraryItem-${encoded_id}"> + <${cell_type} style="padding-left: ${pad+20}px;">${tool_dependency.name | h}</${cell_type}> + <${cell_type}> + <% + if tool_dependency.version: + version_str = tool_dependency.version + else: + version_str = '' + %> + ${version_str | h} + </${cell_type}> + <${cell_type}>${tool_dependency.type | h}</${cell_type}> + </tr> + <% + my_row = row_counter.count + row_counter.increment() + %> +</%def> + +<%def name="render_workflow( workflow, pad, parent, row_counter, row_is_header=False )"> + <% + from galaxy.tool_shed.encoding_util import tool_shed_encode + encoded_id = trans.security.encode_id( workflow.id ) + if row_is_header: + cell_type = 'th' + else: + cell_type = 'td' + %> + <tr class="datasetRow" + %if parent is not None: + parent="${parent}" + %endif + id="libraryItem-${encoded_id}"> + <${cell_type} style="padding-left: ${pad+20}px;"> + %if row_is_header: + ${workflow.workflow_name | h} + %else: + <a href="${h.url_for( controller='workflow', action='view_workflow', repository_metadata_id=trans.security.encode_id( workflow.repository_metadata_id ), workflow_name=tool_shed_encode( workflow.workflow_name ) )}">${workflow.workflow_name | h}</a> + %endif + </${cell_type}> + <${cell_type}>${workflow.steps | h}</${cell_type}> + <${cell_type}>${workflow.format_version | h}</${cell_type}> + <${cell_type}>${workflow.annotation | h}</${cell_type}> + </tr> + <% + my_row = row_counter.count + row_counter.increment() + %> +</%def> + +<%def name="render_repository_items( repository_metadata_id, changeset_revision, metadata, containers_dict, can_set_metadata=False )"> + <% + from galaxy.tool_shed.encoding_util import tool_shed_encode + + has_datatypes = metadata and 'datatypes' in metadata + has_readme = metadata and 'readme' in metadata + has_workflows = metadata and 'workflows' in metadata + + datatypes_root_folder = containers_dict[ 'datatypes' ] + invalid_tools_root_folder = containers_dict[ 'invalid_tools' ] + repository_dependencies_root_folder = containers_dict[ 'repository_dependencies' ] + tool_dependencies_root_folder = containers_dict[ 'tool_dependencies' ] + valid_tools_root_folder = containers_dict[ 'valid_tools' ] + workflows_root_folder = containers_dict[ 'workflows' ] + + has_contents = datatypes_root_folder, invalid_tools_root_folder or valid_tools_root_folder or workflows_root_folder + + class RowCounter( object ): + def __init__( self ): + self.count = 0 + def increment( self ): + self.count += 1 + def __str__( self ): + return str( self.count ) + %> + %if repository_dependencies_root_folder or tool_dependencies_root_folder: + <div class="toolForm"> + <div class="toolFormTitle">Dependencies of this repository</div> + <div class="toolFormBody"> + %if repository_dependencies_root_folder: + <p/> + <% row_counter = RowCounter() %> + <table cellspacing="0" cellpadding="0" border="0" width="100%" class="tables container-table" id="repository_dependencies"> + ${self.render_folder( repository_dependencies_root_folder, 0, parent=None, row_counter=row_counter, is_root_folder=True )} + </table> + %endif + %if tool_dependencies_root_folder: + <p/> + <% row_counter = RowCounter() %> + <table cellspacing="0" cellpadding="0" border="0" width="100%" class="tables container-table" id="tool_dependencies"> + ${self.render_folder( tool_dependencies_root_folder, 0, parent=None, row_counter=row_counter, is_root_folder=True )} + </table> + %endif + </div> + </div> + %endif + %if has_contents: <p/><div class="toolForm"> - <div class="toolFormTitle">Preview tools and inspect metadata by tool version</div> + <div class="toolFormTitle">Contents of this repository</div><div class="toolFormBody"> - %if metadata: - %if 'repository_dependencies' in metadata: - <div class="form-row"> - <table class="grid"> - <tr> - <td><b>tool shed</b></td> - <td><b>name</b></td> - <td><b>version</b></td> - <td><b>type</b></td> - </tr> - %for repository_dependency_tup in metadata[ 'repository_dependencies' ]: - <% toolshed, name, owner, changeset_revision = repository_dependency_tup %> - <tr> - <td>${toolshed | h}</td> - <td>${name | h}</td> - <td>${owner | h}</td> - <td>${changeset_revision | h}</td> - </tr> - %endfor - </table> - </div> - <div style="clear: both"></div> - %endif - %if 'tool_dependencies' in metadata: - <% - # See if tool dependencies are packages, environment settings or both. - tool_dependencies = metadata[ 'tool_dependencies' ] - contains_packages = False - for k in tool_dependencies.keys(): - if k != 'set_environment': - contains_packages = True - break - contains_env_settings = 'set_environment' in tool_dependencies.keys() - %> - %if contains_packages: - <div class="form-row"> - <table width="100%"> - <tr bgcolor="#D8D8D8" width="100%"> - <td><b>The following tool dependencies can optionally be automatically installed</i></td> - </tr> - </table> - </div> - <div style="clear: both"></div> - <div class="form-row"> - <table class="grid"> - <tr> - <td><b>name</b></td> - <td><b>version</b></td> - <td><b>type</b></td> - </tr> - %for dependency_key, requirements_dict in tool_dependencies.items(): - %if dependency_key != 'set_environment': - <% - name = requirements_dict[ 'name' ] - version = requirements_dict[ 'version' ] - type = requirements_dict[ 'type' ] - %> - <tr> - <td>${name | h}</td> - <td>${version | h}</td> - <td>${type | h}</td> - </tr> - %endif - %endfor - </table> - </div> - <div style="clear: both"></div> - %endif - %if contains_env_settings: - <div class="form-row"> - <table width="100%"> - <tr bgcolor="#D8D8D8" width="100%"> - <td><b>The following environment settings can optionally be handled as part of the installation</i></td> - </tr> - </table> - </div> - <div style="clear: both"></div> - <div class="form-row"> - <table class="grid"> - <tr> - <td><b>name</b></td> - <td><b>type</b></td> - </tr> - <% environment_settings = tool_dependencies[ 'set_environment' ] %> - %for requirements_dict in environment_settings: - <tr> - <td>${requirements_dict[ 'name' ] | h}</td> - <td>${requirements_dict[ 'type' ] | h}</td> - </tr> - %endfor - </table> - </div> - <div style="clear: both"></div> - %endif - %endif - %if 'tools' in metadata: - <div class="form-row"> - <table width="100%"> - <tr bgcolor="#D8D8D8" width="100%"> - <td><b>Valid tools</b><i> - click the name to preview the tool and use the pop-up menu to inspect all metadata</i></td> - </tr> - </table> - </div> - <div class="form-row"> - <% tool_dicts = metadata[ 'tools' ] %> - <table class="grid"> - <tr> - <td><b>name</b></td> - <td><b>description</b></td> - <td><b>version</b></td> - <td><b>requirements</b></td> - </tr> - %for index, tool_dict in enumerate( tool_dicts ): - <tr> - <td> - <div style="float:left;" class="menubutton split popup" id="tool-${index}-popup"> - <a class="view-info" href="${h.url_for( controller='repository', action='display_tool', repository_id=trans.security.encode_id( repository.id ), tool_config=tool_dict[ 'tool_config' ], changeset_revision=changeset_revision )}">${tool_dict[ 'name' ]}</a> - </div> - <div popupmenu="tool-${index}-popup"> - <a class="action-button" href="${h.url_for( controller='repository', action='view_tool_metadata', repository_id=trans.security.encode_id( repository.id ), changeset_revision=changeset_revision, tool_id=tool_dict[ 'id' ] )}">View tool metadata</a> - </div> - </td> - <td>${tool_dict[ 'description' ] | h}</td> - <td>${tool_dict[ 'version' ] | h}</td> - <td> - <% - if 'requirements' in tool_dict: - requirements = tool_dict[ 'requirements' ] - else: - requirements = None - %> - %if requirements: - <% - requirements_str = '' - for requirement_dict in tool_dict[ 'requirements' ]: - requirements_str += '%s (%s), ' % ( requirement_dict[ 'name' ], requirement_dict[ 'type' ] ) - requirements_str = requirements_str.rstrip( ', ' ) - %> - ${requirements_str | h} - %else: - none - %endif - </td> - </tr> - %endfor - </table> - </div> - <div style="clear: both"></div> - %endif - %if 'invalid_tools' in metadata: - <div class="form-row"> - <table width="100%"> - <tr bgcolor="#D8D8D8" width="100%"> - <td><b>Invalid tools</b><i> - click the tool config file name to see why the tool is invalid</i></td> - </tr> - </table> - </div> - <div style="clear: both"></div> - <div class="form-row"> - <% invalid_tool_configs = metadata[ 'invalid_tools' ] %> - <table class="grid"> - %for invalid_tool_config in invalid_tool_configs: - <tr> - <td> - <a class="view-info" href="${h.url_for( controller='repository', action='load_invalid_tool', repository_id=trans.security.encode_id( repository.id ), tool_config=invalid_tool_config, changeset_revision=changeset_revision )}"> - ${invalid_tool_config | h} - </a> - </td> - </tr> - %endfor - </table> - </div> - <div style="clear: both"></div> - %endif - %if 'workflows' in metadata: - ## metadata[ 'workflows' ] is a list of tuples where each contained tuple is - ## [ <relative path to the .ga file in the repository>, <exported workflow dict> ] - <div class="form-row"> - <table width="100%"> - <tr bgcolor="#D8D8D8" width="100%"> - <td><b>Workflows</b></td> - </tr> - </table> - </div> - <div style="clear: both"></div> - <div class="form-row"> - <% workflow_tups = metadata[ 'workflows' ] %> - <table class="grid"> - <tr> - <td><b>name</b></td> - <td><b>steps</b></td> - <td><b>format-version</b></td> - <td><b>annotation</b></td> - </tr> - %for workflow_tup in workflow_tups: - <% - relative_path = workflow_tup[0] - workflow_dict = workflow_tup[1] - workflow_name = workflow_dict[ 'name' ] - ## Initially steps were not stored in the metadata record. - steps = workflow_dict.get( 'steps', [] ) - format_version = workflow_dict[ 'format-version' ] - annotation = workflow_dict[ 'annotation' ] - %> - <tr> - <td> - <a href="${h.url_for( controller='workflow', action='view_workflow', repository_metadata_id=repository_metadata_id, workflow_name=tool_shed_encode( workflow_name ) )}">${workflow_name | h}</a> - </td> - <td> - %if steps: - ${len( steps )} - %else: - unknown - %endif - </td> - <td>${format_version | h}</td> - <td>${annotation | h}</td> - </tr> - %endfor - </table> - </div> - <div style="clear: both"></div> - %endif - %if 'datatypes' in metadata: - <div class="form-row"> - <table width="100%"> - <tr bgcolor="#D8D8D8" width="100%"> - <td><b>Data types</b></td> - </tr> - </table> - </div> - <div style="clear: both"></div> - <div class="form-row"> - <% datatypes_dicts = metadata[ 'datatypes' ] %> - <table class="grid"> - <tr> - <td><b>extension</b></td> - <td><b>type</b></td> - <td><b>mimetype</b></td> - <td><b>subclass</b></td> - </tr> - %for datatypes_dict in datatypes_dicts: - <% - extension = datatypes_dict.get( 'extension', ' ' ) - dtype = datatypes_dict.get( 'dtype', ' ' ) - mimetype = datatypes_dict.get( 'mimetype', ' ' ) - subclass = datatypes_dict.get( 'subclass', ' ' ) - %> - <tr> - <td>${extension | h}</td> - <td>${dtype | h}</td> - <td>${mimetype | h}</td> - <td>${subclass | h}</td> - </tr> - %endfor - </table> - </div> - <div style="clear: both"></div> - %endif + %if valid_tools_root_folder: + <p/> + <% row_counter = RowCounter() %> + <table cellspacing="0" cellpadding="0" border="0" width="100%" class="tables container-table" id="valid_tools"> + ${self.render_folder( valid_tools_root_folder, 0, parent=None, row_counter=row_counter, is_root_folder=True )} + </table> + %endif + %if invalid_tools_root_folder: + <p/> + <% row_counter = RowCounter() %> + <table cellspacing="0" cellpadding="0" border="0" width="100%" class="tables container-table" id="invalid_tools"> + ${self.render_folder( invalid_tools_root_folder, 0, parent=None, row_counter=row_counter, is_root_folder=True )} + </table> + %endif + %if workflows_root_folder: + <p/> + <% row_counter = RowCounter() %> + <table cellspacing="0" cellpadding="0" border="0" width="100%" class="tables container-table" id="workflows"> + ${self.render_folder( workflows_root_folder, 0, parent=None, row_counter=row_counter, is_root_folder=True )} + </table> + %endif + %if datatypes_root_folder: + <p/> + <% row_counter = RowCounter() %> + <table cellspacing="0" cellpadding="0" border="0" width="100%" class="tables container-table" id="datatypes"> + ${self.render_folder( datatypes_root_folder, 0, parent=None, row_counter=row_counter, is_root_folder=True )} + </table> %endif </div></div> diff -r eea034b7cc625fa294fdd1e071d99defb40f67d3 -r 519b7df6d72a28689582e02879026c04b2214f2c templates/webapps/community/repository/manage_repository.mako --- a/templates/webapps/community/repository/manage_repository.mako +++ b/templates/webapps/community/repository/manage_repository.mako @@ -16,10 +16,6 @@ can_set_metadata = not is_new and not is_deprecated can_rate = not is_new and not is_deprecated and trans.user and repository.user != trans.user can_view_change_log = not is_new - if can_push: - browse_label = 'Browse or delete repository tip files' - else: - browse_label = 'Browse repository tip files' can_set_malicious = metadata and can_set_metadata and is_admin and changeset_revision == repository.tip( trans.app ) can_deprecate = not is_new and trans.user and ( is_admin or repository.user == trans.user ) and not is_deprecated can_undeprecate = trans.user and ( is_admin or repository.user == trans.user ) and is_deprecated @@ -27,6 +23,11 @@ has_readme = metadata and 'readme' in metadata can_review_repository = not is_deprecated and trans.app.security_agent.user_can_review_repositories( trans.user ) reviewing_repository = cntrller and cntrller == 'repository_review' + + if can_push: + browse_label = 'Browse or delete repository tip files' + else: + browse_label = 'Browse repository tip files' if changeset_revision == repository.tip( trans.app ): tip_str = 'repository tip' else: @@ -42,10 +43,15 @@ %><%inherit file="${inherit(context)}"/> +<%def name="stylesheets()"> + ${parent.stylesheets()} + ${h.css( "library" )} +</%def> + <%def name="javascripts()"> ${parent.javascripts()} - ${h.js( "libs/jquery/jquery.rating" )} - ${common_javascripts(repository)} + ${h.js("libs/jquery/jquery.rating", "libs/jquery/jstorage" )} + ${dependency_javascripts()} </%def><br/><br/> @@ -204,7 +210,7 @@ </form></div></div> -${render_repository_items( repository_metadata_id, changeset_revision, metadata, can_set_metadata=True )} +${render_repository_items( repository_metadata_id, changeset_revision, metadata, containers_dict, can_set_metadata=True )} <p/><div class="toolForm"><div class="toolFormTitle">Manage categories</div> diff -r eea034b7cc625fa294fdd1e071d99defb40f67d3 -r 519b7df6d72a28689582e02879026c04b2214f2c templates/webapps/community/repository/preview_tools_in_changeset.mako --- a/templates/webapps/community/repository/preview_tools_in_changeset.mako +++ b/templates/webapps/community/repository/preview_tools_in_changeset.mako @@ -28,10 +28,15 @@ %><%inherit file="${inherit(context)}"/> +<%def name="stylesheets()"> + ${parent.stylesheets()} + ${h.css( "library" )} +</%def> + <%def name="javascripts()"> ${parent.javascripts()} - ${h.js( "libs/jquery/jquery.rating" )} - ${common_javascripts(repository)} + ${h.js("libs/jquery/jquery.rating", "libs/jquery/jstorage" )} + ${dependency_javascripts()} </%def><br/><br/> @@ -79,4 +84,4 @@ </div></div><p/> -${render_repository_items( repository_metadata_id, changeset_revision, metadata, can_set_metadata=False )} +${render_repository_items( repository_metadata_id, changeset_revision, metadata, containers_dict, can_set_metadata=False )} diff -r eea034b7cc625fa294fdd1e071d99defb40f67d3 -r 519b7df6d72a28689582e02879026c04b2214f2c templates/webapps/community/repository/view_repository.mako --- a/templates/webapps/community/repository/view_repository.mako +++ b/templates/webapps/community/repository/view_repository.mako @@ -32,10 +32,15 @@ %><%inherit file="${inherit(context)}"/> +<%def name="stylesheets()"> + ${parent.stylesheets()} + ${h.css( "library" )} +</%def> + <%def name="javascripts()"> ${parent.javascripts()} - ${h.js( "libs/jquery/jquery.rating" )} - ${common_javascripts(repository)} + ${h.js("libs/jquery/jquery.rating", "libs/jquery/jstorage" )} + ${dependency_javascripts()} </%def><br/><br/> @@ -181,7 +186,7 @@ %endif </div></div> -${render_repository_items( repository_metadata_id, changeset_revision, metadata, can_set_metadata=False )} +${render_repository_items( repository_metadata_id, changeset_revision, metadata, containers_dict, can_set_metadata=False )} %if repository.categories: <p/><div class="toolForm"> diff -r eea034b7cc625fa294fdd1e071d99defb40f67d3 -r 519b7df6d72a28689582e02879026c04b2214f2c templates/webapps/community/repository_review/browse_review.mako --- a/templates/webapps/community/repository_review/browse_review.mako +++ b/templates/webapps/community/repository_review/browse_review.mako @@ -4,7 +4,7 @@ <% from galaxy.web.form_builder import CheckboxField - from galaxy.webapps.community.controllers.common import STRSEP + from galaxy.webapps.community.util.container_util import STRSEP can_manage_repository = is_admin or repository.user == trans.user %> diff -r eea034b7cc625fa294fdd1e071d99defb40f67d3 -r 519b7df6d72a28689582e02879026c04b2214f2c templates/webapps/community/repository_review/edit_review.mako --- a/templates/webapps/community/repository_review/edit_review.mako +++ b/templates/webapps/community/repository_review/edit_review.mako @@ -5,7 +5,7 @@ <% from galaxy.web.form_builder import CheckboxField from galaxy.webapps.community.controllers.repository_review import build_approved_select_field - from galaxy.webapps.community.controllers.common import STRSEP + from galaxy.webapps.community.util.container_util import STRSEP can_manage_repository = is_admin or repository.user == trans.user %> diff -r eea034b7cc625fa294fdd1e071d99defb40f67d3 -r 519b7df6d72a28689582e02879026c04b2214f2c templates/webapps/community/repository_review/reviews_of_changeset_revision.mako --- a/templates/webapps/community/repository_review/reviews_of_changeset_revision.mako +++ b/templates/webapps/community/repository_review/reviews_of_changeset_revision.mako @@ -5,7 +5,7 @@ <% from galaxy.webapps.community.controllers.repository_review import build_approved_select_field - from galaxy.webapps.community.controllers.common import STRSEP + from galaxy.webapps.community.util.container_util import STRSEP is_admin = trans.user_is_admin() is_new = repository.is_new( trans.app ) can_browse_contents = not is_new 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.
participants (1)
-
Bitbucket