Add decorators.@required_feature to centralize FeatureDisabled exc.
This commit is contained in:
		
							parent
							
								
									af6785cead
								
							
						
					
					
						commit
						09f209719b
					
				
					 4 changed files with 35 additions and 27 deletions
				
			
		|  | @ -154,6 +154,7 @@ DEFAULT_CONFIGURATION = { | ||||||
|     'cache_size_tag': 1000, |     'cache_size_tag': 1000, | ||||||
|     'cache_size_user': 200, |     'cache_size_user': 200, | ||||||
| 
 | 
 | ||||||
|  |     'enable_album_edit': True, | ||||||
|     'enable_new_album': True, |     'enable_new_album': True, | ||||||
|     'enable_new_bookmark': True, |     'enable_new_bookmark': True, | ||||||
|     'enable_new_photo': True, |     'enable_new_photo': True, | ||||||
|  |  | ||||||
|  | @ -7,6 +7,30 @@ import warnings | ||||||
| from . import jsonify | from . import jsonify | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | def required_feature(features): | ||||||
|  |     ''' | ||||||
|  |     Declare that the photodb or object method requires certain 'enable_*' | ||||||
|  |     fields in the config. | ||||||
|  |     ''' | ||||||
|  |     from . import objects | ||||||
|  |     if isinstance(features, str): | ||||||
|  |         features = [features] | ||||||
|  | 
 | ||||||
|  |     def wrapper(function): | ||||||
|  |         @functools.wraps(function) | ||||||
|  |         def wrapped(self, *args, **kwargs): | ||||||
|  |             if isinstance(self, objects.ObjectBase): | ||||||
|  |                 config = self.photodb.config | ||||||
|  |             else: | ||||||
|  |                 config = self.config | ||||||
|  | 
 | ||||||
|  |             if not all(config[key] for key in features): | ||||||
|  |                 raise exceptions.FeatureDisabled(function.__name__) | ||||||
|  | 
 | ||||||
|  |             return function(self, *args, **kwargs) | ||||||
|  |         return wrapped | ||||||
|  |     return wrapper | ||||||
|  | 
 | ||||||
| def required_fields(fields, forbid_whitespace=False): | def required_fields(fields, forbid_whitespace=False): | ||||||
|     ''' |     ''' | ||||||
|     Declare that the endpoint requires certain POST body fields. Without them, |     Declare that the endpoint requires certain POST body fields. Without them, | ||||||
|  |  | ||||||
|  | @ -307,6 +307,7 @@ class Album(ObjectBase, GroupableMixin): | ||||||
|         else: |         else: | ||||||
|             return self.id |             return self.id | ||||||
| 
 | 
 | ||||||
|  |     @decorators.required_feature('enable_album_edit') | ||||||
|     @decorators.transaction |     @decorators.transaction | ||||||
|     def edit(self, title=None, description=None, *, commit=True): |     def edit(self, title=None, description=None, *, commit=True): | ||||||
|         ''' |         ''' | ||||||
|  | @ -488,11 +489,9 @@ class Photo(ObjectBase): | ||||||
|     def _uncache(self): |     def _uncache(self): | ||||||
|         self.photodb.caches['photo'].remove(self.id) |         self.photodb.caches['photo'].remove(self.id) | ||||||
| 
 | 
 | ||||||
|  |     @decorators.required_feature('enable_photo_add_remove_tag') | ||||||
|     @decorators.transaction |     @decorators.transaction | ||||||
|     def add_tag(self, tag, *, commit=True): |     def add_tag(self, tag, *, commit=True): | ||||||
|         if not self.photodb.config['enable_photo_add_remove_tag']: |  | ||||||
|             raise exceptions.FeatureDisabled('photo.add_tag, photo.remove_tag') |  | ||||||
| 
 |  | ||||||
|         tag = self.photodb.get_tag(tag) |         tag = self.photodb.get_tag(tag) | ||||||
| 
 | 
 | ||||||
|         existing = self.has_tag(tag, check_children=False) |         existing = self.has_tag(tag, check_children=False) | ||||||
|  | @ -577,15 +576,13 @@ class Photo(ObjectBase): | ||||||
|         return helpers.seconds_to_hms(self.duration) |         return helpers.seconds_to_hms(self.duration) | ||||||
| 
 | 
 | ||||||
|     #@decorators.time_me |     #@decorators.time_me | ||||||
|  |     @decorators.required_feature('enable_photo_generate_thumbnail') | ||||||
|     @decorators.transaction |     @decorators.transaction | ||||||
|     def generate_thumbnail(self, *, commit=True, **special): |     def generate_thumbnail(self, *, commit=True, **special): | ||||||
|         ''' |         ''' | ||||||
|         special: |         special: | ||||||
|             For videos, you can provide a `timestamp` to take the thumbnail at. |             For videos, you can provide a `timestamp` to take the thumbnail at. | ||||||
|         ''' |         ''' | ||||||
|         if not self.photodb.config['enable_photo_generate_thumbnail']: |  | ||||||
|             raise exceptions.FeatureDisabled('photo.generate_thumbnail') |  | ||||||
| 
 |  | ||||||
|         hopeful_filepath = self.make_thumbnail_filepath() |         hopeful_filepath = self.make_thumbnail_filepath() | ||||||
|         hopeful_filepath = hopeful_filepath.relative_path |         hopeful_filepath = hopeful_filepath.relative_path | ||||||
|         #print(hopeful_filepath) |         #print(hopeful_filepath) | ||||||
|  | @ -714,14 +711,12 @@ class Photo(ObjectBase): | ||||||
|         return hopeful_filepath |         return hopeful_filepath | ||||||
| 
 | 
 | ||||||
|     #@decorators.time_me |     #@decorators.time_me | ||||||
|  |     @decorators.required_feature('enable_photo_reload_metadata') | ||||||
|     @decorators.transaction |     @decorators.transaction | ||||||
|     def reload_metadata(self, *, commit=True): |     def reload_metadata(self, *, commit=True): | ||||||
|         ''' |         ''' | ||||||
|         Load the file's height, width, etc as appropriate for this type of file. |         Load the file's height, width, etc as appropriate for this type of file. | ||||||
|         ''' |         ''' | ||||||
|         if not self.photodb.config['enable_photo_reload_metadata']: |  | ||||||
|             raise exceptions.FeatureDisabled('photo.reload_metadata') |  | ||||||
| 
 |  | ||||||
|         self.bytes = os.path.getsize(self.real_filepath) |         self.bytes = os.path.getsize(self.real_filepath) | ||||||
|         self.width = None |         self.width = None | ||||||
|         self.height = None |         self.height = None | ||||||
|  | @ -806,11 +801,9 @@ class Photo(ObjectBase): | ||||||
|             self.photodb.log.debug('Commit - relocate photo') |             self.photodb.log.debug('Commit - relocate photo') | ||||||
|             self.photodb.commit() |             self.photodb.commit() | ||||||
| 
 | 
 | ||||||
|  |     @decorators.required_feature('enable_photo_add_remove_tag') | ||||||
|     @decorators.transaction |     @decorators.transaction | ||||||
|     def remove_tag(self, tag, *, commit=True): |     def remove_tag(self, tag, *, commit=True): | ||||||
|         if not self.photodb.config['enable_photo_add_remove_tag']: |  | ||||||
|             raise exceptions.FeatureDisabled('photo.add_tag, photo.remove_tag') |  | ||||||
| 
 |  | ||||||
|         tag = self.photodb.get_tag(tag) |         tag = self.photodb.get_tag(tag) | ||||||
| 
 | 
 | ||||||
|         self.photodb.log.debug('Removing tag {t} from photo {p}'.format(t=repr(tag), p=repr(self))) |         self.photodb.log.debug('Removing tag {t} from photo {p}'.format(t=repr(tag), p=repr(self))) | ||||||
|  |  | ||||||
|  | @ -280,6 +280,7 @@ class PDBAlbumMixin: | ||||||
|             if album.parent() is None: |             if album.parent() is None: | ||||||
|                 yield album |                 yield album | ||||||
| 
 | 
 | ||||||
|  |     @decorators.required_feature('enable_new_album') | ||||||
|     @decorators.transaction |     @decorators.transaction | ||||||
|     def new_album( |     def new_album( | ||||||
|             self, |             self, | ||||||
|  | @ -293,9 +294,6 @@ class PDBAlbumMixin: | ||||||
|         ''' |         ''' | ||||||
|         Create a new album. Photos can be added now or later. |         Create a new album. Photos can be added now or later. | ||||||
|         ''' |         ''' | ||||||
|         if not self.config['enable_new_album']: |  | ||||||
|             raise exceptions.FeatureDisabled('new_album') |  | ||||||
| 
 |  | ||||||
|         albumid = self.generate_id('albums') |         albumid = self.generate_id('albums') | ||||||
|         title = title or '' |         title = title or '' | ||||||
|         description = description or '' |         description = description or '' | ||||||
|  | @ -365,11 +363,9 @@ class PDBBookmarkMixin: | ||||||
|     def get_bookmarks(self): |     def get_bookmarks(self): | ||||||
|         yield from self.get_things(thing_type='bookmark') |         yield from self.get_things(thing_type='bookmark') | ||||||
| 
 | 
 | ||||||
|  |     @decorators.required_feature('enable_new_bookmark') | ||||||
|     @decorators.transaction |     @decorators.transaction | ||||||
|     def new_bookmark(self, url, title=None, *, author=None, commit=True): |     def new_bookmark(self, url, title=None, *, author=None, commit=True): | ||||||
|         if not self.config['enable_new_bookmark']: |  | ||||||
|             raise exceptions.FeatureDisabled('new_bookmark') |  | ||||||
| 
 |  | ||||||
|         if not url: |         if not url: | ||||||
|             raise ValueError('Must provide a URL') |             raise ValueError('Must provide a URL') | ||||||
| 
 | 
 | ||||||
|  | @ -440,6 +436,7 @@ class PDBPhotoMixin: | ||||||
|             if count <= 0: |             if count <= 0: | ||||||
|                 break |                 break | ||||||
| 
 | 
 | ||||||
|  |     @decorators.required_feature('enable_new_photo') | ||||||
|     @decorators.transaction |     @decorators.transaction | ||||||
|     def new_photo( |     def new_photo( | ||||||
|             self, |             self, | ||||||
|  | @ -461,9 +458,6 @@ class PDBPhotoMixin: | ||||||
| 
 | 
 | ||||||
|         Returns the Photo object. |         Returns the Photo object. | ||||||
|         ''' |         ''' | ||||||
|         if not self.config['enable_new_photo']: |  | ||||||
|             raise exceptions.FeatureDisabled('new_photo') |  | ||||||
| 
 |  | ||||||
|         filepath = pathclass.Path(filepath) |         filepath = pathclass.Path(filepath) | ||||||
|         if not filepath.is_file: |         if not filepath.is_file: | ||||||
|             raise FileNotFoundError(filepath.absolute_path) |             raise FileNotFoundError(filepath.absolute_path) | ||||||
|  | @ -954,14 +948,12 @@ class PDBTagMixin: | ||||||
|     def get_tags(self): |     def get_tags(self): | ||||||
|         yield from self.get_things(thing_type='tag') |         yield from self.get_things(thing_type='tag') | ||||||
| 
 | 
 | ||||||
|  |     @decorators.required_feature('enable_new_tag') | ||||||
|     @decorators.transaction |     @decorators.transaction | ||||||
|     def new_tag(self, tagname, *, commit=True): |     def new_tag(self, tagname, *, commit=True): | ||||||
|         ''' |         ''' | ||||||
|         Register a new tag and return the Tag object. |         Register a new tag and return the Tag object. | ||||||
|         ''' |         ''' | ||||||
|         if not self.config['enable_new_tag']: |  | ||||||
|             raise exceptions.FeatureDisabled('new_tag') |  | ||||||
| 
 |  | ||||||
|         tagname = self.normalize_tagname(tagname) |         tagname = self.normalize_tagname(tagname) | ||||||
|         try: |         try: | ||||||
|             existing_tag = self.get_tag_by_name(tagname) |             existing_tag = self.get_tag_by_name(tagname) | ||||||
|  | @ -1080,11 +1072,9 @@ class PDBUserMixin: | ||||||
| 
 | 
 | ||||||
|         return objects.User(self, fetch) |         return objects.User(self, fetch) | ||||||
| 
 | 
 | ||||||
|  |     @decorators.required_feature('enable_new_user') | ||||||
|     @decorators.transaction |     @decorators.transaction | ||||||
|     def register_user(self, username, password, commit=True): |     def register_user(self, username, password, commit=True): | ||||||
|         if not self.config['enable_new_user']: |  | ||||||
|             raise exceptions.FeatureDisabled('new_user') |  | ||||||
| 
 |  | ||||||
|         if len(username) < self.config['min_username_length']: |         if len(username) < self.config['min_username_length']: | ||||||
|             raise exceptions.UsernameTooShort( |             raise exceptions.UsernameTooShort( | ||||||
|                 username=username, |                 username=username, | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue