Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Managers, sharable: implement list_shared_with; API, histories: imple… #614

Merged
merged 1 commit into from
Aug 19, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 17 additions & 9 deletions lib/galaxy/managers/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ def _session_setattr( self, item, attr, val, fn=None, flush=True ):
return item

# .... query foundation wrapper
def query( self, eagerloads=True, filters=None, order_by=None, limit=None, offset=None, **kwargs ):
def query( self, eagerloads=True, **kwargs ):
"""
Return a basic query from model_class, filters, order_by, and limit and offset.

Expand All @@ -188,7 +188,10 @@ def query( self, eagerloads=True, filters=None, order_by=None, limit=None, offse
# joined table loading
if eagerloads is False:
query = query.enable_eagerloads( False )
return self._filter_and_order_query( query, **kwargs )

def _filter_and_order_query( self, query, filters=None, order_by=None, limit=None, offset=None, **kwargs ):
# TODO: not a lot of functional cohesion here
query = self._apply_orm_filters( query, filters )
query = self._apply_order_by( query, order_by )
query = self._apply_orm_limit_offset( query, limit, offset )
Expand Down Expand Up @@ -299,21 +302,19 @@ def by_id( self, id, **kwargs ):
return self.one( filters=id_filter, **kwargs )

# .... multirow queries
def _orm_list( self, query=None, **kwargs ):
"""
Sends kwargs to build the query return all models found.
"""
query = query or self.query( **kwargs )
return query.all()

def list( self, filters=None, order_by=None, limit=None, offset=None, **kwargs ):
"""
Returns all objects matching the given filters
"""
# list becomes a way of applying both filters generated in the orm (such as .user ==)
# and functional filters that aren't currently possible using the orm (such as instance calcluated values
# or annotations/tags). List splits those two filters and applies limits/offsets
# only after functional filters (if any) using python.
orm_filters, fn_filters = self._split_filters( filters )
if not fn_filters:
# if no fn_filtering required, we can use the 'all orm' version with limit offset
return self._orm_list( filters=orm_filters, order_by=order_by, limit=limit, offset=offset, **kwargs )
return self._orm_list( filters=orm_filters, order_by=order_by,
limit=limit, offset=offset, **kwargs )

# fn filters will change the number of items returnable by limit/offset - remove them here from the orm query
query = self.query( filters=orm_filters, order_by=order_by, limit=None, offset=None, **kwargs )
Expand Down Expand Up @@ -347,6 +348,13 @@ def _is_fn_filter( self, filter_ ):
"""
return callable( filter_ )

def _orm_list( self, query=None, **kwargs ):
"""
Sends kwargs to build the query return all models found.
"""
query = query or self.query( **kwargs )
return query.all()

def _apply_fn_filters_gen( self, items, filters ):
"""
If all the filter functions in `filters` return True for an item in `items`,
Expand Down
45 changes: 32 additions & 13 deletions lib/galaxy/managers/sharable.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@


class SharableModelManager( base.ModelManager, secured.OwnableManagerMixin, secured.AccessibleManagerMixin,
taggable.TaggableManagerMixin, annotatable.AnnotatableManagerMixin, ratable.RatableManagerMixin ):
taggable.TaggableManagerMixin, annotatable.AnnotatableManagerMixin, ratable.RatableManagerMixin ):
# e.g. histories, pages, stored workflows, visualizations
# base.DeleteableModelMixin? (all four are deletable)

Expand Down Expand Up @@ -185,17 +185,36 @@ def unshare_with( self, item, user, flush=True ):
self.session().flush()
return user_share_assoc

# def _query_shared_with( self, user, filters=None, **kwargs ):
# TODO:
# """
# """
# pass
def _query_shared_with( self, user, eagerloads=True, **kwargs ):
"""
Return a query for this model already filtered to models shared
with a particular user.
"""
query = self.session().query( self.model_class ).join( 'users_shared_with' )
if eagerloads is False:
query = query.enable_eagerloads( False )
# TODO: as filter in FilterParser also
query = query.filter( self.user_share_model.user == user )
return self._filter_and_order_query( query, **kwargs )

# def list_shared_with( self, user, **kwargs ):
# """
# """
# query = self._query_shared_with( user, **kwargs )
# return self.list( query=query, **kwargs )
def list_shared_with( self, user, filters=None, order_by=None, limit=None, offset=None, **kwargs ):
"""
Return a list of those models shared with a particular user.
"""
# TODO: refactor out dupl-code btwn base.list
orm_filters, fn_filters = self._split_filters( filters )
if not fn_filters:
# if no fn_filtering required, we can use the 'all orm' version with limit offset
query = self._query_shared_with( user, filters=orm_filters,
order_by=order_by, limit=limit, offset=offset, **kwargs )
return self._orm_list( query=query, **kwargs )

# fn filters will change the number of items returnable by limit/offset - remove them here from the orm query
query = self._query_shared_with( user, filters=orm_filters,
order_by=order_by, limit=None, offset=None, **kwargs )
# apply limit and offset afterwards
items = self._apply_fn_filters_gen( query.all(), fn_filters )
return list( self._apply_fn_limit_offset_gen( items, limit, offset ) )

# .... slugs
# slugs are human readable strings often used to link to sharable resources (replacing ids)
Expand Down Expand Up @@ -303,7 +322,7 @@ def create_unique_slug( self, item, flush=True ):


