Managers: normalize mixin names (remove Interface, Model, add where appropriate); Fix 'has' substr filter name in tests

This commit is contained in:
Carl Eberhard
2015-01-29 15:20:46 -05:00
parent a850aa8300
commit ec3eec5609
9 changed files with 71 additions and 70 deletions
+3 -3
View File
@@ -6,7 +6,7 @@ import logging
log = logging.getLogger( __name__ )
class AnnotatableManagerInterface( object ):
class AnnotatableManagerMixin( object ):
#: class of AnnotationAssociation (e.g. HistoryAnnotationAssociation)
annotation_assoc = None
@@ -33,7 +33,7 @@ class AnnotatableManagerInterface( object ):
# pass
class AnnotatableSerializer( object ):
class AnnotatableSerializerMixin( object ):
def add_serializers( self ):
self.serializers[ 'annotation' ] = self.serialize_annotation
@@ -50,7 +50,7 @@ class AnnotatableSerializer( object ):
return returned
class AnnotatableDeserializer( object ):
class AnnotatableDeserializerMixin( object ):
def add_deserializers( self ):
self.deserializers[ 'annotation' ] = self.deserialize_annotation
+19 -19
View File
@@ -760,7 +760,7 @@ class ModelValidator( object ):
# ==== Building query filters based on model data
class FilterParser( object ):
class ModelFilterParser( object ):
"""
Converts string tuples (partially converted query string params) of
attr, op, val into either:
@@ -996,7 +996,7 @@ class FilterParser( object ):
# ==== Security Mixins
class AccessibleModelInterface( object ):
class AccessibleManagerMixin( object ):
"""
A security interface to check if a User can read/view an item's.
@@ -1009,7 +1009,7 @@ class AccessibleModelInterface( object ):
Return True if the item accessible to user.
"""
# override in subclasses
raise exceptions.NotImplemented( "Abstract Interface Method" )
raise exceptions.NotImplemented( "Abstract interface Method" )
def get_accessible( self, trans, id, user, **kwargs ):
"""
@@ -1039,7 +1039,7 @@ class AccessibleModelInterface( object ):
:raises exceptions.ItemAccessibilityException:
"""
raise exceptions.NotImplemented( "Abstract Interface Method" )
raise exceptions.NotImplemented( "Abstract interface Method" )
# NOTE: this will be a large, inefficient list if filters are not passed in kwargs
# items = ModelManager.list( self, trans, **kwargs )
# return [ self.error_unless_accessible( trans, item, user ) for item in items ]
@@ -1048,13 +1048,13 @@ class AccessibleModelInterface( object ):
"""
Return a list of items accessible to the user.
"""
raise exceptions.NotImplemented( "Abstract Interface Method" )
raise exceptions.NotImplemented( "Abstract interface Method" )
# NOTE: this will be a large, inefficient list if filters are not passed in kwargs
# items = ModelManager.list( self, trans, **kwargs )
# return filter( lambda item: self.is_accessible( trans, item, user ), items )
class OwnableModelInterface( object ):
class OwnableManagerMixin( object ):
"""
A security interface to check if a User is an item's owner.
@@ -1069,7 +1069,7 @@ class OwnableModelInterface( object ):
Return True if user owns the item.
"""
# override in subclasses
raise exceptions.NotImplemented( "Abstract Interface Method" )
raise exceptions.NotImplemented( "Abstract interface Method" )
def get_owned( self, trans, id, user, **kwargs ):
"""
@@ -1098,7 +1098,7 @@ class OwnableModelInterface( object ):
:raises exceptions.ItemAccessibilityException:
"""
raise exceptions.NotImplemented( "Abstract Interface Method" )
raise exceptions.NotImplemented( "Abstract interface Method" )
# just alias to by_user (easier/same thing)
#return self.by_user( trans, user, **kwargs )
@@ -1111,7 +1111,7 @@ class OwnableModelInterface( object ):
# ---- Deletable and Purgable models
class DeletableModelInterface( object ):
class DeletableManagerMixin( object ):
"""
A mixin/interface for a model that is deletable (i.e. has a 'deleted' attr).
@@ -1141,14 +1141,14 @@ class DeletableModelInterface( object ):
return item
class DeletableModelSerializer( object ):
class DeletableSerializerMixin( object ):
def add_serializers( self ):
pass
# TODO: these are of questionable value if we don't want to enable users to delete/purge via update
class DeletableModelDeserializer( object ):
class DeletableDeserializerMixin( object ):
def add_deserializers( self ):
self.deserializers[ 'deleted' ] = self.deserialize_deleted
@@ -1168,7 +1168,7 @@ class DeletableModelDeserializer( object ):
return item.deleted
class DeletableModelFilters( object ):
class DeletableFiltersMixin( object ):
def _add_parsers( self ):
self.orm_filter_parsers.update({
@@ -1176,7 +1176,7 @@ class DeletableModelFilters( object ):
})
class PurgableModelInterface( DeletableModelInterface ):
class PurgableManagerMixin( DeletableManagerMixin ):
"""
A manager interface/mixin for a resource that allows deleting and purging where
purging is often removal of some additional, non-db resource (e.g. a dataset's
@@ -1196,16 +1196,16 @@ class PurgableModelInterface( DeletableModelInterface ):
return item
class PurgableModelSerializer( DeletableModelSerializer ):
class PurgableSerializerMixin( DeletableSerializerMixin ):
def add_serializers( self ):
DeletableModelSerializer.add_serializers( self )
DeletableSerializerMixin.add_serializers( self )
class PurgableModelDeserializer( DeletableModelDeserializer ):
class PurgableDeserializerMixin( DeletableDeserializerMixin ):
def add_deserializers( self ):
DeletableModelDeserializer.add_deserializers( self )
DeletableDeserializerMixin.add_deserializers( self )
self.deserializers[ 'purged' ] = self.deserialize_purged
def deserialize_purged( self, trans, item, key, val ):
@@ -1220,10 +1220,10 @@ class PurgableModelDeserializer( DeletableModelDeserializer ):
return self.purged
class PurgableModelFilters( DeletableModelFilters ):
class PurgableFiltersMixin( DeletableFiltersMixin ):
def _add_parsers( self ):
DeletableModelFilters._add_parsers( self )
DeletableFiltersMixin._add_parsers( self )
self.orm_filter_parsers.update({
'purged' : { 'op': ( 'eq' ), 'val': self.parse_bool }
})
+11 -10
View File
@@ -11,7 +11,7 @@ import logging
log = logging.getLogger( __name__ )
class DatasetManager( base.ModelManager, base.AccessibleModelInterface, base.PurgableModelInterface ):
class DatasetManager( base.ModelManager, base.AccessibleManagerMixin, base.PurgableManagerMixin ):
"""
Manipulate datasets: the components contained in DatasetAssociations/DatasetInstances/HDAs/LDDAs
"""
@@ -185,7 +185,7 @@ class DatasetManager( base.ModelManager, base.AccessibleModelInterface, base.Pur
# .... data, object_store
class DatasetSerializer( base.ModelSerializer, base.PurgableModelSerializer ):
class DatasetSerializer( base.ModelSerializer, base.PurgableSerializerMixin ):
def __init__( self, app ):
super( DatasetSerializer, self ).__init__( app )
@@ -212,7 +212,8 @@ class DatasetSerializer( base.ModelSerializer, base.PurgableModelSerializer ):
self.default_view = 'summary'
def add_serializers( self ):
base.PurgableModelSerializer.add_serializers( self )
super( DatasetSerializer, self ).add_serializers()
base.PurgableSerializerMixin.add_serializers( self )
self.serializers.update({
'id' : self.serialize_id,
'create_time' : self.serialize_date,
@@ -221,16 +222,16 @@ class DatasetSerializer( base.ModelSerializer, base.PurgableModelSerializer ):
})
class DatasetDeserializer( base.ModelDeserializer, base.PurgableModelDeserializer ):
class DatasetDeserializer( base.ModelDeserializer, base.PurgableDeserializerMixin ):
model_manager_class = DatasetManager
def add_deserializers( self ):
super( DatasetDeserializer, self ).add_deserializers()
base.PurgableModelDeserializer.add_deserializers( self )
base.PurgableDeserializerMixin.add_deserializers( self )
class DatasetAssociationManager( base.ModelManager, base.AccessibleModelInterface, base.PurgableModelInterface ):
class DatasetAssociationManager( base.ModelManager, base.AccessibleManagerMixin, base.PurgableManagerMixin ):
"""
DatasetAssociation/DatasetInstances are intended to be working
proxies to a Dataset, associated with either a library or a
@@ -265,15 +266,15 @@ class DatasetAssociationManager( base.ModelManager, base.AccessibleModelInterfac
# pass
class DatasetAssociationSerializer( base.ModelSerializer, base.PurgableModelSerializer ):
class DatasetAssociationSerializer( base.ModelSerializer, base.PurgableSerializerMixin ):
def add_serializers( self ):
super( DatasetAssociationSerializer, self ).add_serializers()
base.PurgableModelSerializer.add_serializers( self )
base.PurgableSerializerMixin.add_serializers( self )
class DatasetAssociationDeserializer( base.ModelDeserializer, base.PurgableModelDeserializer ):
class DatasetAssociationDeserializer( base.ModelDeserializer, base.PurgableDeserializerMixin ):
def add_deserializers( self ):
super( DatasetAssociationDeserializer, self ).add_deserializers()
base.PurgableModelDeserializer.add_deserializers( self )
base.PurgableDeserializerMixin.add_deserializers( self )
+8 -8
View File
@@ -25,8 +25,8 @@ import logging
log = logging.getLogger( __name__ )
class HDAManager( datasets.DatasetAssociationManager, base.OwnableModelInterface,
taggable.TaggableManagerInterface, annotatable.AnnotatableManagerInterface ):
class HDAManager( datasets.DatasetAssociationManager, base.OwnableManagerMixin,
taggable.TaggableManagerMixin, annotatable.AnnotatableManagerMixin ):
"""
Interface/service object for interacting with HDAs.
"""
@@ -308,7 +308,7 @@ class HDAManager( datasets.DatasetAssociationManager, base.OwnableModelInterface
class HDASerializer( datasets.DatasetAssociationSerializer,
taggable.TaggableSerializer, annotatable.AnnotatableSerializer ):
taggable.TaggableSerializerMixin, annotatable.AnnotatableSerializerMixin ):
#TODO: inherit from datasets.DatasetAssociationSerializer
#TODO: move what makes sense into DatasetSerializer
@@ -379,8 +379,8 @@ class HDASerializer( datasets.DatasetAssociationSerializer,
def add_serializers( self ):
super( HDASerializer, self ).add_serializers()
taggable.TaggableSerializer.add_serializers( self )
annotatable.AnnotatableSerializer.add_serializers( self )
taggable.TaggableSerializerMixin.add_serializers( self )
annotatable.AnnotatableSerializerMixin.add_serializers( self )
self.serializers.update({
'model_class' : lambda *a: 'HistoryDatasetAssociation',
@@ -568,7 +568,7 @@ class HDASerializer( datasets.DatasetAssociationSerializer,
class HDADeserializer( datasets.DatasetAssociationDeserializer,
taggable.TaggableDeserializer, annotatable.AnnotatableDeserializer ):
taggable.TaggableDeserializerMixin, annotatable.AnnotatableDeserializerMixin ):
"""
Interface/service object for validating and deserializing dictionaries into histories.
"""
@@ -580,8 +580,8 @@ class HDADeserializer( datasets.DatasetAssociationDeserializer,
def add_deserializers( self ):
super( HDADeserializer, self ).add_deserializers()
taggable.TaggableDeserializer.add_deserializers( self )
annotatable.AnnotatableDeserializer.add_deserializers( self )
taggable.TaggableDeserializerMixin.add_deserializers( self )
annotatable.AnnotatableDeserializerMixin.add_deserializers( self )
self.deserializers.update({
'name' : self.deserialize_basestring,
+7 -7
View File
@@ -16,7 +16,7 @@ import logging
log = logging.getLogger( __name__ )
class HistoryManager( sharable.SharableModelManager, base.PurgableModelInterface ):
class HistoryManager( sharable.SharableModelManager, base.PurgableManagerMixin ):
model_class = model.History
foreign_key_name = 'history'
@@ -234,7 +234,7 @@ class HistoryManager( sharable.SharableModelManager, base.PurgableModelInterface
return state
class HistorySerializer( sharable.SharableModelSerializer, base.PurgableModelSerializer ):
class HistorySerializer( sharable.SharableModelSerializer, base.PurgableSerializerMixin ):
"""
Interface/service object for serializing histories into dictionaries.
"""
@@ -288,7 +288,7 @@ class HistorySerializer( sharable.SharableModelSerializer, base.PurgableModelSer
#assumes: outgoing to json.dumps and sanitized
def add_serializers( self ):
super( HistorySerializer, self ).add_serializers()
base.PurgableModelSerializer.add_serializers( self )
base.PurgableSerializerMixin.add_serializers( self )
self.serializers.update({
'model_class' : lambda *a: 'History',
@@ -333,7 +333,7 @@ class HistorySerializer( sharable.SharableModelSerializer, base.PurgableModelSer
security=self.app.security, parent=dataset_collection_instance.history, view="element" )
class HistoryDeserializer( sharable.SharableModelDeserializer, base.PurgableModelDeserializer ):
class HistoryDeserializer( sharable.SharableModelDeserializer, base.PurgableDeserializerMixin ):
"""
Interface/service object for validating and deserializing dictionaries into histories.
"""
@@ -345,7 +345,7 @@ class HistoryDeserializer( sharable.SharableModelDeserializer, base.PurgableMode
def add_deserializers( self ):
super( HistoryDeserializer, self ).add_deserializers()
base.PurgableModelDeserializer.add_deserializers( self )
base.PurgableDeserializerMixin.add_deserializers( self )
self.deserializers.update({
'name' : self.deserialize_basestring,
@@ -353,12 +353,12 @@ class HistoryDeserializer( sharable.SharableModelDeserializer, base.PurgableMode
})
class HistoryFilters( sharable.SharableModelFilters, base.PurgableModelFilters ):
class HistoryFilters( sharable.SharableModelFilters, base.PurgableFiltersMixin ):
model_class = model.History
def _add_parsers( self ):
super( HistoryFilters, self )._add_parsers()
base.PurgableModelFilters._add_parsers( self )
base.PurgableFiltersMixin._add_parsers( self )
self.orm_filter_parsers.update({
# history specific
+3 -3
View File
@@ -10,7 +10,7 @@ log = logging.getLogger( __name__ )
#TODO: stub
class RatableManagerInterface( object ):
class RatableManagerMixin( object ):
#: class of RatingAssociation (e.g. HistoryRatingAssociation)
rating_assoc = None
@@ -20,7 +20,7 @@ class RatableManagerInterface( object ):
# pass
class RatableSerializer( object ):
class RatableSerializerMixin( object ):
def add_serializers( self ):
self.serializers[ 'user_rating' ] = self.serialize_user_rating
@@ -37,7 +37,7 @@ class RatableSerializer( object ):
pass
class RatableDeserializer( object ):
class RatableDeserializerMixin( object ):
def add_deserializers( self ):
pass
+12 -12
View File
@@ -24,10 +24,10 @@ import logging
log = logging.getLogger( __name__ )
class SharableModelManager( base.ModelManager, base.OwnableModelInterface, base.AccessibleModelInterface,
taggable.TaggableManagerInterface, annotatable.AnnotatableManagerInterface, ratable.RatableManagerInterface ):
class SharableModelManager( base.ModelManager, base.OwnableManagerMixin, base.AccessibleManagerMixin,
taggable.TaggableManagerMixin, annotatable.AnnotatableManagerMixin, ratable.RatableManagerMixin ):
# e.g. histories, pages, stored workflows, visualizations
# base.DeleteableModelInterface? (all four are deletable)
# base.DeleteableModelMixin? (all four are deletable)
#: the model used for UserShareAssociations with this model
user_share_model = None
@@ -333,15 +333,15 @@ class SharableModelManager( base.ModelManager, base.OwnableModelInterface, base.
class SharableModelSerializer( base.ModelSerializer,
taggable.TaggableSerializer, annotatable.AnnotatableSerializer, ratable.RatableSerializer ):
taggable.TaggableSerializerMixin, annotatable.AnnotatableSerializerMixin, ratable.RatableSerializerMixin ):
#TODO: stub
SINGLE_CHAR_ABBR = None
def add_serializers( self ):
super( SharableModelSerializer, self ).add_serializers()
taggable.TaggableSerializer.add_serializers( self )
annotatable.AnnotatableSerializer.add_serializers( self )
ratable.RatableSerializer.add_serializers( self )
taggable.TaggableSerializerMixin.add_serializers( self )
annotatable.AnnotatableSerializerMixin.add_serializers( self )
ratable.RatableSerializerMixin.add_serializers( self )
self.serializers.update({
'user_id' : self.serialize_id,
@@ -370,13 +370,13 @@ class SharableModelSerializer( base.ModelSerializer,
class SharableModelDeserializer( base.ModelDeserializer,
taggable.TaggableDeserializer, annotatable.AnnotatableDeserializer, ratable.RatableDeserializer ):
taggable.TaggableDeserializerMixin, annotatable.AnnotatableDeserializerMixin, ratable.RatableDeserializerMixin ):
def add_deserializers( self ):
super( SharableModelDeserializer, self ).add_deserializers()
taggable.TaggableDeserializer.add_deserializers( self )
annotatable.AnnotatableDeserializer.add_deserializers( self )
ratable.RatableDeserializer.add_deserializers( self )
taggable.TaggableDeserializerMixin.add_deserializers( self )
annotatable.AnnotatableDeserializerMixin.add_deserializers( self )
ratable.RatableDeserializerMixin.add_deserializers( self )
self.deserializers.update({
'published' : self.deserialize_published,
@@ -418,7 +418,7 @@ class SharableModelDeserializer( base.ModelDeserializer,
#def deserialize_user_shares():
class SharableModelFilters( base.FilterParser ):
class SharableModelFilters( base.ModelFilterParser ):
def _add_parsers( self ):
super( SharableModelFilters, self )._add_parsers()
+3 -3
View File
@@ -9,7 +9,7 @@ import logging
log = logging.getLogger( __name__ )
class TaggableManagerInterface( object ):
class TaggableManagerMixin( object ):
#: class of TagAssociation (e.g. HistoryTagAssociation)
tag_assoc = None
@@ -19,7 +19,7 @@ class TaggableManagerInterface( object ):
# pass
class TaggableSerializer( object ):
class TaggableSerializerMixin( object ):
def add_serializers( self ):
self.serializers[ 'tags' ] = self.serialize_tags
@@ -40,7 +40,7 @@ class TaggableSerializer( object ):
return tags_str_list
class TaggableDeserializer( object ):
class TaggableDeserializerMixin( object ):
def add_deserializers( self ):
self.deserializers[ 'tags' ] = self.deserialize_tags
+5 -5
View File
@@ -311,7 +311,7 @@ class HistoryManagerTestCase( BaseTestCase ):
filters = filter_parser.parse_filters([
( 'name', 'eq', 'wot' ),
( 'deleted', 'eq', 'True' ),
( 'annotation', 'in', 'hrrmm' )
( 'annotation', 'has', 'hrrmm' )
])
self.log( 'both orm and fn filters should be parsed and returned' )
self.assertEqual( len( filters ), 3 )
@@ -387,7 +387,7 @@ class HistoryManagerTestCase( BaseTestCase ):
history2 = self.history_mgr.create( self.trans, name='history2', user=user2 )
history3 = self.history_mgr.create( self.trans, name='history3', user=user2 )
filters = filter_parser.parse_filters([ ( 'annotation', 'in', 'no play' ), ])
filters = filter_parser.parse_filters([ ( 'annotation', 'has', 'no play' ), ])
anno_filter = filters[0]
history3.add_item_annotation( self.trans.sa_session, user2, history3, "All work and no play" )
@@ -406,7 +406,7 @@ class HistoryManagerTestCase( BaseTestCase ):
shining_examples = self.history_mgr.list( self.trans, filters=filter_parser.parse_filters([
( 'importable', 'eq', 'True' ),
( 'annotation', 'in', 'no play' ),
( 'annotation', 'has', 'no play' ),
]))
self.assertEqual( shining_examples, [ history3 ])
@@ -491,7 +491,7 @@ class HistoryManagerTestCase( BaseTestCase ):
found = self.history_mgr.list( self.trans, filters=filters, offset=1, limit=1 )
self.assertEqual( found, [ history2 ] )
filters = filter_parser.parse_filters([ ( 'annotation', 'in', test_annotation ) ])
filters = filter_parser.parse_filters([ ( 'annotation', 'has', test_annotation ) ])
self.log( "fn filtered, no offset, no limit should work" )
found = self.history_mgr.list( self.trans, filters=filters )
self.assertEqual( found, [ history2, history3, history4 ] )
@@ -507,7 +507,7 @@ class HistoryManagerTestCase( BaseTestCase ):
filters = filter_parser.parse_filters([
( 'deleted', 'eq', 'True' ),
( 'annotation', 'in', test_annotation )
( 'annotation', 'has', test_annotation )
])
self.log( "orm and fn filtered, no offset, no limit should work" )
found = self.history_mgr.list( self.trans, filters=filters )