1 new commit in galaxy-central: https://bitbucket.org/galaxy/galaxy-central/commits/f7ebd14c2f9b/ Changeset: f7ebd14c2f9b User: martenson Date: 2014-03-19 20:38:14 Summary: libraries: imrpoved to_dict handling; corrected unencoded ID treatment; eceptions refactoring for API; docs Affected #: 3 files diff -r 40213f2f80646d21013c1ec7fe461aef3542c6e0 -r f7ebd14c2f9b260cdb6627e4abfd5c03f14c4900 lib/galaxy/model/__init__.py --- a/lib/galaxy/model/__init__.py +++ b/lib/galaxy/model/__init__.py @@ -1951,6 +1951,14 @@ self.description = description self.synopsis = synopsis self.root_folder = root_folder + def to_dict( self, view='collection', value_mapper=None ): + """ + We prepend an F to folders. + """ + rval = super( Library, self ).to_dict( view=view, value_mapper=value_mapper ) + if 'root_folder_id' in rval: + rval[ 'root_folder_id' ] = 'F' + rval[ 'root_folder_id' ] + return rval def get_active_folders( self, folder, folders=None ): # TODO: should we make sure the library is not deleted? def sort_by_attr( seq, attr ): diff -r 40213f2f80646d21013c1ec7fe461aef3542c6e0 -r f7ebd14c2f9b260cdb6627e4abfd5c03f14c4900 lib/galaxy/webapps/galaxy/api/libraries.py --- a/lib/galaxy/webapps/galaxy/api/libraries.py +++ b/lib/galaxy/webapps/galaxy/api/libraries.py @@ -54,8 +54,7 @@ trans.model.Library.table.c.id.in_( accessible_restricted_library_ids ) ) ) libraries = [] for library in query: - item = self.prepend_folder_prefix( library.to_dict( view='element', - value_mapper={ 'id' : trans.security.encode_id , 'root_folder_id' : trans.security.encode_id } ) ) + item = library.to_dict( view='element', value_mapper={ 'id' : trans.security.encode_id , 'root_folder_id' : trans.security.encode_id } ) libraries.append( item ) return libraries @@ -93,8 +92,7 @@ library = None if not library or not ( trans.user_is_admin() or trans.app.security_agent.can_access_library( trans.get_current_user_roles(), library ) ): raise exceptions.ObjectNotFound( 'Library with the id provided ( %s ) was not found' % id ) - return self.prepend_folder_prefix( library.to_dict( view='element', - value_mapper={ 'id' : trans.security.encode_id , 'root_folder_id' : trans.security.encode_id } ) ) + return library.to_dict( view='element', value_mapper={ 'id' : trans.security.encode_id , 'root_folder_id' : trans.security.encode_id } ) @expose_api def create( self, trans, payload, **kwd ): @@ -131,8 +129,7 @@ library.root_folder = root_folder trans.sa_session.add_all( ( library, root_folder ) ) trans.sa_session.flush() - return self.prepend_folder_prefix( library.to_dict( view='element', - value_mapper={ 'id' : trans.security.encode_id , 'root_folder_id' : trans.security.encode_id } ) ) + return library.to_dict( view='element', value_mapper={ 'id' : trans.security.encode_id , 'root_folder_id' : trans.security.encode_id } ) @expose_api def update( self, trans, id, **kwd ): @@ -183,8 +180,7 @@ raise exceptions.RequestParameterMissingException( "You did not specify any payload." ) trans.sa_session.add( library ) trans.sa_session.flush() - return self.prepend_folder_prefix( library.to_dict( view='element', - value_mapper={ 'id' : trans.security.encode_id , 'root_folder_id' : trans.security.encode_id } ) ) + return library.to_dict( view='element', value_mapper={ 'id' : trans.security.encode_id , 'root_folder_id' : trans.security.encode_id } ) @expose_api def delete( self, trans, id, **kwd ): @@ -229,33 +225,5 @@ trans.sa_session.add( library ) trans.sa_session.flush() - return self.prepend_folder_prefix( library.to_dict( view='element', - value_mapper={ 'id' : trans.security.encode_id , 'root_folder_id' : trans.security.encode_id } ) ) + return library.to_dict( view='element', value_mapper={ 'id' : trans.security.encode_id , 'root_folder_id' : trans.security.encode_id } ) - def prepend_folder_prefix (self, dictionary, type='library' ): - """ - prepend_folder_prefix (self, dictionary, type='library' ) - In Galaxy folders have an 'F' as a prefix to the encoded id to distinguish between folders and libraries - - :param dictionary: a supported object after to_dict containing _encoded_ ids - :type dictionary: dictionary - - :param type: string representing the type of dictionary that is passed in, defaults to 'library' - :type type: string - - :raises: TypeError, ValueError - """ - if not ( type in [ 'library', 'folder' ] ): - raise TypeError( 'Prepending is not implemented for given type of dictionary.' ) - return_dict = dictionary - if type == 'library': - if return_dict[ 'root_folder_id' ]: - return_dict[ 'root_folder_id' ] = 'F' + return_dict[ 'root_folder_id' ] - else: - raise ValueError( 'Given library does not contain root_folder_id to prepend to.' ) - elif type == 'folder': - if return_dict[ 'id' ]: - return_dict[ 'id' ] = 'F' + return_dict[ 'id' ] - else: - raise ValueError( 'Given folder does not contain an id to prepend to.' ) - return return_dict diff -r 40213f2f80646d21013c1ec7fe461aef3542c6e0 -r f7ebd14c2f9b260cdb6627e4abfd5c03f14c4900 lib/galaxy/webapps/galaxy/api/library_contents.py --- a/lib/galaxy/webapps/galaxy/api/library_contents.py +++ b/lib/galaxy/webapps/galaxy/api/library_contents.py @@ -1,39 +1,47 @@ """ -API operations on the contents of a library. +API operations on the contents of a data library. """ -import logging -from galaxy import web, exceptions -from galaxy.model import ExtendedMetadata, ExtendedMetadataIndex +from galaxy import util +from galaxy import web +from galaxy import exceptions +from galaxy.web import _future_expose_api as expose_api +from galaxy.web import _future_expose_api_anonymous as expose_api_anonymous from galaxy.web.base.controller import BaseAPIController, UsesLibraryMixin, UsesLibraryMixinItems from galaxy.web.base.controller import UsesHistoryDatasetAssociationMixin from galaxy.web.base.controller import HTTPBadRequest, url_for -from galaxy import util +from galaxy.model import ExtendedMetadata, ExtendedMetadataIndex +from sqlalchemy.orm.exc import MultipleResultsFound +from sqlalchemy.orm.exc import NoResultFound +import logging log = logging.getLogger( __name__ ) class LibraryContentsController( BaseAPIController, UsesLibraryMixin, UsesLibraryMixinItems, UsesHistoryDatasetAssociationMixin ): - @web.expose_api - # TODO: Add parameter to only get top level of datasets/subfolders. + @expose_api def index( self, trans, library_id, **kwd ): """ index( self, trans, library_id, **kwd ) * GET /api/libraries/{library_id}/contents: - return a list of library files and folders + Returns a list of library files and folders. - :type library_id: str - :param library_id: encoded id string of the library that contains this item + .. note:: May be slow! Returns all content traversing recursively through all folders. + .. seealso:: :class:`galaxy.webapps.galaxy.api.FolderContentsController.index` for a non-recursive solution - :rtype: list + :param library_id: encoded id string of the library + :type library_id: string + :returns: list of dictionaries of the form: - * id: the encoded id of the library item * name: the 'libary path' or relationship of the library item to the root * type: 'file' or 'folder' * url: the url to get detailed information on the library item + :rtype: list + + :raises: MalformedId, InconsistentDatabase, RequestParameterInvalidException, InternalServerError """ rval = [] current_user_roles = trans.get_current_user_roles() @@ -56,33 +64,32 @@ ld.library_dataset_dataset_association.dataset ) if (admin or can_access) and not ld.deleted: - #log.debug( "type(folder): %s" % type( folder ) ) - #log.debug( "type(api_path): %s; folder.api_path: %s" % ( type(folder.api_path), folder.api_path ) ) - #log.debug( "attributes of folder: %s" % str(dir(folder)) ) ld.api_path = folder.api_path + '/' + ld.name ld.api_type = 'file' rval.append( ld ) return rval try: decoded_library_id = trans.security.decode_id( library_id ) - except TypeError: - trans.response.status = 400 - return "Malformed library id ( %s ) specified, unable to decode." % str( library_id ) + except Exception: + raise exceptions.MalformedId( 'Malformed library id ( %s ) specified, unable to decode.' % library_id ) try: - library = trans.sa_session.query( trans.app.model.Library ).get( decoded_library_id ) - except: - library = None - if not library or not ( trans.user_is_admin() or trans.app.security_agent.can_access_library( current_user_roles, library ) ): - trans.response.status = 400 - return "Invalid library id ( %s ) specified." % str( library_id ) - #log.debug( "Root folder type: %s" % type( library.root_folder ) ) + library = trans.sa_session.query( trans.app.model.Library ).filter( trans.app.model.Library.table.c.id == decoded_library_id ).one() + except MultipleResultsFound: + raise exceptions.InconsistentDatabase( 'Multiple libraries found with the same id.' ) + except NoResultFound: + raise exceptions.RequestParameterInvalidException( 'No library found with the id provided.' ) + except Exception, e: + raise exceptions.InternalServerError( 'Error loading from the database.' + str(e)) + if not ( trans.user_is_admin() or trans.app.security_agent.can_access_library( current_user_roles, library ) ): + raise exceptions.RequestParameterInvalidException( 'No library found with the id provided.' ) encoded_id = 'F' + trans.security.encode_id( library.root_folder.id ) + # appending root folder rval.append( dict( id=encoded_id, type='folder', name='/', url=url_for( 'library_content', library_id=library_id, id=encoded_id ) ) ) - #log.debug( "Root folder attributes: %s" % str(dir(library.root_folder)) ) library.root_folder.api_path = '' + # appending all other items in the library recursively for content in traverse( library.root_folder ): encoded_id = trans.security.encode_id( content.id ) if content.api_type == 'folder': @@ -93,20 +100,22 @@ url=url_for( 'library_content', library_id=library_id, id=encoded_id, ) ) ) return rval - @web.expose_api + @expose_api def show( self, trans, id, library_id, **kwd ): """ show( self, trans, id, library_id, **kwd ) * GET /api/libraries/{library_id}/contents/{id} - return information about library file or folder + Returns information about library file or folder. + :param id: the encoded id of the library item to return :type id: str - :param id: the encoded id of the library item to return + + :param library_id: encoded id string of the library that contains this item :type library_id: str - :param library_id: encoded id string of the library that contains this item + :returns: detailed library item information :rtype: dict - :returns: detailed library item information + .. seealso:: :func:`galaxy.model.LibraryDataset.to_dict` and :attr:`galaxy.model.LibraryFolder.dict_element_visible_keys` @@ -116,7 +125,9 @@ content = self.get_library_folder( trans, content_id, check_ownership=False, check_accessible=True ) else: content = self.get_library_dataset( trans, content_id, check_ownership=False, check_accessible=True ) - return self.encode_all_ids( trans, content.to_dict( view='element' ) ) + + return content.to_dict( view='element', value_mapper={ 'id' : trans.security.encode_id } ) + # return self.encode_all_ids( trans, content.to_dict( view='element' ) ) @web.expose_api def create( self, trans, library_id, payload, **kwd ): 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.