class SharableModelSerializer( base.ModelSerializer,
taggable.TaggableSerializerMixin, annotatable.AnnotatableSerializerMixin, ratable.RatableSerializerMixin ):
taggable.TaggableSerializerMixin, annotatable.AnnotatableSerializerMixin, ratable.RatableSerializerMixin ):
# TODO: stub
SINGLE_CHAR_ABBR = None

Expand Down Expand Up @@ -342,7 +361,7 @@ def serialize_username_and_slug( self, item, key, **context ):


class SharableModelDeserializer( base.ModelDeserializer,
taggable.TaggableDeserializerMixin, annotatable.AnnotatableDeserializerMixin, ratable.RatableDeserializerMixin ):
taggable.TaggableDeserializerMixin, annotatable.AnnotatableDeserializerMixin, ratable.RatableDeserializerMixin ):

def add_deserializers( self ):
super( SharableModelDeserializer, self ).add_deserializers()
Expand Down
38 changes: 33 additions & 5 deletions lib/galaxy/webapps/galaxy/api/histories.py
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ def show( self, trans, id, deleted='False', **kwd ):
history = self.history_manager.get_accessible( self.decode_id( history_id ), trans.user, current_history=trans.history )

return self.history_serializer.serialize_to_view( history,
user=trans.user, trans=trans, **self._parse_serialization_params( kwd, 'detailed' ) )
user=trans.user, trans=trans, **self._parse_serialization_params( kwd, 'detailed' ) )

@expose_api_anonymous
def citations( self, trans, history_id, **kwd ):
Expand Down Expand Up @@ -237,7 +237,34 @@ def published( self, trans, **kwd ):
histories = self.history_manager.list_published( filters=filters, order_by=order_by, limit=limit, offset=offset )
rval = []
for history in histories:
history_dict = self.history_serializer.serialize_to_view( history, user=trans.user, trans=trans, **self._parse_serialization_params( kwd, 'summary' ) )
history_dict = self.history_serializer.serialize_to_view( history, user=trans.user, trans=trans,
**self._parse_serialization_params( kwd, 'summary' ) )
rval.append( history_dict )
return rval

@expose_api_anonymous_and_sessionless
def shared_with_me( self, trans, **kwd ):
"""
shared_with_me( self, trans, **kwd )
* GET /api/histories/shared_with_me:
return all histories that are shared with the current user

:rtype: list
:returns: list of dictionaries containing summary history information

Follows the same filtering logic as the index() method above.
"""
current_user = trans.user
limit, offset = self.parse_limit_offset( kwd )
filter_params = self.parse_filter_params( kwd )
filters = self.history_filters.parse_filters( filter_params )
order_by = self._parse_order_by( kwd.get( 'order', 'create_time-dsc' ) )
histories = self.history_manager.list_shared_with( current_user,
filters=filters, order_by=order_by, limit=limit, offset=offset )
rval = []
for history in histories:
history_dict = self.history_serializer.serialize_to_view( history, user=current_user, trans=trans,
**self._parse_serialization_params( kwd, 'summary' ) )
rval.append( history_dict )
return rval

Expand Down Expand Up @@ -288,7 +315,7 @@ def create( self, trans, payload, **kwd ):
trans.sa_session.flush()

return self.history_serializer.serialize_to_view( new_history,
user=trans.user, trans=trans, **self._parse_serialization_params( kwd, 'detailed' ) )
user=trans.user, trans=trans, **self._parse_serialization_params( kwd, 'detailed' ) )

@expose_api
def delete( self, trans, id, **kwd ):
Expand Down Expand Up @@ -327,7 +354,7 @@ def delete( self, trans, id, **kwd ):
self.history_manager.purge( history )

return self.history_serializer.serialize_to_view( history,
user=trans.user, trans=trans, **self._parse_serialization_params( kwd, 'detailed' ) )
user=trans.user, trans=trans, **self._parse_serialization_params( kwd, 'detailed' ) )

@expose_api
def undelete( self, trans, id, **kwd ):
Expand All @@ -345,12 +372,13 @@ def undelete( self, trans, id, **kwd ):
:rtype: str
:returns: 'OK' if the history was undeleted
"""
# TODO: remove at v2
history_id = id
history = self.history_manager.get_owned( self.decode_id( history_id ), trans.user, current_history=trans.history )
self.history_manager.undelete( history )

return self.history_serializer.serialize_to_view( history,
user=trans.user, trans=trans, **self._parse_serialization_params( kwd, 'detailed' ) )
user=trans.user, trans=trans, **self._parse_serialization_params( kwd, 'detailed' ) )

@expose_api
def update( self, trans, id, payload, **kwd ):
Expand Down
1 change: 1 addition & 0 deletions lib/galaxy/webapps/galaxy/buildapp.py
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,7 @@ def populate_api_routes( webapp, app ):
name_prefix="history_content_",
path_prefix='/api/histories/:history_id/contents/:history_content_id' )
webapp.mapper.connect( '/api/histories/published', action='published', controller="histories", conditions=dict( method=[ "GET" ] ) )
webapp.mapper.connect( '/api/histories/shared_with_me', action='shared_with_me', controller="histories" )
_add_item_tags_controller( webapp,
name_prefix="history_",
path_prefix='/api/histories/:history_id' )
Expand Down