commit/galaxy-central: 2 new changesets
2 new commits in galaxy-central: https://bitbucket.org/galaxy/galaxy-central/changeset/8d3caff4bd0f/ changeset: 8d3caff4bd0f user: carlfeberhard date: 2012-10-30 21:53:10 summary: api/histories.show: add 'nice_size', 'annotation', 'state_ids' (map of possible hda states : lists of hda ids in those states ), reorder history state from child hda states (running/queued higher priority than error), return error string; affected #: 1 file diff -r 7b807f69906eff1ea1fa3ea367b299c628736d71 -r 8d3caff4bd0fc2e76bfdf47adc27930c538a9c1f lib/galaxy/webapps/galaxy/api/histories.py --- a/lib/galaxy/webapps/galaxy/api/histories.py +++ b/lib/galaxy/webapps/galaxy/api/histories.py @@ -10,6 +10,10 @@ import galaxy.datatypes from galaxy.util.bunch import Bunch +import pkg_resources +pkg_resources.require( "Routes" ) +import routes + log = logging.getLogger( __name__ ) class HistoriesController( BaseAPIController, UsesHistoryMixin ): @@ -31,12 +35,14 @@ item = history.get_api_value(value_mapper={'id':trans.security.encode_id}) item['url'] = url_for( 'history', id=trans.security.encode_id( history.id ) ) rval.append( item ) + elif trans.galaxy_session.current_history: #No user, this must be session authentication with an anonymous user. history = trans.galaxy_session.current_history item = history.get_api_value(value_mapper={'id':trans.security.encode_id}) item['url'] = url_for( 'history', id=trans.security.encode_id( history.id ) ) rval.append(item) + except Exception, e: rval = "Error in history API" log.error( rval + ": %s" % str(e) ) @@ -55,52 +61,90 @@ params = util.Params( kwd ) deleted = util.string_as_bool( deleted ) - def traverse( datasets ): - rval = {} - states = trans.app.model.Dataset.states + states = trans.app.model.Dataset.states + + def get_dataset_state_summaries( datasets ): + # cycles through the history's datasets, building counts and id lists for each possible ds state + state_counts = {} + state_ids = {} + + # init counts, ids for each state for key, state in states.items(): - rval[state] = 0 + state_counts[state] = 0 + state_ids[state] = [] + + # cycle through datasets saving each ds' state for dataset in datasets: - item = dataset.get_api_value( view='element' ) - if not item['deleted']: - rval[item['state']] = rval[item['state']] + 1 - return rval + dataset_dict = dataset.get_api_value( view='element' ) + item_state = dataset_dict[ 'state' ] + + if not dataset_dict['deleted']: + state_counts[ item_state ] = state_counts[ item_state ] + 1 + state_ids[ item_state ].append( trans.security.encode_id( dataset_dict[ 'id' ] ) ) + + return ( state_counts, state_ids ) + + # try to load the history, by most_recently_used or the given id try: if history_id == "most_recently_used": - if trans.user and len(trans.user.galaxy_sessions) > 0: + if trans.user and len( trans.user.galaxy_sessions ) > 0: # Most recent active history for user sessions, not deleted history = trans.user.galaxy_sessions[0].histories[-1].history else: - history = None + return None else: - history = self.get_history( trans, history_id, check_ownership=True, check_accessible=True, deleted=deleted ) - except Exception, e: - return str( e ) - try: - item = history.get_api_value(view='element', value_mapper={'id':trans.security.encode_id}) - num_sets = len( [hda.id for hda in history.datasets if not hda.deleted] ) - states = trans.app.model.Dataset.states + history = self.get_history( trans, history_id, check_ownership=False, + check_accessible=True, deleted=deleted ) + + history_data = history.get_api_value( view='element', value_mapper={'id':trans.security.encode_id} ) + history_data[ 'nice_size' ] = history.get_disk_size( nice_size=True ) + + #TODO: separate, move to annotation api, fill on the client + history_data[ 'annotation' ] = history.get_item_annotation_str( trans.sa_session, trans.user, history ) + if not history_data[ 'annotation' ]: + history_data[ 'annotation' ] = '' + + # get the history state using the state summaries of it's datasets (default to ERROR) + num_sets = len([ hda.id for hda in history.datasets if not hda.deleted ]) state = states.ERROR + + ( state_counts, state_ids ) = get_dataset_state_summaries( history.datasets ) + if num_sets == 0: state = states.NEW + else: - summary = traverse(history.datasets) - if summary[states.ERROR] > 0 or summary[states.FAILED_METADATA] > 0: + + if( ( state_counts[ states.RUNNING ] > 0 ) + or ( state_counts[ states.SETTING_METADATA ] > 0 ) + or ( state_counts[ states.UPLOAD ] > 0 ) ): + state = states.RUNNING + + elif state_counts[ states.QUEUED ] > 0: + state = states.QUEUED + + elif( ( state_counts[ states.ERROR ] > 0 ) + or ( state_counts[ states.FAILED_METADATA ] > 0 ) ): state = states.ERROR - elif summary[states.RUNNING] > 0 or summary[states.SETTING_METADATA] > 0: - state = states.RUNNING - elif summary[states.QUEUED] > 0: - state = states.QUEUED - elif summary[states.OK] == num_sets: + + elif state_counts[ states.OK ] == num_sets: state = states.OK - item['contents_url'] = url_for( 'history_contents', history_id=history_id ) - item['state_details'] = summary - item['state'] = state + + history_data[ 'state' ] = state + + history_data[ 'state_details' ] = state_counts + history_data[ 'state_ids' ] = state_ids + + history_data[ 'contents_url' ] = url_for( 'history_contents', history_id=history_id ) + + except Exception, e: - item = "Error in history API at showing history detail" - log.error(item + ": %s" % str(e)) + msg = "Error in history API at showing history detail: %s" % ( str( e ) ) + log.error( msg, exc_info=True ) trans.response.status = 500 - return item + return msg + + return history_data @web.expose_api def create( self, trans, payload, **kwd ): https://bitbucket.org/galaxy/galaxy-central/changeset/4ceab232dc02/ changeset: 4ceab232dc02 user: carlfeberhard date: 2012-10-30 21:55:23 summary: api/history_contents: (1) index: if passed ids=<id|csv id list> in query string, provide full data (as history_contents.show) for each id listed (if no 'ids' - use previous summary behaviour), return error string; (2) show: return 'accessible', 'api_type' (consistent with summary style in index), 'display_types', 'display_apps', 'file_ext', 'hid', 'history_id', 'meta_files' (file types of associated files for generating download urls, eg. myBam.meta_files: [{ 'file_type' : 'bam_index' }]), 'visualizations' (list of visualization names appr. for this hda), 'peek' (data.peek as used in the history panel), return error string; affected #: 1 file diff -r 8d3caff4bd0fc2e76bfdf47adc27930c538a9c1f -r 4ceab232dc02a5a99eca0b24c0038c490d49a392 lib/galaxy/webapps/galaxy/api/history_contents.py --- a/lib/galaxy/webapps/galaxy/api/history_contents.py +++ b/lib/galaxy/webapps/galaxy/api/history_contents.py @@ -2,8 +2,17 @@ API operations on the contents of a history. """ import logging +import urllib +from gettext import gettext + from galaxy import web -from galaxy.web.base.controller import BaseAPIController, url_for, UsesHistoryDatasetAssociationMixin, UsesHistoryMixin, UsesLibraryMixin, UsesLibraryMixinItems +from galaxy.web.base.controller import BaseAPIController, url_for +from galaxy.web.base.controller import UsesHistoryDatasetAssociationMixin, UsesHistoryMixin +from galaxy.web.base.controller import UsesLibraryMixin, UsesLibraryMixinItems + +from galaxy.web.framework.helpers import to_unicode +from galaxy.datatypes.display_applications import util +from galaxy.datatypes.metadata import FileParameter import pkg_resources pkg_resources.require( "Routes" ) @@ -11,27 +20,39 @@ log = logging.getLogger( __name__ ) -class HistoryContentsController( BaseAPIController, UsesHistoryDatasetAssociationMixin, UsesHistoryMixin, UsesLibraryMixin, UsesLibraryMixinItems ): - +class HistoryContentsController( BaseAPIController, UsesHistoryDatasetAssociationMixin, UsesHistoryMixin, + UsesLibraryMixin, UsesLibraryMixinItems ): @web.expose_api - def index( self, trans, history_id, **kwd ): + def index( self, trans, history_id, ids=None, **kwd ): """ GET /api/histories/{encoded_history_id}/contents Displays a collection (list) of history contents """ + rval = [] try: history = self.get_history( trans, history_id, check_ownership=True, check_accessible=True ) - except Exception, e: - return str( e ) - rval = [] - try: - for dataset in history.datasets: - api_type = "file" - encoded_id = trans.security.encode_id( dataset.id ) - rval.append( dict( id = encoded_id, - type = api_type, - name = dataset.name, - url = url_for( 'history_content', history_id=history_id, id=encoded_id, ) ) ) + + # if no ids passed, return a _SUMMARY_ of _all_ datasets in the history + if not ids: + for dataset in history.datasets: + api_type = "file" + encoded_id = trans.security.encode_id( dataset.id ) + # build the summary + rval.append( dict( id = encoded_id, + type = api_type, + name = dataset.name, + url = url_for( 'history_content', history_id=history_id, id=encoded_id, ) ) ) + + # if ids, return _FULL_ data (as show) for each id passed + #NOTE: this might not be the best form (passing all info), + # but we(I?) need an hda collection with full data somewhere + else: + ids = ids.split( ',' ) + for id in ids: + hda = self.get_history_dataset_association( trans, history, id, + check_ownership=True, check_accessible=True, check_state=False ) + rval.append( get_hda_dict( trans, history, hda, for_editing=True ) ) + except Exception, e: rval = "Error in history API at listing contents" log.error( rval + ": %s" % str(e) ) @@ -44,30 +65,21 @@ GET /api/histories/{encoded_history_id}/contents/{encoded_content_id} Displays information about a history content (dataset). """ - content_id = id + hda_dict = {} try: - # get the history just for the access checks - history = self.get_history( trans, history_id, check_ownership=True, check_accessible=True, deleted=False ) - content = self.get_history_dataset_association( trans, history, content_id, check_ownership=True, check_accessible=True ) + history = self.get_history( trans, history_id, + check_ownership=True, check_accessible=True, deleted=False ) + hda = self.get_history_dataset_association( trans, history, id, + check_ownership=True, check_accessible=True ) + hda_dict = get_hda_dict( trans, history, hda, for_editing=True ) + except Exception, e: - return str( e ) - try: - item = content.get_api_value( view='element' ) - if trans.user_is_admin() or trans.app.config.expose_dataset_path: - item['file_name'] = content.file_name - if not item['deleted']: - # Problem: Method url_for cannot use the dataset controller - # Get the environment from DefaultWebTransaction and use default webapp mapper instead of webapp API mapper - url = routes.URLGenerator(trans.webapp.mapper, trans.environ) - # http://routes.groovie.org/generating.html - # url_for is being phased out, so new applications should use url - item['download_url'] = url(controller='dataset', action='display', dataset_id=trans.security.encode_id(content.id), to_ext=content.ext) - item = self.encode_all_ids( trans, item ) - except Exception, e: - item = "Error in history API at listing dataset" - log.error( item + ": %s" % str(e) ) + msg = "Error in history API at listing dataset: %s" % ( str(e) ) + log.error( msg, exc_info=True ) trans.response.status = 500 - return item + return msg + + return hda_dict @web.expose_api def create( self, trans, history_id, payload, **kwd ): @@ -99,3 +111,69 @@ trans.response.status = 403 return "Not implemented." + +# move these into model?? hell if I know...doesn't seem like the urls should go here +def get_hda_dict( trans, history, hda, for_editing ): + hda_dict = hda.get_api_value( view='element' ) + + hda_dict[ 'id' ] = trans.security.encode_id( hda.id ) + hda_dict[ 'history_id' ] = trans.security.encode_id( history.id ) + hda_dict[ 'hid' ] = hda.hid + + hda_dict[ 'file_ext' ] = hda.ext + if trans.user_is_admin() or trans.app.config.expose_dataset_path: + hda_dict[ 'file_name' ] = hda.file_name + + if not hda_dict[ 'deleted' ]: + # Problem: Method url_for cannot use the dataset controller + # Get the environment from DefaultWebTransaction + # and use default webapp mapper instead of webapp API mapper + web_url_for = routes.URLGenerator( trans.webapp.mapper, trans.environ ) + # http://routes.groovie.org/generating.html + # url_for is being phased out, so new applications should use url + hda_dict[ 'download_url' ] = web_url_for( controller='dataset', action='display', + dataset_id=trans.security.encode_id( hda.id ), to_ext=hda.ext ) + + can_access_hda = trans.app.security_agent.can_access_dataset( trans.get_current_user_roles(), hda.dataset ) + hda_dict[ 'accessible' ] = ( trans.user_is_admin() or can_access_hda ) + hda_dict[ 'api_type' ] = "file" + + if not( hda.purged or hda.deleted or hda.dataset.purged ): + meta_files = [] + for meta_type in hda.metadata.spec.keys(): + if isinstance( hda.metadata.spec[ meta_type ].param, FileParameter ): + meta_files.append( dict( file_type=meta_type ) ) + if meta_files: + hda_dict[ 'meta_files' ] = meta_files + + #hda_dict[ 'display_apps' ] = get_display_apps( trans, hda ) + hda_dict[ 'visualizations' ] = hda.get_visualizations() + hda_dict[ 'peek' ] = to_unicode( hda.display_peek() ) + + return hda_dict + +def get_display_apps( trans, hda ): + display_apps = [] + + def get_display_app_url( display_app_link, hda, trans ): + web_url_for = routes.URLGenerator( trans.webapp.mapper, trans.environ ) + dataset_hash, user_hash = util.encode_dataset_user( trans, hda, None ) + return web_url_for( controller='/dataset', + action="display_application", + dataset_id=dataset_hash, + user_id=user_hash, + app_name=urllib.quote_plus( display_app_link.display_application.id ), + link_name=urllib.quote_plus( display_app_link.id ) ) + + + for display_app in hda.get_display_applications( trans ).itervalues(): + app_links = [] + for display_app_link in display_app.links.itervalues(): + app_links.append({ + 'target' : display_app_link.url.get( 'target_frame', '_blank' ), + 'href' : get_display_app_url( display_app_link, hda, trans ), + 'text' : gettext( display_app_link.name ) + }) + display_apps.append( dict( label=display_app.name, links=app_links ) ) + + return display_apps 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