1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/bc1d006b0e66/
Changeset: bc1d006b0e66
User: martenson
Date: 2014-05-07 21:27:37
Summary: hunted down bug in streamball implementation that prevented adding files to archive if the filecheck was on and it passed
Affected #: 1 file
diff -r f7baaf52e94c57cc1a3f7297c191a3e19826293d -r bc1d006b0e66209e26f107ff6b48bfece3777eec lib/galaxy/util/streamball.py
--- a/lib/galaxy/util/streamball.py
+++ b/lib/galaxy/util/streamball.py
@@ -19,6 +19,8 @@
if check_file and len(file)>0:
if not os.path.isfile(file):
raise ObjectNotFound
+ else:
+ self.members[file] = relpath
else:
self.members[file] = relpath
def stream( self, environ, start_response ):
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.
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/a73c02cd503e/
Changeset: a73c02cd503e
User: martenson
Date: 2014-05-07 20:10:30
Summary: data libraries: API pep8, cleanup, repaired yet another encoding bug
Affected #: 2 files
diff -r 9eb2b42e21fee519b1ea5e9c791bb6b8989f6b5c -r a73c02cd503ef2bec4819013517530df7045127e lib/galaxy/webapps/galaxy/api/folder_contents.py
--- a/lib/galaxy/webapps/galaxy/api/folder_contents.py
+++ b/lib/galaxy/webapps/galaxy/api/folder_contents.py
@@ -13,6 +13,7 @@
import logging
log = logging.getLogger( __name__ )
+
class FolderContentsController( BaseAPIController, UsesLibraryMixin, UsesLibraryMixinItems, UsesHistoryDatasetAssociationMixin ):
"""
Class controls retrieval, creation and updating of folder contents.
@@ -23,14 +24,14 @@
"""
GET /api/folders/{encoded_folder_id}/contents
- Displays a collection (list) of a folder's contents
+ Displays a collection (list) of a folder's contents
(files and folders). Encoded folder ID is prepended
with 'F' if it is a folder as opposed to a data set
which does not have it. Full path is provided in
- response as a separate object providing data for
+ response as a separate object providing data for
breadcrumb path building.
- :param folder_id: encoded ID of the folder which
+ :param folder_id: encoded ID of the folder which
contents should be library_dataset_dict
:type folder_id: encoded string
@@ -70,7 +71,7 @@
can_add_library_item = trans.user_is_admin() or trans.app.security_agent.can_add_library_item( current_user_roles, folder )
if not ( trans.user_is_admin() or trans.app.security_agent.can_access_library_item( current_user_roles, folder, trans.user ) ):
- if folder.parent_id == None:
+ if folder.parent_id is None:
try:
library = trans.sa_session.query( trans.app.model.Library ).filter( trans.app.model.Library.table.c.root_folder_id == decoded_folder_id ).one()
except Exception:
@@ -82,14 +83,14 @@
log.warning( "SECURITY: User (id: %s) without proper access rights is trying to load folder with ID of %s" % ( trans.user.id, decoded_folder_id ) )
else:
log.warning( "SECURITY: Anonymous user without proper access rights is trying to load folder with ID of %s" % ( decoded_folder_id ) )
- raise exceptions.ObjectNotFound( 'Folder with the id provided ( %s ) was not found' % str( folder_id ) )
+ raise exceptions.ObjectNotFound( 'Folder with the id provided ( %s ) was not found' % str( folder_id ) )
else:
if trans.user:
log.warning( "SECURITY: User (id: %s) without proper access rights is trying to load folder with ID of %s" % ( trans.user.id, decoded_folder_id ) )
else:
log.warning( "SECURITY: Anonymous user without proper access rights is trying to load folder with ID of %s" % ( decoded_folder_id ) )
raise exceptions.ObjectNotFound( 'Folder with the id provided ( %s ) was not found' % str( folder_id ) )
-
+
def build_path( folder ):
"""
Search the path upwards recursively and load the whole route of
@@ -111,50 +112,45 @@
upper_folder = trans.sa_session.query( trans.app.model.LibraryFolder ).get( folder.parent_id )
path_to_root.extend( build_path( upper_folder ) )
return path_to_root
-
+
# Return the reversed path so it starts with the library node.
full_path = build_path( folder )[::-1]
folder_contents = []
update_time = ''
create_time = ''
- # Go through every accessible item in the folder and include its meta-data.
+ # Go through every accessible item (folders, datasets) in the folder and include its meta-data.
for content_item in self._load_folder_contents( trans, folder, deleted ):
- can_access = trans.app.security_agent.can_access_library_item( current_user_roles, content_item, trans.user )
- if ( can_access or ( content_item.api_type == 'folder' and trans.app.security_agent.folder_is_unrestricted( content_item ) ) ):
- return_item = {}
- encoded_id = trans.security.encode_id( content_item.id )
- update_time = content_item.update_time.strftime( "%Y-%m-%d %I:%M %p" )
- create_time = content_item.create_time.strftime( "%Y-%m-%d %I:%M %p" )
+ return_item = {}
+ encoded_id = trans.security.encode_id( content_item.id )
+ update_time = content_item.update_time.strftime( "%Y-%m-%d %I:%M %p" )
+ create_time = content_item.create_time.strftime( "%Y-%m-%d %I:%M %p" )
- # For folder return also hierarchy values
- if content_item.api_type == 'folder':
- encoded_id = 'F' + encoded_id
+ if content_item.api_type == 'folder':
+ encoded_id = 'F' + encoded_id
- # this is commented for now as it includes the items that might not be accessible
- # item_count = content_item.item_count if can_access else 0
- # return_item.update ( dict ( item_count = item_count ) )
+ if content_item.api_type == 'file':
+ library_dataset_dict = content_item.to_dict()
+ library_dataset_dict[ 'is_unrestricted' ] = trans.app.security_agent.dataset_is_public( content_item.library_dataset_dataset_association.dataset )
+ library_dataset_dict[ 'is_private' ] = trans.app.security_agent.dataset_is_private_to_user( trans, content_item )
- if content_item.api_type == 'file':
- library_dataset_dict = content_item.to_dict()
- library_dataset_dict['data_type']
- library_dataset_dict['file_size']
- library_dataset_dict['date_uploaded']
- return_item.update ( dict ( data_type = library_dataset_dict['data_type'],
- file_size = library_dataset_dict['file_size'],
- date_uploaded = library_dataset_dict['date_uploaded'] ) )
+ return_item.update( dict( data_type=library_dataset_dict[ 'data_type' ],
+ file_size=library_dataset_dict[ 'file_size' ],
+ date_uploaded=library_dataset_dict[ 'date_uploaded' ],
+ is_unrestricted=library_dataset_dict[ 'is_unrestricted' ],
+ is_private=library_dataset_dict[ 'is_private' ] ) )
- # For every item return also the default meta-data
- return_item.update( dict( id = encoded_id,
- type = content_item.api_type,
- name = content_item.name,
- update_time = update_time,
- create_time = create_time,
- deleted = content_item.deleted
- ) )
- folder_contents.append( return_item )
+ # For every item include the default meta-data
+ return_item.update( dict( id=encoded_id,
+ type=content_item.api_type,
+ name=content_item.name,
+ update_time=update_time,
+ create_time=create_time,
+ deleted=content_item.deleted
+ ) )
+ folder_contents.append( return_item )
- return { 'metadata' : { 'full_path' : full_path, 'can_add_library_item': can_add_library_item, 'folder_name': folder.name }, 'folder_contents' : folder_contents }
+ return { 'metadata': { 'full_path': full_path, 'can_add_library_item': can_add_library_item, 'folder_name': folder.name }, 'folder_contents': folder_contents }
def _load_folder_contents( self, trans, folder, include_deleted ):
"""
@@ -166,7 +162,7 @@
:type folder: Galaxy LibraryFolder
:param include_deleted: flag, when true the items that are deleted
- and can be undeleted by current user are shown
+ and can be undeleted by current user are shown
:type include_deleted: boolean
:returns: a list containing the requested items
@@ -175,34 +171,42 @@
current_user_roles = trans.get_current_user_roles()
is_admin = trans.user_is_admin()
content_items = []
- for subfolder in folder.active_folders:
+ for subfolder in folder.folders:
if subfolder.deleted:
if include_deleted:
if is_admin:
+ # Admins can see all deleted folders.
subfolder.api_type = 'folder'
content_items.append( subfolder )
else:
+ # Users with MODIFY permissions can see deleted folders.
can_modify = trans.app.security_agent.can_modify_library_item( current_user_roles, subfolder )
if can_modify:
subfolder.api_type = 'folder'
content_items.append( subfolder )
else:
- if is_admin:
- subfolder.api_type = 'folder'
- content_items.append( subfolder )
- else:
- can_access, folder_ids = trans.app.security_agent.check_folder_contents( trans.user, current_user_roles, subfolder )
- if can_access:
- subfolder.api_type = 'folder'
- content_items.append( subfolder )
+ # Undeleted folders are non-restricted for now. The contents are not.
+ # TODO decide on restrictions
+ subfolder.api_type = 'folder'
+ content_items.append( subfolder )
+ # if is_admin:
+ # subfolder.api_type = 'folder'
+ # content_items.append( subfolder )
+ # else:
+ # can_access, folder_ids = trans.app.security_agent.check_folder_contents( trans.user, current_user_roles, subfolder )
+ # if can_access:
+ # subfolder.api_type = 'folder'
+ # content_items.append( subfolder )
for dataset in folder.datasets:
if dataset.deleted:
if include_deleted:
if is_admin:
+ # Admins can see all deleted datasets.
dataset.api_type = 'file'
content_items.append( dataset )
else:
+ # Users with MODIFY permissions on the item can see the deleted item.
can_modify = trans.app.security_agent.can_modify_library_item( current_user_roles, dataset )
if can_modify:
dataset.api_type = 'file'
@@ -230,19 +234,19 @@
:type payload: dict
* folder_id: the parent folder of the new item
- * from_hda_id: (optional) the id of an accessible HDA to copy
+ * from_hda_id: (optional) the id of an accessible HDA to copy
into the library
* ldda_message: (optional) the new message attribute of the LDDA
created
- * extended_metadata: (optional) dub-dictionary containing any
+ * extended_metadata: (optional) dub-dictionary containing any
extended metadata to associate with the item
- :returns: a dictionary containing the id, name,
+ :returns: a dictionary containing the id, name,
and 'show' url of the new item
:rtype: dict
- :raises: ObjectAttributeInvalidException,
- InsufficientPermissionsException, ItemAccessibilityException,
+ :raises: ObjectAttributeInvalidException,
+ InsufficientPermissionsException, ItemAccessibilityException,
InternalServerError
"""
encoded_folder_id_16 = self.__decode_library_content_id( trans, encoded_folder_id )
@@ -287,13 +291,13 @@
:param encoded_folder_id: encoded id of Galaxy LibraryFolder
:type encoded_folder_id: encoded string
- :returns: last 16 chars of the encoded id in case it was Folder
+ :returns: last 16 chars of the encoded id in case it was Folder
(had 'F' prepended)
:type: string
:raises: MalformedId
"""
- if ( len( encoded_folder_id ) == 17 and encoded_folder_id.startswith( 'F' )):
+ if ( len( encoded_folder_id ) == 17 and encoded_folder_id.startswith( 'F' )):
return encoded_folder_id[1:]
else:
raise exceptions.MalformedId( 'Malformed folder id ( %s ) specified, unable to decode.' % str( encoded_folder_id ) )
diff -r 9eb2b42e21fee519b1ea5e9c791bb6b8989f6b5c -r a73c02cd503ef2bec4819013517530df7045127e lib/galaxy/webapps/galaxy/api/folders.py
--- a/lib/galaxy/webapps/galaxy/api/folders.py
+++ b/lib/galaxy/webapps/galaxy/api/folders.py
@@ -1,18 +1,24 @@
"""
API operations on library folders
"""
-import os, string, shutil, urllib, re, socket, traceback
-from galaxy import datatypes, jobs, web, security
+# import os
+# import shutil
+# import urllib
+# import re
+# import socket
+# import traceback
+# import string
+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 BaseAPIController, UsesLibraryMixin, UsesLibraryMixinItems
from sqlalchemy.orm.exc import MultipleResultsFound
from sqlalchemy.orm.exc import NoResultFound
import logging
log = logging.getLogger( __name__ )
+
class FoldersController( BaseAPIController, UsesLibraryMixin, UsesLibraryMixinItems ):
@web.expose_api
@@ -32,18 +38,19 @@
Displays information about a folder.
- :param encoded_parent_folder_id: the parent folder's id (required)
- :type encoded_parent_folder_id: an encoded id string (should be prefixed by 'F')
+ :param id: the folder's encoded id (required)
+ :type id: an encoded id string (has to be prefixed by 'F')
+
+ :returns: dictionary including details of the folder
+ :rtype: dict
"""
- # Eliminate any 'F' in front of the folder id. Just take the
- # last 16 characters:
- if ( len( id ) >= 17 ):
- id = id[-16:]
- # Retrieve the folder and return its contents encoded. Note that the
- # check_ownership=false since we are only displaying it.
- content = self.get_library_folder( trans, id, check_ownership=False,
- check_accessible=True )
- return self.encode_all_ids( trans, content.to_dict( view='element' ) )
+ folder_id_without_prefix = self.__cut_the_prefix( id )
+ content = self.get_library_folder( trans, folder_id_without_prefix, check_ownership=False, check_accessible=True )
+ return_dict = self.encode_all_ids( trans, content.to_dict( view='element' ) )
+ return_dict[ 'id' ] = 'F' + return_dict[ 'id' ]
+ if return_dict[ 'parent_id' ] is not None:
+ return_dict[ 'parent_id' ] = 'F' + return_dict[ 'parent_id' ]
+ return return_dict
@expose_api
def create( self, trans, encoded_parent_folder_id, **kwd ):
@@ -53,13 +60,13 @@
*POST /api/folders/{encoded_parent_folder_id}
Create a new folder object underneath the one specified in the parameters.
-
+
:param encoded_parent_folder_id: the parent folder's id (required)
- :type encoded_parent_folder_id: an encoded id string (should be prefixed by 'F')
+ :type encoded_parent_folder_id: an encoded id string (should be prefixed by 'F')
:param name: the name of the new folder (required)
- :type name: str
-
+ :type name: str
+
:param description: the description of the new folder
:type description: str
@@ -70,16 +77,16 @@
"""
payload = kwd.get( 'payload', None )
- if payload == None:
+ if payload is None:
raise exceptions.RequestParameterMissingException( "Missing required parameters 'encoded_parent_folder_id' and 'name'." )
name = payload.get( 'name', None )
description = payload.get( 'description', '' )
- if encoded_parent_folder_id == None:
+ if encoded_parent_folder_id is None:
raise exceptions.RequestParameterMissingException( "Missing required parameter 'encoded_parent_folder_id'." )
- elif name == None:
+ elif name is None:
raise exceptions.RequestParameterMissingException( "Missing required parameter 'name'." )
- # encoded_parent_folder_id may be prefixed by 'F'
+ # encoded_parent_folder_id should be prefixed by 'F'
encoded_parent_folder_id = self.__cut_the_prefix( encoded_parent_folder_id )
try:
decoded_parent_folder_id = trans.security.decode_id( encoded_parent_folder_id )
@@ -93,7 +100,7 @@
except NoResultFound:
raise exceptions.RequestParameterInvalidException( 'No folder found with the id provided.' )
except Exception, e:
- raise exceptions.InternalServerError( 'Error loading from the database.' + str(e))
+ raise exceptions.InternalServerError( 'Error loading from the database.' + str( e ) )
library = parent_folder.parent_library
if library.deleted:
@@ -108,29 +115,28 @@
try:
folder = trans.sa_session.query( trans.app.model.LibraryFolder ).get( v.id )
except Exception, e:
- raise exceptions.InternalServerError( 'Error loading from the database.' + str( e ))
+ raise exceptions.InternalServerError( 'Error loading from the database.' + str( e ))
if folder:
- return_dict = folder.to_dict( view='element' )
- return_dict[ 'parent_library_id' ] = trans.security.encode_id( return_dict[ 'parent_library_id' ] )
- return_dict[ 'parent_id' ] = 'F' + trans.security.encode_id( return_dict[ 'parent_id' ] )
- return_dict[ 'id' ] = 'F' + trans.security.encode_id( return_dict[ 'id' ] )
+ update_time = folder.update_time.strftime( "%Y-%m-%d %I:%M %p" )
+ return_dict = self.encode_all_ids( trans, folder.to_dict( view='element' ) )
+ return_dict[ 'update_time' ] = update_time
+ return_dict[ 'parent_id' ] = 'F' + return_dict[ 'parent_id' ]
+ return_dict[ 'id' ] = 'F' + return_dict[ 'id' ]
return return_dict
else:
- raise exceptions.InternalServerError( 'Error while creating a folder.' + str(e))
+ raise exceptions.InternalServerError( 'Error while creating a folder.' + str( e ) )
@web.expose_api
def update( self, trans, id, library_id, payload, **kwd ):
"""
PUT /api/folders/{encoded_folder_id}
- For now this does nothing. There are no semantics for folders that
- indicates that an update operation is needed; the existing
- library_contents folder does not allow for update, either.
+
"""
- pass
+ raise exceptions.NotImplemented( 'Updating folder through this endpoint is not implemented yet.' )
def __cut_the_prefix(self, encoded_id):
- if ( len( encoded_id ) == 17 and encoded_id.startswith( 'F' ) ):
- return encoded_id[-16:]
+
+ if ( ( len( encoded_id ) % 2 == 1 ) and encoded_id.startswith( 'F' ) ):
+ return encoded_id[ 1: ]
else:
- return encoded_id
-
+ raise exceptions.MalformedId( 'Malformed folder id ( %s ) specified, unable to decode.' % str( encoded_id ) )
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.