Add decorators.@transaction to rollback sql upon exception
This commit is contained in:
		
							parent
							
								
									c71a45191e
								
							
						
					
					
						commit
						af6785cead
					
				
					 3 changed files with 53 additions and 0 deletions
				
			
		|  | @ -55,3 +55,16 @@ def time_me(function): | ||||||
|         print('%s: %0.8f' % (function.__name__, end-start)) |         print('%s: %0.8f' % (function.__name__, end-start)) | ||||||
|         return result |         return result | ||||||
|     return timed_function |     return timed_function | ||||||
|  | 
 | ||||||
|  | def transaction(method): | ||||||
|  |     @functools.wraps(method) | ||||||
|  |     def wrapped(self, *args, **kwargs): | ||||||
|  |         try: | ||||||
|  |             ret = method(self, *args, **kwargs) | ||||||
|  |             return ret | ||||||
|  |         except Exception as e: | ||||||
|  |             self.log.debug('Rolling back') | ||||||
|  |             print(e) | ||||||
|  |             self.sql.rollback() | ||||||
|  |             raise | ||||||
|  |     return wrapped | ||||||
|  |  | ||||||
|  | @ -17,6 +17,14 @@ class ObjectBase: | ||||||
|         super().__init__() |         super().__init__() | ||||||
|         self.photodb = photodb |         self.photodb = photodb | ||||||
| 
 | 
 | ||||||
|  |     @property | ||||||
|  |     def log(self): | ||||||
|  |         return self.photodb.log | ||||||
|  | 
 | ||||||
|  |     @property | ||||||
|  |     def sql(self): | ||||||
|  |         return self.photodb.sql | ||||||
|  | 
 | ||||||
|     def __eq__(self, other): |     def __eq__(self, other): | ||||||
|         return ( |         return ( | ||||||
|             isinstance(other, type(self)) and |             isinstance(other, type(self)) and | ||||||
|  | @ -39,6 +47,7 @@ class GroupableMixin: | ||||||
|     group_sql_index = None |     group_sql_index = None | ||||||
|     group_table = None |     group_table = None | ||||||
| 
 | 
 | ||||||
|  |     @decorators.transaction | ||||||
|     def add(self, member, *, commit=True): |     def add(self, member, *, commit=True): | ||||||
|         ''' |         ''' | ||||||
|         Add a child object to this group. |         Add a child object to this group. | ||||||
|  | @ -99,6 +108,7 @@ class GroupableMixin: | ||||||
|             results.sort(key=lambda x: x.id) |             results.sort(key=lambda x: x.id) | ||||||
|         return results |         return results | ||||||
| 
 | 
 | ||||||
|  |     @decorators.transaction | ||||||
|     def delete(self, *, delete_children=False, commit=True): |     def delete(self, *, delete_children=False, commit=True): | ||||||
|         ''' |         ''' | ||||||
|         Delete this object's relationships to other groupables. |         Delete this object's relationships to other groupables. | ||||||
|  | @ -160,6 +170,7 @@ class GroupableMixin: | ||||||
|         parentid = fetch[self.group_sql_index['parentid']] |         parentid = fetch[self.group_sql_index['parentid']] | ||||||
|         return self.group_getter(id=parentid) |         return self.group_getter(id=parentid) | ||||||
| 
 | 
 | ||||||
|  |     @decorators.transaction | ||||||
|     def join_group(self, group, *, commit=True): |     def join_group(self, group, *, commit=True): | ||||||
|         ''' |         ''' | ||||||
|         Leave the current group, then call `group.add(self)`. |         Leave the current group, then call `group.add(self)`. | ||||||
|  | @ -175,6 +186,7 @@ class GroupableMixin: | ||||||
|         self.leave_group(commit=commit) |         self.leave_group(commit=commit) | ||||||
|         group.add(self, commit=commit) |         group.add(self, commit=commit) | ||||||
| 
 | 
 | ||||||
|  |     @decorators.transaction | ||||||
|     def leave_group(self, *, commit=True): |     def leave_group(self, *, commit=True): | ||||||
|         ''' |         ''' | ||||||
|         Leave the current group and become independent. |         Leave the current group and become independent. | ||||||
|  | @ -228,6 +240,8 @@ class Album(ObjectBase, GroupableMixin): | ||||||
|         self._sum_bytes_photos = None |         self._sum_bytes_photos = None | ||||||
|         self._sum_bytes_albums = None |         self._sum_bytes_albums = None | ||||||
| 
 | 
 | ||||||
|  |     @decorators.transaction | ||||||
|  |     @decorators.transaction | ||||||
|     def add_photo(self, photo, *, commit=True): |     def add_photo(self, photo, *, commit=True): | ||||||
|         if self.photodb != photo.photodb: |         if self.photodb != photo.photodb: | ||||||
|             raise ValueError('Not the same PhotoDB') |             raise ValueError('Not the same PhotoDB') | ||||||
|  | @ -241,6 +255,7 @@ class Album(ObjectBase, GroupableMixin): | ||||||
|             self.photodb.log.debug('Committing - add photo to album') |             self.photodb.log.debug('Committing - add photo to album') | ||||||
|             self.photodb.commit() |             self.photodb.commit() | ||||||
| 
 | 
 | ||||||
|  |     @decorators.transaction | ||||||
|     def add_tag_to_all(self, tag, *, nested_children=True, commit=True): |     def add_tag_to_all(self, tag, *, nested_children=True, commit=True): | ||||||
|         ''' |         ''' | ||||||
|         Add this tag to every photo in the album. Saves you from having to |         Add this tag to every photo in the album. Saves you from having to | ||||||
|  | @ -272,6 +287,7 @@ class Album(ObjectBase, GroupableMixin): | ||||||
|         directories = [pathclass.Path(x) for x in directories] |         directories = [pathclass.Path(x) for x in directories] | ||||||
|         return directories |         return directories | ||||||
| 
 | 
 | ||||||
|  |     @decorators.transaction | ||||||
|     def delete(self, *, delete_children=False, commit=True): |     def delete(self, *, delete_children=False, commit=True): | ||||||
|         self.photodb.log.debug('Deleting album {album:r}'.format(album=self)) |         self.photodb.log.debug('Deleting album {album:r}'.format(album=self)) | ||||||
|         GroupableMixin.delete(self, delete_children=delete_children, commit=False) |         GroupableMixin.delete(self, delete_children=delete_children, commit=False) | ||||||
|  | @ -291,6 +307,7 @@ class Album(ObjectBase, GroupableMixin): | ||||||
|         else: |         else: | ||||||
|             return self.id |             return self.id | ||||||
| 
 | 
 | ||||||
|  |     @decorators.transaction | ||||||
|     def edit(self, title=None, description=None, *, commit=True): |     def edit(self, title=None, description=None, *, commit=True): | ||||||
|         ''' |         ''' | ||||||
|         Change the title or description. Leave None to keep current value. |         Change the title or description. Leave None to keep current value. | ||||||
|  | @ -335,6 +352,7 @@ class Album(ObjectBase, GroupableMixin): | ||||||
|         photos.sort(key=lambda x: x.basename.lower()) |         photos.sort(key=lambda x: x.basename.lower()) | ||||||
|         return photos |         return photos | ||||||
| 
 | 
 | ||||||
|  |     @decorators.transaction | ||||||
|     def remove_photo(self, photo, *, commit=True): |     def remove_photo(self, photo, *, commit=True): | ||||||
|         if not self.has_photo(photo): |         if not self.has_photo(photo): | ||||||
|             return |             return | ||||||
|  | @ -386,12 +404,14 @@ class Bookmark(ObjectBase): | ||||||
|     def __repr__(self): |     def __repr__(self): | ||||||
|         return 'Bookmark:{id}'.format(id=self.id) |         return 'Bookmark:{id}'.format(id=self.id) | ||||||
| 
 | 
 | ||||||
|  |     @decorators.transaction | ||||||
|     def delete(self, *, commit=True): |     def delete(self, *, commit=True): | ||||||
|         cur = self.photodb.sql.cursor() |         cur = self.photodb.sql.cursor() | ||||||
|         cur.execute('DELETE FROM bookmarks WHERE id == ?', [self.id]) |         cur.execute('DELETE FROM bookmarks WHERE id == ?', [self.id]) | ||||||
|         if commit: |         if commit: | ||||||
|             self.photodb.commit() |             self.photodb.commit() | ||||||
| 
 | 
 | ||||||
|  |     @decorators.transaction | ||||||
|     def edit(self, title=None, url=None, *, commit=True): |     def edit(self, title=None, url=None, *, commit=True): | ||||||
|         if title is None and url is None: |         if title is None and url is None: | ||||||
|             return |             return | ||||||
|  | @ -468,6 +488,7 @@ class Photo(ObjectBase): | ||||||
|     def _uncache(self): |     def _uncache(self): | ||||||
|         self.photodb.caches['photo'].remove(self.id) |         self.photodb.caches['photo'].remove(self.id) | ||||||
| 
 | 
 | ||||||
|  |     @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']: |         if not self.photodb.config['enable_photo_add_remove_tag']: | ||||||
|             raise exceptions.FeatureDisabled('photo.add_tag, photo.remove_tag') |             raise exceptions.FeatureDisabled('photo.add_tag, photo.remove_tag') | ||||||
|  | @ -526,6 +547,7 @@ class Photo(ObjectBase): | ||||||
|         for tag in other_photo.tags(): |         for tag in other_photo.tags(): | ||||||
|             self.add_tag(tag) |             self.add_tag(tag) | ||||||
| 
 | 
 | ||||||
|  |     @decorators.transaction | ||||||
|     def delete(self, *, delete_file=False, commit=True): |     def delete(self, *, delete_file=False, commit=True): | ||||||
|         ''' |         ''' | ||||||
|         Delete the Photo and its relation to any tags and albums. |         Delete the Photo and its relation to any tags and albums. | ||||||
|  | @ -555,6 +577,7 @@ class Photo(ObjectBase): | ||||||
|         return helpers.seconds_to_hms(self.duration) |         return helpers.seconds_to_hms(self.duration) | ||||||
| 
 | 
 | ||||||
|     #@decorators.time_me |     #@decorators.time_me | ||||||
|  |     @decorators.transaction | ||||||
|     def generate_thumbnail(self, *, commit=True, **special): |     def generate_thumbnail(self, *, commit=True, **special): | ||||||
|         ''' |         ''' | ||||||
|         special: |         special: | ||||||
|  | @ -691,6 +714,7 @@ class Photo(ObjectBase): | ||||||
|         return hopeful_filepath |         return hopeful_filepath | ||||||
| 
 | 
 | ||||||
|     #@decorators.time_me |     #@decorators.time_me | ||||||
|  |     @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. | ||||||
|  | @ -749,6 +773,7 @@ class Photo(ObjectBase): | ||||||
|             self.photodb.log.debug('Committing - reload metadata') |             self.photodb.log.debug('Committing - reload metadata') | ||||||
|             self.photodb.commit() |             self.photodb.commit() | ||||||
| 
 | 
 | ||||||
|  |     @decorators.transaction | ||||||
|     def relocate(self, new_filepath, *, allow_duplicates=False, commit=True): |     def relocate(self, new_filepath, *, allow_duplicates=False, commit=True): | ||||||
|         ''' |         ''' | ||||||
|         Point the Photo object to a different filepath. |         Point the Photo object to a different filepath. | ||||||
|  | @ -781,6 +806,7 @@ class Photo(ObjectBase): | ||||||
|             self.photodb.log.debug('Commit - relocate photo') |             self.photodb.log.debug('Commit - relocate photo') | ||||||
|             self.photodb.commit() |             self.photodb.commit() | ||||||
| 
 | 
 | ||||||
|  |     @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']: |         if not self.photodb.config['enable_photo_add_remove_tag']: | ||||||
|             raise exceptions.FeatureDisabled('photo.add_tag, photo.remove_tag') |             raise exceptions.FeatureDisabled('photo.add_tag, photo.remove_tag') | ||||||
|  | @ -802,6 +828,7 @@ class Photo(ObjectBase): | ||||||
|             self.photodb.log.debug('Committing - remove photo tag') |             self.photodb.log.debug('Committing - remove photo tag') | ||||||
|             self.photodb.commit() |             self.photodb.commit() | ||||||
| 
 | 
 | ||||||
|  |     @decorators.transaction | ||||||
|     def rename_file(self, new_filename, *, move=False, commit=True): |     def rename_file(self, new_filename, *, move=False, commit=True): | ||||||
|         ''' |         ''' | ||||||
|         Rename the file on the disk as well as in the database. |         Rename the file on the disk as well as in the database. | ||||||
|  | @ -921,6 +948,7 @@ class Tag(ObjectBase, GroupableMixin): | ||||||
|     def _uncache(self): |     def _uncache(self): | ||||||
|         self.photodb.caches['tag'].remove(self.id) |         self.photodb.caches['tag'].remove(self.id) | ||||||
| 
 | 
 | ||||||
|  |     @decorators.transaction | ||||||
|     def add_synonym(self, synname, *, commit=True): |     def add_synonym(self, synname, *, commit=True): | ||||||
|         synname = self.photodb.normalize_tagname(synname) |         synname = self.photodb.normalize_tagname(synname) | ||||||
| 
 | 
 | ||||||
|  | @ -945,6 +973,7 @@ class Tag(ObjectBase, GroupableMixin): | ||||||
| 
 | 
 | ||||||
|         return synname |         return synname | ||||||
| 
 | 
 | ||||||
|  |     @decorators.transaction | ||||||
|     def convert_to_synonym(self, mastertag, *, commit=True): |     def convert_to_synonym(self, mastertag, *, commit=True): | ||||||
|         ''' |         ''' | ||||||
|         Convert this tag into a synonym for a different tag. |         Convert this tag into a synonym for a different tag. | ||||||
|  | @ -993,6 +1022,7 @@ class Tag(ObjectBase, GroupableMixin): | ||||||
|             self.photodb.log.debug('Committing - convert to synonym') |             self.photodb.log.debug('Committing - convert to synonym') | ||||||
|             self.photodb.commit() |             self.photodb.commit() | ||||||
| 
 | 
 | ||||||
|  |     @decorators.transaction | ||||||
|     def delete(self, *, delete_children=False, commit=True): |     def delete(self, *, delete_children=False, commit=True): | ||||||
|         self.photodb.log.debug('Deleting tag {tag:r}'.format(tag=self)) |         self.photodb.log.debug('Deleting tag {tag:r}'.format(tag=self)) | ||||||
|         self.photodb._cached_frozen_children = None |         self.photodb._cached_frozen_children = None | ||||||
|  | @ -1018,6 +1048,7 @@ class Tag(ObjectBase, GroupableMixin): | ||||||
|         self._cached_qualified_name = qualname |         self._cached_qualified_name = qualname | ||||||
|         return qualname |         return qualname | ||||||
| 
 | 
 | ||||||
|  |     @decorators.transaction | ||||||
|     def remove_synonym(self, synname, *, commit=True): |     def remove_synonym(self, synname, *, commit=True): | ||||||
|         ''' |         ''' | ||||||
|         Delete a synonym. |         Delete a synonym. | ||||||
|  | @ -1043,6 +1074,7 @@ class Tag(ObjectBase, GroupableMixin): | ||||||
|             self.photodb.log.debug('Committing - remove synonym') |             self.photodb.log.debug('Committing - remove synonym') | ||||||
|             self.photodb.commit() |             self.photodb.commit() | ||||||
| 
 | 
 | ||||||
|  |     @decorators.transaction | ||||||
|     def rename(self, new_name, *, apply_to_synonyms=True, commit=True): |     def rename(self, new_name, *, apply_to_synonyms=True, commit=True): | ||||||
|         ''' |         ''' | ||||||
|         Rename the tag. Does not affect its relation to Photos or tag groups. |         Rename the tag. Does not affect its relation to Photos or tag groups. | ||||||
|  |  | ||||||
|  | @ -280,6 +280,7 @@ class PDBAlbumMixin: | ||||||
|             if album.parent() is None: |             if album.parent() is None: | ||||||
|                 yield album |                 yield album | ||||||
| 
 | 
 | ||||||
|  |     @decorators.transaction | ||||||
|     def new_album( |     def new_album( | ||||||
|             self, |             self, | ||||||
|             title=None, |             title=None, | ||||||
|  | @ -364,6 +365,7 @@ 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.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']: |         if not self.config['enable_new_bookmark']: | ||||||
|             raise exceptions.FeatureDisabled('new_bookmark') |             raise exceptions.FeatureDisabled('new_bookmark') | ||||||
|  | @ -438,6 +440,7 @@ class PDBPhotoMixin: | ||||||
|             if count <= 0: |             if count <= 0: | ||||||
|                 break |                 break | ||||||
| 
 | 
 | ||||||
|  |     @decorators.transaction | ||||||
|     def new_photo( |     def new_photo( | ||||||
|             self, |             self, | ||||||
|             filepath, |             filepath, | ||||||
|  | @ -518,6 +521,7 @@ class PDBPhotoMixin: | ||||||
|             self.commit() |             self.commit() | ||||||
|         return photo |         return photo | ||||||
| 
 | 
 | ||||||
|  |     @decorators.transaction | ||||||
|     def purge_deleted_files(self, photos=None, *, commit=True): |     def purge_deleted_files(self, photos=None, *, commit=True): | ||||||
|         ''' |         ''' | ||||||
|         Remove Photo entries if their corresponding file is no longer found. |         Remove Photo entries if their corresponding file is no longer found. | ||||||
|  | @ -536,6 +540,7 @@ class PDBPhotoMixin: | ||||||
|             self.log.debug('Committing - purge deleted photos') |             self.log.debug('Committing - purge deleted photos') | ||||||
|             self.commit() |             self.commit() | ||||||
| 
 | 
 | ||||||
|  |     @decorators.transaction | ||||||
|     def purge_empty_albums(self, *, commit=True): |     def purge_empty_albums(self, *, commit=True): | ||||||
|         albums = self.get_albums() |         albums = self.get_albums() | ||||||
|         for album in albums: |         for album in albums: | ||||||
|  | @ -949,6 +954,7 @@ 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.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. | ||||||
|  | @ -1074,6 +1080,7 @@ class PDBUserMixin: | ||||||
| 
 | 
 | ||||||
|         return objects.User(self, fetch) |         return objects.User(self, fetch) | ||||||
| 
 | 
 | ||||||
|  |     @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']: |         if not self.config['enable_new_user']: | ||||||
|             raise exceptions.FeatureDisabled('new_user') |             raise exceptions.FeatureDisabled('new_user') | ||||||
|  | @ -1216,6 +1223,7 @@ class PhotoDB(PDBAlbumMixin, PDBBookmarkMixin, PDBPhotoMixin, PDBTagMixin, PDBUs | ||||||
|             task['action'](*args, **kwargs) |             task['action'](*args, **kwargs) | ||||||
|         self.sql.commit() |         self.sql.commit() | ||||||
| 
 | 
 | ||||||
|  |     @decorators.transaction | ||||||
|     def digest_directory( |     def digest_directory( | ||||||
|             self, |             self, | ||||||
|             directory, |             directory, | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue