details: http://www.bx.psu.edu/hg/galaxy/rev/dea0ad16553e changeset: 3771:dea0ad16553e user: Greg Von Kuster <greg@bx.psu.edu> date: Wed May 12 09:18:05 2010 -0400 description: Fixes for uploading a tool to the community space, and keep None from being displayed if there is no user_description. diffstat: lib/galaxy/webapps/community/controllers/common.py | 12 +- lib/galaxy/webapps/community/controllers/upload.py | 199 ++++++++++---------- lib/galaxy/webapps/community/datatypes/__init__.py | 10 +- templates/webapps/community/tool/edit_tool.mako | 6 +- templates/webapps/community/tool/view_tool.mako | 10 +- 5 files changed, 131 insertions(+), 106 deletions(-) diffs (321 lines): diff -r 7232b61da6d3 -r dea0ad16553e lib/galaxy/webapps/community/controllers/common.py --- a/lib/galaxy/webapps/community/controllers/common.py Tue May 11 18:02:39 2010 -0400 +++ b/lib/galaxy/webapps/community/controllers/common.py Wed May 12 09:18:05 2010 -0400 @@ -28,8 +28,11 @@ else: # There must not be any categories associated with the tool trans.app.security_agent.set_entity_category_associations( tools=[ tool ], categories=[] ) - if params.get( 'description', False ): - tool.user_description = util.restore_text( params.get( 'description', '' ) ) + user_description = util.restore_text( params.get( 'user_description', '' ) ) + if user_description: + tool.user_description = user_description + else: + tool.user_description = '' trans.sa_session.add( tool ) trans.sa_session.flush() message="Tool '%s' description and category associations have been saved" % tool.name @@ -236,7 +239,10 @@ def get_tool( trans, id ): return trans.sa_session.query( trans.model.Tool ).get( trans.app.security.decode_id( id ) ) def get_tools( trans ): - return trans.sa_session.query( trans.model.Tool ).order_by( trans.model.Tool.name ) + # Return only the latest version of each tool + return trans.sa_session.query( trans.model.Tool ) \ + .filter( trans.model.Tool.newer_version_id == None ) \ + .order_by( trans.model.Tool.name ) def get_approved_tools( trans, category=None ): # TODO: write this as a query using eagerload - will be much faster. ids = [] diff -r 7232b61da6d3 -r dea0ad16553e lib/galaxy/webapps/community/controllers/upload.py --- a/lib/galaxy/webapps/community/controllers/upload.py Tue May 11 18:02:39 2010 -0400 +++ b/lib/galaxy/webapps/community/controllers/upload.py Wed May 12 09:18:05 2010 -0400 @@ -26,112 +26,119 @@ replace_version = None uploaded_file = None categories = get_categories( trans ) - if not get_categories( trans ): + if not categories: return trans.response.send_redirect( web.url_for( controller='tool', action='browse_tools', cntrller='tool', message='No categories have been configured in this instance of the Galaxy Community. An administrator needs to create some via the Administrator control panel before anything can be uploaded', status='error' ) ) - elif params.file_data == '' and params.url.strip() == '': - message = 'No files were entered on the upload form.' - status = 'error' - elif params.file_data == '': - try: - uploaded_file = urllib2.urlopen( params.url.strip() ) - except ( ValueError, urllib2.HTTPError ), e: - message = 'An error occurred trying to retrieve the URL entered on the upload form: %s' % e + if params.get( 'upload_button', False ): + + url_paste = params.get( 'url', '' ).strip() + file_data = params.get( 'file_data', '' ) + if file_data == '' and url_paste == '': + message = 'No files were entered on the upload form.' status = 'error' - except urllib2.URLError, e: - message = 'An error occurred trying to retrieve the URL entered on the upload form: %s' % e.reason - status = 'error' - elif params.file_data not in ( '', None ): - uploaded_file = params.file_data.file - if params.upload_button and uploaded_file: - datatype = trans.app.datatypes_registry.get_datatype_by_extension( params.upload_type ) - if datatype is None: - message = 'An unknown file type was selected. This should not be possible, please report the error.' - status = 'error' - else: + elif file_data == '': try: - # Initialize the tool object - meta = datatype.verify( uploaded_file ) - meta.user = trans.user - meta.guid = trans.app.security.get_new_guid() - obj = datatype.create_model_object( meta ) - trans.sa_session.add( obj ) - if isinstance( obj, trans.app.model.Tool ): - existing = trans.sa_session.query( trans.app.model.Tool ).filter_by( tool_id = meta.id ).first() - if existing and replace_id is None: - raise UploadError( 'A tool with the same ID already exists. If you are trying to update this tool to a new version, please use the upload form on the "Edit Tool" page. Otherwise, please choose a new ID.' ) - elif existing: - replace_version = trans.sa_session.query( trans.app.model.Tool ).get( trans.security.decode_id( replace_id ) ) - if replace_version.newer_version: - # If the user has picked an old version, switch to the newest version - replace_version = get_versions( trans, replace_version )[0] - if replace_version.tool_id != meta.id: - raise UploadError( 'The new tool id (%s) does not match the old tool id (%s). Check the tool XML file' % ( meta.id, replace_version.tool_id ) ) - for old_version in get_versions( trans, replace_version ): - if old_version.version == meta.version: - raise UploadError( 'The new version (%s) matches an old version. Check your version in the tool XML file' % meta.version ) - if old_version.is_new(): - raise UploadError( 'There is an existing version of this tool which has not yet been submitted for approval, so either <a href="%s">submit or delete it</a> before uploading a new version.' % url_for( controller='common', - action='view_tool', - cntrller='tool', - id=trans.security.encode_id( old_version.id ) ) ) - if old_version.is_waiting(): - raise UploadError( 'There is an existing version of this tool which is waiting for administrative approval, so contact an administrator for help.' ) - # Defer setting the id since the newer version id doesn't exist until the new Tool object is flushed - if category_ids: - for category_id in category_ids: - category = trans.app.model.Category.get( trans.security.decode_id( category_id ) ) - # Initialize the tool category - tca = trans.app.model.ToolCategoryAssociation( obj, category ) - trans.sa_session.add( tca ) - # Initialize the tool event - event = trans.app.model.Event( state=trans.app.model.Tool.states.NEW ) - # Flush to get an event id - trans.sa_session.add( event ) + uploaded_file = urllib2.urlopen( url_paste ) + except ( ValueError, urllib2.HTTPError ), e: + message = 'An error occurred trying to retrieve the URL entered on the upload form: %s' % e + status = 'error' + except urllib2.URLError, e: + message = 'An error occurred trying to retrieve the URL entered on the upload form: %s' % e.reason + status = 'error' + elif file_data not in ( '', None ): + uploaded_file = file_data.file + if uploaded_file: + # TODO: tool should no longer be the default when we upload histories and workflows + upload_type = params.get( 'upload_type', 'tool' ) + datatype = trans.app.datatypes_registry.get_datatype_by_extension( upload_type ) + if datatype is None: + message = 'An unknown file type was selected. This should not be possible, please report the error.' + status = 'error' + else: + try: + # Initialize the tool object + meta = datatype.verify( uploaded_file ) + meta.user = trans.user + meta.guid = trans.app.security.get_new_guid() + obj = datatype.create_model_object( meta ) + trans.sa_session.add( obj ) + if isinstance( obj, trans.app.model.Tool ): + existing = trans.sa_session.query( trans.app.model.Tool ).filter_by( tool_id = meta.id ).first() + if existing and replace_id is None: + raise UploadError( 'A tool with the same ID already exists. If you are trying to update this tool to a new version, please use the upload form on the "Edit Tool" page. Otherwise, please choose a new ID.' ) + elif existing: + replace_version = trans.sa_session.query( trans.app.model.Tool ).get( trans.security.decode_id( replace_id ) ) + if replace_version.newer_version: + # If the user has picked an old version, switch to the newest version + replace_version = get_versions( trans, replace_version )[0] + if replace_version.tool_id != meta.id: + raise UploadError( 'The new tool id (%s) does not match the old tool id (%s). Check the tool XML file' % ( meta.id, replace_version.tool_id ) ) + for old_version in get_versions( trans, replace_version ): + if old_version.version == meta.version: + raise UploadError( 'The new version (%s) matches an old version. Check your version in the tool XML file' % meta.version ) + if old_version.is_new(): + raise UploadError( 'There is an existing version of this tool which has not yet been submitted for approval, so either <a href="%s">submit or delete it</a> before uploading a new version.' % url_for( controller='common', + action='view_tool', + cntrller='tool', + id=trans.security.encode_id( old_version.id ) ) ) + if old_version.is_waiting(): + raise UploadError( 'There is an existing version of this tool which is waiting for administrative approval, so contact an administrator for help.' ) + # Defer setting the id since the newer version id doesn't exist until the new Tool object is flushed + if category_ids: + for category_id in category_ids: + category = trans.app.model.Category.get( trans.security.decode_id( category_id ) ) + # Initialize the tool category + tca = trans.app.model.ToolCategoryAssociation( obj, category ) + trans.sa_session.add( tca ) + # Initialize the tool event + event = trans.app.model.Event( state=trans.app.model.Tool.states.NEW ) + # Flush to get an event id + trans.sa_session.add( event ) + trans.sa_session.flush() + tea = trans.app.model.ToolEventAssociation( obj, event ) + trans.sa_session.add( tea ) + if replace_version and replace_id: + replace_version.newer_version_id = obj.id + trans.sa_session.add( replace_version ) trans.sa_session.flush() - tea = trans.app.model.ToolEventAssociation( obj, event ) - trans.sa_session.add( tea ) - if replace_version and replace_id: - replace_version.newer_version_id = obj.id - trans.sa_session.add( replace_version ) - trans.sa_session.flush() - try: - os.link( uploaded_file.name, obj.file_name ) - except OSError: - shutil.copy( uploaded_file.name, obj.file_name ) - # We're setting cntrller to 'tool' since that is the only controller from which we can upload + try: + os.link( uploaded_file.name, obj.file_name ) + except OSError: + shutil.copy( uploaded_file.name, obj.file_name ) + # We're setting cntrller to 'tool' since that is the only controller from which we can upload + # TODO: this will need tweaking when we can upload histories or workflows + return trans.response.send_redirect( web.url_for( controller='common', + action='edit_tool', + cntrller='tool', + id=trans.app.security.encode_id( obj.id ), + message='Uploaded %s' % meta.message, + status='done' ) ) + except ( datatypes.DatatypeVerificationError, UploadError ), e: + message = str( e ) + status = 'error' + uploaded_file.close() + elif replace_id is not None: + replace_version = trans.sa_session.query( trans.app.model.Tool ).get( int( trans.app.security.decode_id( replace_id ) ) ) + old_version = None + for old_version in get_versions( trans, replace_version ): + if old_version.is_new(): + message = 'There is an existing version of this tool which has not been submitted for approval, so either submit or delete it before uploading a new version.' + break + if old_version.is_waiting(): + message = 'There is an existing version of this tool which is waiting for administrative approval, so contact an administrator for help.' + break + else: + old_version = None + if old_version is not None: return trans.response.send_redirect( web.url_for( controller='common', - action='edit_tool', + action='view_tool', cntrller='tool', - id=trans.app.security.encode_id( obj.id ), - message='Uploaded %s' % meta.message, - status='done' ) ) - except ( datatypes.DatatypeVerificationError, UploadError ), e: - message = str( e ) - status = 'error' - uploaded_file.close() - elif replace_id is not None: - replace_version = trans.sa_session.query( trans.app.model.Tool ).get( int( trans.app.security.decode_id( replace_id ) ) ) - old_version = None - for old_version in get_versions( trans, replace_version ): - if old_version.is_new(): - message = 'There is an existing version of this tool which has not been submitted for approval, so either submit or delete it before uploading a new version.' - break - if old_version.is_waiting(): - message = 'There is an existing version of this tool which is waiting for administrative approval, so contact an administrator for help.' - break - else: - old_version = None - if old_version is not None: - return trans.response.send_redirect( web.url_for( controller='common', - action='view_tool', - cntrller='tool', - id=trans.app.security.encode_id( old_version.id ), - message=message, - status='error' ) ) + id=trans.app.security.encode_id( old_version.id ), + message=message, + status='error' ) ) selected_upload_type = params.get( 'type', 'tool' ) selected_categories = [ trans.security.decode_id( id ) for id in category_ids ] return trans.fill_template( '/webapps/community/upload/upload.mako', diff -r 7232b61da6d3 -r dea0ad16553e lib/galaxy/webapps/community/datatypes/__init__.py --- a/lib/galaxy/webapps/community/datatypes/__init__.py Tue May 11 18:02:39 2010 -0400 +++ b/lib/galaxy/webapps/community/datatypes/__init__.py Wed May 12 09:18:05 2010 -0400 @@ -120,11 +120,13 @@ rval.version = root.attrib['version'] except KeyError, e: raise DatatypeVerificationError( 'Tool XML file does not conform to the specification. Missing required <tool> tag attribute: %s' % e ) - rval.description = None + rval.description = '' desc_tag = root.find( 'description' ) - if desc_tag is not None: - rval.description = desc_tag.text.strip() - rval.message = 'Tool: %s %s, Version: %s, ID: %s' % ( rval.name, rval.description or '', rval.version, rval.id ) + if desc_tag: + description = desc_tag.text + if description: + rval.description = description.strip() + rval.message = 'Tool: %s %s, Version: %s, ID: %s' % ( str( rval.name ), str( rval.description ), str( rval.version ), str( rval.id ) ) return rval else: raise DatatypeVerificationError( 'Unable to find a properly formatted tool XML file' ) diff -r 7232b61da6d3 -r dea0ad16553e templates/webapps/community/tool/edit_tool.mako --- a/templates/webapps/community/tool/edit_tool.mako Tue May 11 18:02:39 2010 -0400 +++ b/templates/webapps/community/tool/edit_tool.mako Wed May 12 09:18:05 2010 -0400 @@ -82,7 +82,11 @@ </div> <div class="form-row"> <label>Description:</label> - <div class="form-row-input"><textarea name="description" rows="5" cols="35">${tool.user_description}</textarea></div> + %if tool.user_description: + <div class="form-row-input"><textarea name="user_description" rows="5" cols="35">${tool.user_description}</textarea></div> + %else: + <div class="form-row-input"><textarea name="user_description" rows="5" cols="35"></textarea></div> + %endif <div style="clear: both"></div> </div> <div class="form-row"> diff -r 7232b61da6d3 -r dea0ad16553e templates/webapps/community/tool/view_tool.mako --- a/templates/webapps/community/tool/view_tool.mako Tue May 11 18:02:39 2010 -0400 +++ b/templates/webapps/community/tool/view_tool.mako Wed May 12 09:18:05 2010 -0400 @@ -4,8 +4,12 @@ from galaxy.web.framework.helpers import time_ago from urllib import quote_plus + menu_label = 'Edit information' + if cntrller in [ 'tool' ]: can_edit = trans.app.security_agent.can_edit_item( trans.user, tool ) + if can_edit: + menu_label = 'Edit information or submit for approval' can_upload_new_version = trans.app.security_agent.can_upload_new_version( trans.user, tool, versions ) visible_versions = [] @@ -89,7 +93,7 @@ <a id="tool-${tool.id}-popup" class="popup-arrow" style="display: none;">▼</a> <div popupmenu="tool-${tool.id}-popup"> %if cntrller=='admin' or can_edit: - <a class="action-button" href="${h.url_for( controller='common', action='edit_tool', id=trans.app.security.encode_id( tool.id ), cntrller=cntrller )}">Edit information</a> + <a class="action-button" href="${h.url_for( controller='common', action='edit_tool', id=trans.app.security.encode_id( tool.id ), cntrller=cntrller )}">${menu_label}</a> %endif <a class="action-button" href="${h.url_for( controller='tool', action='download_tool', id=trans.app.security.encode_id( tool.id ) )}">Download tool</a> %if cntrller=='admin' or trans.user==tool.user: @@ -114,7 +118,9 @@ </div> <div class="form-row"> <label>Description:</label> - ${tool.user_description} + %if tool.user_description: + ${tool.user_description} + %endif <div style="clear: both"></div> </div> <div class="form-row">