From 7001ed476d4597df8ee227c332cca8b0929d94b2 Mon Sep 17 00:00:00 2001 From: Ruud Date: Sun, 26 Jan 2014 00:33:21 +0100 Subject: [PATCH] Wrap all commits with try/except --- couchpotato/__init__.py | 4 +- couchpotato/core/media/__init__.py | 37 ++- couchpotato/core/media/_base/media/main.py | 126 ++++----- couchpotato/core/media/movie/_base/main.py | 183 +++++++------ couchpotato/core/media/movie/library/movie/main.py | 261 ++++++++++--------- couchpotato/core/media/movie/searcher/main.py | 7 +- couchpotato/core/media/movie/suggestion/main.py | 2 - couchpotato/core/notifications/core/main.py | 69 +++-- couchpotato/core/plugins/category/main.py | 130 ++++++---- couchpotato/core/plugins/dashboard/main.py | 1 - couchpotato/core/plugins/file/main.py | 72 ++++-- couchpotato/core/plugins/profile/main.py | 240 ++++++++++------- couchpotato/core/plugins/quality/main.py | 127 +++++---- couchpotato/core/plugins/release/main.py | 287 ++++++++++++--------- couchpotato/core/plugins/renamer/main.py | 1 + couchpotato/core/plugins/scanner/main.py | 2 +- couchpotato/core/plugins/status/main.py | 75 +++--- couchpotato/core/settings/__init__.py | 23 +- couchpotato/environment.py | 25 +- 19 files changed, 951 insertions(+), 721 deletions(-) diff --git a/couchpotato/__init__.py b/couchpotato/__init__.py index 966da0c..6b8cfd3 100644 --- a/couchpotato/__init__.py +++ b/couchpotato/__init__.py @@ -48,8 +48,8 @@ def addView(route, func, static = False): views[route] = func -def get_session(engine = None): - return Env.getSession(engine) +def get_session(): + return Env.getSession() # Web view diff --git a/couchpotato/core/media/__init__.py b/couchpotato/core/media/__init__.py index 2635ca6..512c52c 100644 --- a/couchpotato/core/media/__init__.py +++ b/couchpotato/core/media/__init__.py @@ -1,3 +1,4 @@ +import traceback from couchpotato import get_session from couchpotato.core.event import addEvent, fireEventAsync, fireEvent from couchpotato.core.plugins.base import Plugin @@ -26,25 +27,33 @@ class MediaBase(Plugin): def createOnComplete(self, id): def onComplete(): - db = get_session() - media = db.query(Media).filter_by(id = id).first() - media_dict = media.to_dict(self.default_dict) - event_name = '%s.searcher.single' % media.type - db.expire_all() - - fireEvent(event_name, media_dict, on_complete = self.createNotifyFront(id)) + try: + db = get_session() + media = db.query(Media).filter_by(id = id).first() + media_dict = media.to_dict(self.default_dict) + event_name = '%s.searcher.single' % media.type + + fireEvent(event_name, media_dict, on_complete = self.createNotifyFront(id)) + except: + log.error('Failed creating onComplete: %s', traceback.format_exc()) + finally: + db.close() return onComplete def createNotifyFront(self, media_id): def notifyFront(): - db = get_session() - media = db.query(Media).filter_by(id = media_id).first() - media_dict = media.to_dict(self.default_dict) - event_name = '%s.update' % media.type - db.expire_all() - - fireEvent('notify.frontend', type = event_name, data = media_dict) + try: + db = get_session() + media = db.query(Media).filter_by(id = media_id).first() + media_dict = media.to_dict(self.default_dict) + event_name = '%s.update' % media.type + + fireEvent('notify.frontend', type = event_name, data = media_dict) + except: + log.error('Failed creating onComplete: %s', traceback.format_exc()) + finally: + db.close() return notifyFront diff --git a/couchpotato/core/media/_base/media/main.py b/couchpotato/core/media/_base/media/main.py index 0ae1b3a..cbcd424 100644 --- a/couchpotato/core/media/_base/media/main.py +++ b/couchpotato/core/media/_base/media/main.py @@ -1,3 +1,4 @@ +import traceback from couchpotato import get_session, tryInt from couchpotato.api import addApiView from couchpotato.core.event import fireEvent, fireEventAsync, addEvent @@ -100,8 +101,6 @@ class MediaPlugin(MediaBase): def handler(): fireEvent(event, identifier = identifier, default_title = default_title, on_complete = self.createOnComplete(id)) - db.expire_all() - if handler: return handler @@ -125,7 +124,6 @@ class MediaPlugin(MediaBase): if m: results = m.to_dict(self.default_dict) - db.expire_all() return results def getView(self, id = None, **kwargs): @@ -261,7 +259,6 @@ class MediaPlugin(MediaBase): 'releases_count': releases_count.get(media_id), })) - db.expire_all() return total_count, movies def listView(self, **kwargs): @@ -355,7 +352,6 @@ class MediaPlugin(MediaBase): if len(chars) == 25: break - db.expire_all() return ''.join(sorted(chars)) def charView(self, **kwargs): @@ -380,50 +376,55 @@ class MediaPlugin(MediaBase): def delete(self, media_id, delete_from = None): - db = get_session() + try: + db = get_session() - media = db.query(Media).filter_by(id = media_id).first() - if media: - deleted = False - if delete_from == 'all': - db.delete(media) - db.commit() - deleted = True - else: - done_status = fireEvent('status.get', 'done', single = True) - - total_releases = len(media.releases) - total_deleted = 0 - new_movie_status = None - for release in media.releases: - if delete_from in ['wanted', 'snatched', 'late']: - if release.status_id != done_status.get('id'): - db.delete(release) - total_deleted += 1 - new_movie_status = 'done' - elif delete_from == 'manage': - if release.status_id == done_status.get('id'): - db.delete(release) - total_deleted += 1 - new_movie_status = 'active' - db.commit() - - if total_releases == total_deleted: + media = db.query(Media).filter_by(id = media_id).first() + if media: + deleted = False + if delete_from == 'all': db.delete(media) db.commit() deleted = True - elif new_movie_status: - new_status = fireEvent('status.get', new_movie_status, single = True) - media.profile_id = None - media.status_id = new_status.get('id') - db.commit() else: - fireEvent('media.restatus', media.id, single = True) + done_status = fireEvent('status.get', 'done', single = True) + + total_releases = len(media.releases) + total_deleted = 0 + new_movie_status = None + for release in media.releases: + if delete_from in ['wanted', 'snatched', 'late']: + if release.status_id != done_status.get('id'): + db.delete(release) + total_deleted += 1 + new_movie_status = 'done' + elif delete_from == 'manage': + if release.status_id == done_status.get('id'): + db.delete(release) + total_deleted += 1 + new_movie_status = 'active' + db.commit() - if deleted: - fireEvent('notify.frontend', type = 'movie.deleted', data = media.to_dict()) + if total_releases == total_deleted: + db.delete(media) + db.commit() + deleted = True + elif new_movie_status: + new_status = fireEvent('status.get', new_movie_status, single = True) + media.profile_id = None + media.status_id = new_status.get('id') + db.commit() + else: + fireEvent('media.restatus', media.id, single = True) + + if deleted: + fireEvent('notify.frontend', type = 'movie.deleted', data = media.to_dict()) + except: + log.error('Failed deleting media: %s', traceback.format_exc()) + db.rollback() + finally: + db.close() - db.expire_all() return True def deleteView(self, id = '', **kwargs): @@ -447,28 +448,33 @@ class MediaPlugin(MediaBase): active_status, done_status = fireEvent('status.get', ['active', 'done'], single = True) - db = get_session() + try: + db = get_session() - m = db.query(Media).filter_by(id = media_id).first() - if not m or len(m.library.titles) == 0: - log.debug('Can\'t restatus movie, doesn\'t seem to exist.') - return False + m = db.query(Media).filter_by(id = media_id).first() + if not m or len(m.library.titles) == 0: + log.debug('Can\'t restatus movie, doesn\'t seem to exist.') + return False - log.debug('Changing status for %s', m.library.titles[0].title) - if not m.profile: - m.status_id = done_status.get('id') - else: - move_to_wanted = True + log.debug('Changing status for %s', m.library.titles[0].title) + if not m.profile: + m.status_id = done_status.get('id') + else: + move_to_wanted = True - for t in m.profile.types: - for release in m.releases: - if t.quality.identifier is release.quality.identifier and (release.status_id is done_status.get('id') and t.finish): - move_to_wanted = False + for t in m.profile.types: + for release in m.releases: + if t.quality.identifier is release.quality.identifier and (release.status_id is done_status.get('id') and t.finish): + move_to_wanted = False - m.status_id = active_status.get('id') if move_to_wanted else done_status.get('id') + m.status_id = active_status.get('id') if move_to_wanted else done_status.get('id') - db.commit() - db.expire_all() + db.commit() - return True + return True + except: + log.error('Failed restatus: %s', traceback.format_exc()) + db.rollback() + finally: + db.close() diff --git a/couchpotato/core/media/movie/_base/main.py b/couchpotato/core/media/movie/_base/main.py index cd2158c..a7ecf2d 100644 --- a/couchpotato/core/media/movie/_base/main.py +++ b/couchpotato/core/media/movie/_base/main.py @@ -1,3 +1,4 @@ +import traceback from couchpotato import get_session from couchpotato.api import addApiView from couchpotato.core.event import fireEvent, fireEventAsync, addEvent @@ -70,76 +71,81 @@ class MovieBase(MovieTypeBase): default_profile = fireEvent('profile.default', single = True) cat_id = params.get('category_id') - db = get_session() - m = db.query(Media).filter_by(library_id = library.get('id')).first() - added = True - do_search = False - search_after = search_after and self.conf('search_on_add', section = 'moviesearcher') - if not m: - m = Media( - library_id = library.get('id'), - profile_id = params.get('profile_id', default_profile.get('id')), - status_id = status_id if status_id else status_active.get('id'), - category_id = tryInt(cat_id) if cat_id is not None and tryInt(cat_id) > 0 else None, - ) - db.add(m) - db.commit() + try: + db = get_session() + m = db.query(Media).filter_by(library_id = library.get('id')).first() + added = True + do_search = False + search_after = search_after and self.conf('search_on_add', section = 'moviesearcher') + if not m: + m = Media( + library_id = library.get('id'), + profile_id = params.get('profile_id', default_profile.get('id')), + status_id = status_id if status_id else status_active.get('id'), + category_id = tryInt(cat_id) if cat_id is not None and tryInt(cat_id) > 0 else None, + ) + db.add(m) + db.commit() - onComplete = None - if search_after: - onComplete = self.createOnComplete(m.id) + onComplete = None + if search_after: + onComplete = self.createOnComplete(m.id) - fireEventAsync('library.update.movie', params.get('identifier'), default_title = params.get('title', ''), on_complete = onComplete) - search_after = False - elif force_readd: + fireEventAsync('library.update.movie', params.get('identifier'), default_title = params.get('title', ''), on_complete = onComplete) + search_after = False + elif force_readd: - # Clean snatched history - for release in m.releases: - if release.status_id in [downloaded_status.get('id'), snatched_status.get('id'), done_status.get('id')]: - if params.get('ignore_previous', False): - release.status_id = ignored_status.get('id') - else: - fireEvent('release.delete', release.id, single = True) + # Clean snatched history + for release in m.releases: + if release.status_id in [downloaded_status.get('id'), snatched_status.get('id'), done_status.get('id')]: + if params.get('ignore_previous', False): + release.status_id = ignored_status.get('id') + else: + fireEvent('release.delete', release.id, single = True) - m.profile_id = params.get('profile_id', default_profile.get('id')) - m.category_id = tryInt(cat_id) if cat_id is not None and tryInt(cat_id) > 0 else (m.category_id or None) - else: - log.debug('Movie already exists, not updating: %s', params) - added = False + m.profile_id = params.get('profile_id', default_profile.get('id')) + m.category_id = tryInt(cat_id) if cat_id is not None and tryInt(cat_id) > 0 else (m.category_id or None) + else: + log.debug('Movie already exists, not updating: %s', params) + added = False - if force_readd: - m.status_id = status_id if status_id else status_active.get('id') - m.last_edit = int(time.time()) - do_search = True + if force_readd: + m.status_id = status_id if status_id else status_active.get('id') + m.last_edit = int(time.time()) + do_search = True - db.commit() + db.commit() - # Remove releases - available_status = fireEvent('status.get', 'available', single = True) - for rel in m.releases: - if rel.status_id is available_status.get('id'): - db.delete(rel) - db.commit() + # Remove releases + available_status = fireEvent('status.get', 'available', single = True) + for rel in m.releases: + if rel.status_id is available_status.get('id'): + db.delete(rel) + db.commit() - movie_dict = m.to_dict(self.default_dict) + movie_dict = m.to_dict(self.default_dict) - if do_search and search_after: - onComplete = self.createOnComplete(m.id) - onComplete() + if do_search and search_after: + onComplete = self.createOnComplete(m.id) + onComplete() - if added: - if params.get('title'): - message = 'Successfully added "%s" to your wanted list.' % params.get('title', '') - else: - title = getTitle(m.library) - if title: - message = 'Successfully added "%s" to your wanted list.' % title + if added: + if params.get('title'): + message = 'Successfully added "%s" to your wanted list.' % params.get('title', '') else: - message = 'Succesfully added to your wanted list.' - fireEvent('notify.frontend', type = 'movie.added', data = movie_dict, message = message) + title = getTitle(m.library) + if title: + message = 'Successfully added "%s" to your wanted list.' % title + else: + message = 'Succesfully added to your wanted list.' + fireEvent('notify.frontend', type = 'movie.added', data = movie_dict, message = message) - db.expire_all() - return movie_dict + return movie_dict + except: + log.error('Failed deleting media: %s', traceback.format_exc()) + db.rollback() + finally: + db.close() def addView(self, **kwargs): add_dict = self.add(params = kwargs) @@ -151,42 +157,51 @@ class MovieBase(MovieTypeBase): def edit(self, id = '', **kwargs): - db = get_session() + try: + db = get_session() - available_status = fireEvent('status.get', 'available', single = True) + available_status = fireEvent('status.get', 'available', single = True) - ids = splitString(id) - for media_id in ids: + ids = splitString(id) + for media_id in ids: - m = db.query(Media).filter_by(id = media_id).first() - if not m: - continue + m = db.query(Media).filter_by(id = media_id).first() + if not m: + continue - m.profile_id = kwargs.get('profile_id') + m.profile_id = kwargs.get('profile_id') - cat_id = kwargs.get('category_id') - if cat_id is not None: - m.category_id = tryInt(cat_id) if tryInt(cat_id) > 0 else None + cat_id = kwargs.get('category_id') + if cat_id is not None: + m.category_id = tryInt(cat_id) if tryInt(cat_id) > 0 else None - # Remove releases - for rel in m.releases: - if rel.status_id is available_status.get('id'): - db.delete(rel) - db.commit() + # Remove releases + for rel in m.releases: + if rel.status_id is available_status.get('id'): + db.delete(rel) + db.commit() - # Default title - if kwargs.get('default_title'): - for title in m.library.titles: - title.default = toUnicode(kwargs.get('default_title', '')).lower() == toUnicode(title.title).lower() + # Default title + if kwargs.get('default_title'): + for title in m.library.titles: + title.default = toUnicode(kwargs.get('default_title', '')).lower() == toUnicode(title.title).lower() - db.commit() + db.commit() - fireEvent('media.restatus', m.id) + fireEvent('media.restatus', m.id) - movie_dict = m.to_dict(self.default_dict) - fireEventAsync('movie.searcher.single', movie_dict, on_complete = self.createNotifyFront(media_id)) + movie_dict = m.to_dict(self.default_dict) + fireEventAsync('movie.searcher.single', movie_dict, on_complete = self.createNotifyFront(media_id)) + + return { + 'success': True, + } + except: + log.error('Failed deleting media: %s', traceback.format_exc()) + db.rollback() + finally: + db.close() - db.expire_all() return { - 'success': True, + 'success': False, } diff --git a/couchpotato/core/media/movie/library/movie/main.py b/couchpotato/core/media/movie/library/movie/main.py index 6266ca4..034a8fb 100644 --- a/couchpotato/core/media/movie/library/movie/main.py +++ b/couchpotato/core/media/movie/library/movie/main.py @@ -26,142 +26,163 @@ class MovieLibraryPlugin(LibraryBase): primary_provider = attrs.get('primary_provider', 'imdb') - db = get_session() - - l = db.query(Library).filter_by(identifier = attrs.get('identifier')).first() - if not l: - status = fireEvent('status.get', 'needs_update', single = True) - l = Library( - year = attrs.get('year'), - identifier = attrs.get('identifier'), - plot = toUnicode(attrs.get('plot')), - tagline = toUnicode(attrs.get('tagline')), - status_id = status.get('id'), - info = {} - ) - - title = LibraryTitle( - title = toUnicode(attrs.get('title')), - simple_title = self.simplifyTitle(attrs.get('title')), - ) - - l.titles.append(title) - - db.add(l) - db.commit() - - # Update library info - if update_after is not False: - handle = fireEventAsync if update_after is 'async' else fireEvent - handle('library.update.movie', identifier = l.identifier, default_title = toUnicode(attrs.get('title', ''))) - - library_dict = l.to_dict(self.default_dict) - - db.expire_all() - return library_dict + try: + db = get_session() + + l = db.query(Library).filter_by(identifier = attrs.get('identifier')).first() + if not l: + status = fireEvent('status.get', 'needs_update', single = True) + l = Library( + year = attrs.get('year'), + identifier = attrs.get('identifier'), + plot = toUnicode(attrs.get('plot')), + tagline = toUnicode(attrs.get('tagline')), + status_id = status.get('id'), + info = {} + ) + + title = LibraryTitle( + title = toUnicode(attrs.get('title')), + simple_title = self.simplifyTitle(attrs.get('title')), + ) + + l.titles.append(title) + + db.add(l) + db.commit() + + # Update library info + if update_after is not False: + handle = fireEventAsync if update_after is 'async' else fireEvent + handle('library.update.movie', identifier = l.identifier, default_title = toUnicode(attrs.get('title', ''))) + + library_dict = l.to_dict(self.default_dict) + return library_dict + except: + log.error('Failed adding media: %s', traceback.format_exc()) + db.rollback() + finally: + db.close() + + return {} def update(self, identifier, default_title = '', extended = False): if self.shuttingDown(): return - db = get_session() - library = db.query(Library).filter_by(identifier = identifier).first() - done_status = fireEvent('status.get', 'done', single = True) - - info = fireEvent('movie.info', merge = True, extended = extended, identifier = identifier) - - # Don't need those here - try: del info['in_wanted'] - except: pass - try: del info['in_library'] - except: pass - - if not info or len(info) == 0: - log.error('Could not update, no movie info to work with: %s', identifier) - return False - - # Main info - library.plot = toUnicode(info.get('plot', '')) - library.tagline = toUnicode(info.get('tagline', '')) - library.year = info.get('year', 0) - library.status_id = done_status.get('id') - library.info.update(info) - db.commit() - - # Titles - [db.delete(title) for title in library.titles] - db.commit() - - titles = info.get('titles', []) - log.debug('Adding titles: %s', titles) - counter = 0 - - def_title = None - for title in titles: - if (len(default_title) == 0 and counter == 0) or len(titles) == 1 or title.lower() == toUnicode(default_title.lower()) or (toUnicode(default_title) == six.u('') and toUnicode(titles[0]) == title): - def_title = toUnicode(title) - break - counter += 1 - - #if not def_title: - # def_title = toUnicode(titles[0]) - - for title in titles: - if not title: - continue - title = toUnicode(title) - t = LibraryTitle( - title = title, - simple_title = self.simplifyTitle(title), - default = title == def_title - ) - library.titles.append(t) - - db.commit() - - # Files - images = info.get('images', []) - for image_type in ['poster']: - for image in images.get(image_type, []): - if not isinstance(image, (str, unicode)): - continue + try: + db = get_session() - file_path = fireEvent('file.download', url = image, single = True) - if file_path: - file_obj = fireEvent('file.add', path = file_path, type_tuple = ('image', image_type), single = True) - try: - file_obj = db.query(File).filter_by(id = file_obj.get('id')).one() - library.files.append(file_obj) - db.commit() + library = db.query(Library).filter_by(identifier = identifier).first() + done_status = fireEvent('status.get', 'done', single = True) - break - except: - log.debug('Failed to attach to library: %s', traceback.format_exc()) + info = fireEvent('movie.info', merge = True, extended = extended, identifier = identifier) - library_dict = library.to_dict(self.default_dict) + # Don't need those here + try: del info['in_wanted'] + except: pass + try: del info['in_library'] + except: pass - db.expire_all() - return library_dict + if not info or len(info) == 0: + log.error('Could not update, no movie info to work with: %s', identifier) + return False - def updateReleaseDate(self, identifier): + # Main info + library.plot = toUnicode(info.get('plot', '')) + library.tagline = toUnicode(info.get('tagline', '')) + library.year = info.get('year', 0) + library.status_id = done_status.get('id') + library.info.update(info) + db.commit() - db = get_session() - library = db.query(Library).filter_by(identifier = identifier).first() + # Titles + [db.delete(title) for title in library.titles] + db.commit() + + titles = info.get('titles', []) + log.debug('Adding titles: %s', titles) + counter = 0 + + def_title = None + for title in titles: + if (len(default_title) == 0 and counter == 0) or len(titles) == 1 or title.lower() == toUnicode(default_title.lower()) or (toUnicode(default_title) == six.u('') and toUnicode(titles[0]) == title): + def_title = toUnicode(title) + break + counter += 1 + + if not def_title: + def_title = toUnicode(titles[0]) - if not library.info: - library_dict = self.update(identifier) - dates = library_dict.get('info', {}).get('release_date') - else: - dates = library.info.get('release_date') + for title in titles: + if not title: + continue + title = toUnicode(title) + t = LibraryTitle( + title = title, + simple_title = self.simplifyTitle(title), + default = title == def_title + ) + library.titles.append(t) - if dates and (dates.get('expires', 0) < time.time() or dates.get('expires', 0) > time.time() + (604800 * 4)) or not dates: - dates = fireEvent('movie.release_date', identifier = identifier, merge = True) - library.info.update({'release_date': dates}) db.commit() - db.expire_all() - return dates + # Files + images = info.get('images', []) + for image_type in ['poster']: + for image in images.get(image_type, []): + if not isinstance(image, (str, unicode)): + continue + + file_path = fireEvent('file.download', url = image, single = True) + if file_path: + file_obj = fireEvent('file.add', path = file_path, type_tuple = ('image', image_type), single = True) + try: + file_obj = db.query(File).filter_by(id = file_obj.get('id')).one() + library.files.append(file_obj) + db.commit() + + break + except: + log.debug('Failed to attach to library: %s', traceback.format_exc()) + db.rollback() + + library_dict = library.to_dict(self.default_dict) + return library_dict + except: + log.error('Failed update media: %s', traceback.format_exc()) + db.rollback() + finally: + db.close() + + return {} + + def updateReleaseDate(self, identifier): + + try: + db = get_session() + library = db.query(Library).filter_by(identifier = identifier).first() + + if not library.info: + library_dict = self.update(identifier) + dates = library_dict.get('info', {}).get('release_date') + else: + dates = library.info.get('release_date') + + if dates and (dates.get('expires', 0) < time.time() or dates.get('expires', 0) > time.time() + (604800 * 4)) or not dates: + dates = fireEvent('movie.release_date', identifier = identifier, merge = True) + library.info.update({'release_date': dates}) + db.commit() + + return dates + except: + log.error('Failed updating release dates: %s', traceback.format_exc()) + db.rollback() + finally: + db.close() + + return {} def simplifyTitle(self, title): diff --git a/couchpotato/core/media/movie/searcher/main.py b/couchpotato/core/media/movie/searcher/main.py index 0daf1b4..7ae76a4 100644 --- a/couchpotato/core/media/movie/searcher/main.py +++ b/couchpotato/core/media/movie/searcher/main.py @@ -89,8 +89,6 @@ class MovieSearcher(SearcherBase, MovieTypeBase): 'files': {}, })) - db.expire_all() - self.in_progress = { 'total': len(movies), 'to_go': len(movies), @@ -209,7 +207,6 @@ class MovieSearcher(SearcherBase, MovieTypeBase): fireEvent('notify.frontend', type = 'movie.searcher.ended', data = {'id': movie['id']}) - db.expire_all() return ret def correctRelease(self, nzb = None, media = None, quality = None, **kwargs): @@ -342,7 +339,6 @@ class MovieSearcher(SearcherBase, MovieTypeBase): for rel in rels: rel.status_id = ignored_status.get('id') db.commit() - db.expire_all() movie_dict = fireEvent('media.get', media_id = media_id, single = True) log.info('Trying next release for: %s', getTitle(movie_dict['library'])) @@ -352,7 +348,10 @@ class MovieSearcher(SearcherBase, MovieTypeBase): except: log.error('Failed searching for next release: %s', traceback.format_exc()) + db.rollback() return False + finally: + db.close() def getSearchTitle(self, media): if media['type'] == 'movie': diff --git a/couchpotato/core/media/movie/suggestion/main.py b/couchpotato/core/media/movie/suggestion/main.py index 02fd27f..22e23fe 100644 --- a/couchpotato/core/media/movie/suggestion/main.py +++ b/couchpotato/core/media/movie/suggestion/main.py @@ -33,7 +33,6 @@ class Suggestion(Plugin): .options(joinedload_all('library')) \ .filter(or_(*[Media.status.has(identifier = s) for s in ['active', 'done']])).all() movies = [x.library.identifier for x in active_movies] - db.expire_all() if not ignored or len(ignored) == 0: ignored = splitString(Env.prop('suggest_ignore', default = '')) @@ -98,7 +97,6 @@ class Suggestion(Plugin): .filter(Media.status_id.in_([active_status.get('id'), done_status.get('id')])).all() movies = [x[0] for x in active_movies] movies.extend(seen) - db.expire_all() ignored.extend([x.get('imdb') for x in cached_suggestion]) suggestions = fireEvent('movie.suggest', movies = movies, ignore = removeDuplicate(ignored), single = True) diff --git a/couchpotato/core/notifications/core/main.py b/couchpotato/core/notifications/core/main.py index 02545ea..93f94d6 100644 --- a/couchpotato/core/notifications/core/main.py +++ b/couchpotato/core/notifications/core/main.py @@ -67,27 +67,42 @@ class CoreNotifier(Notification): def clean(self): - db = get_session() - db.query(Notif).filter(Notif.added <= (int(time.time()) - 2419200)).delete() - db.commit() + try: + db = get_session() + db.query(Notif).filter(Notif.added <= (int(time.time()) - 2419200)).delete() + db.commit() + except: + log.error('Failed cleaning notification: %s', traceback.format_exc()) + db.rollback() + finally: + db.close() def markAsRead(self, ids = None, **kwargs): ids = splitString(ids) if ids else None - db = get_session() + try: + db = get_session() - if ids: - q = db.query(Notif).filter(or_(*[Notif.id == tryInt(s) for s in ids])) - else: - q = db.query(Notif).filter_by(read = False) + if ids: + q = db.query(Notif).filter(or_(*[Notif.id == tryInt(s) for s in ids])) + else: + q = db.query(Notif).filter_by(read = False) - q.update({Notif.read: True}) + q.update({Notif.read: True}) + db.commit() - db.commit() + return { + 'success': True + } + except: + log.error('Failed mark as read: %s', traceback.format_exc()) + db.rollback() + finally: + db.close() return { - 'success': True + 'success': False } def listView(self, limit_offset = None, **kwargs): @@ -139,24 +154,30 @@ class CoreNotifier(Notification): def notify(self, message = '', data = None, listener = None): if not data: data = {} - db = get_session() + try: + db = get_session() - data['notification_type'] = listener if listener else 'unknown' + data['notification_type'] = listener if listener else 'unknown' - n = Notif( - message = toUnicode(message), - data = data - ) - db.add(n) - db.commit() + n = Notif( + message = toUnicode(message), + data = data + ) + db.add(n) + db.commit() - ndict = n.to_dict() - ndict['type'] = 'notification' - ndict['time'] = time.time() + ndict = n.to_dict() + ndict['type'] = 'notification' + ndict['time'] = time.time() - self.frontend(type = listener, data = data) + self.frontend(type = listener, data = data) - return True + return True + except: + log.error('Failed notify: %s', traceback.format_exc()) + db.rollback() + finally: + db.close() def frontend(self, type = 'notification', data = None, message = None): if not data: data = {} diff --git a/couchpotato/core/plugins/category/main.py b/couchpotato/core/plugins/category/main.py index 6ac9127..c7abaee 100644 --- a/couchpotato/core/plugins/category/main.py +++ b/couchpotato/core/plugins/category/main.py @@ -1,3 +1,4 @@ +import traceback from couchpotato import get_session from couchpotato.api import addApiView from couchpotato.core.event import addEvent @@ -41,83 +42,116 @@ class CategoryPlugin(Plugin): for category in categories: temp.append(category.to_dict()) - db.expire_all() return temp def save(self, **kwargs): - db = get_session() + try: + db = get_session() - c = db.query(Category).filter_by(id = kwargs.get('id')).first() - if not c: - c = Category() - db.add(c) + c = db.query(Category).filter_by(id = kwargs.get('id')).first() + if not c: + c = Category() + db.add(c) - c.order = kwargs.get('order', c.order if c.order else 0) - c.label = toUnicode(kwargs.get('label', '')) - c.ignored = toUnicode(kwargs.get('ignored', '')) - c.preferred = toUnicode(kwargs.get('preferred', '')) - c.required = toUnicode(kwargs.get('required', '')) - c.destination = toUnicode(kwargs.get('destination', '')) + c.order = kwargs.get('order', c.order if c.order else 0) + c.label = toUnicode(kwargs.get('label', '')) + c.ignored = toUnicode(kwargs.get('ignored', '')) + c.preferred = toUnicode(kwargs.get('preferred', '')) + c.required = toUnicode(kwargs.get('required', '')) + c.destination = toUnicode(kwargs.get('destination', '')) - db.commit() + db.commit() - category_dict = c.to_dict() + category_dict = c.to_dict() + + return { + 'success': True, + 'category': category_dict + } + except: + log.error('Failed: %s', traceback.format_exc()) + db.rollback() + finally: + db.close() return { - 'success': True, - 'category': category_dict + 'success': False, + 'category': None } def saveOrder(self, **kwargs): - db = get_session() + try: + db = get_session() - order = 0 - for category_id in kwargs.get('ids', []): - c = db.query(Category).filter_by(id = category_id).first() - c.order = order + order = 0 + for category_id in kwargs.get('ids', []): + c = db.query(Category).filter_by(id = category_id).first() + c.order = order - order += 1 + order += 1 - db.commit() + db.commit() + + return { + 'success': True + } + except: + log.error('Failed: %s', traceback.format_exc()) + db.rollback() + finally: + db.close() return { - 'success': True + 'success': False } def delete(self, id = None, **kwargs): - db = get_session() - - success = False - message = '' try: - c = db.query(Category).filter_by(id = id).first() - db.delete(c) - db.commit() + db = get_session() + + success = False + message = '' + try: + c = db.query(Category).filter_by(id = id).first() + db.delete(c) + db.commit() + + # Force defaults on all empty category movies + self.removeFromMovie(id) - # Force defaults on all empty category movies - self.removeFromMovie(id) + success = True + except Exception as e: + message = log.error('Failed deleting category: %s', e) - success = True - except Exception as e: - message = log.error('Failed deleting category: %s', e) + return { + 'success': success, + 'message': message + } + except: + log.error('Failed: %s', traceback.format_exc()) + db.rollback() + finally: + db.close() - db.expire_all() return { - 'success': success, - 'message': message + 'success': False } def removeFromMovie(self, category_id): - db = get_session() - movies = db.query(Media).filter(Media.category_id == category_id).all() - - if len(movies) > 0: - for movie in movies: - movie.category_id = None - db.commit() - - db.expire_all() + try: + db = get_session() + movies = db.query(Media).filter(Media.category_id == category_id).all() + + if len(movies) > 0: + for movie in movies: + movie.category_id = None + db.commit() + except: + log.error('Failed: %s', traceback.format_exc()) + db.rollback() + finally: + db.close() diff --git a/couchpotato/core/plugins/dashboard/main.py b/couchpotato/core/plugins/dashboard/main.py index 2c5939d..949d8f5 100644 --- a/couchpotato/core/plugins/dashboard/main.py +++ b/couchpotato/core/plugins/dashboard/main.py @@ -119,7 +119,6 @@ class Dashboard(Plugin): 'files': {}, })) - db.expire_all() return { 'success': True, 'empty': len(movies) == 0, diff --git a/couchpotato/core/plugins/file/main.py b/couchpotato/core/plugins/file/main.py index 806af16..c52a980 100644 --- a/couchpotato/core/plugins/file/main.py +++ b/couchpotato/core/plugins/file/main.py @@ -66,7 +66,6 @@ class FileManager(Plugin): time.sleep(3) log.debug('Cleaning up unused files') - python_cache = Env.get('cache')._path try: db = get_session() for root, dirs, walk_files in os.walk(Env.get('cache_dir')): @@ -78,6 +77,9 @@ class FileManager(Plugin): os.remove(file_path) except: log.error('Failed removing unused file: %s', traceback.format_exc()) + db.rollback() + finally: + db.close() def showCacheFile(self, route, **kwargs): Env.get('app').add_handlers(".*$", [('%s%s' % (Env.get('api_base'), route), StaticFileHandler, {'path': Env.get('cache_dir')})]) @@ -103,42 +105,56 @@ class FileManager(Plugin): def add(self, path = '', part = 1, type_tuple = (), available = 1, properties = None): if not properties: properties = {} - type_id = self.getType(type_tuple).get('id') - db = get_session() + try: + db = get_session() + type_id = self.getType(type_tuple).get('id') - f = db.query(File).filter(File.path == toUnicode(path)).first() - if not f: - f = File() - db.add(f) + f = db.query(File).filter(File.path == toUnicode(path)).first() + if not f: + f = File() + db.add(f) - f.path = toUnicode(path) - f.part = part - f.available = available - f.type_id = type_id + f.path = toUnicode(path) + f.part = part + f.available = available + f.type_id = type_id - db.commit() + db.commit() - file_dict = f.to_dict() + file_dict = f.to_dict() - return file_dict + return file_dict + except: + log.error('Failed adding file: %s, %s', (path, traceback.format_exc())) + db.rollback() + finally: + db.close() def getType(self, type_tuple): - db = get_session() - type_type, type_identifier = type_tuple - - ft = db.query(FileType).filter_by(identifier = type_identifier).first() - if not ft: - ft = FileType( - type = toUnicode(type_type), - identifier = type_identifier, - name = toUnicode(type_identifier[0].capitalize() + type_identifier[1:]) - ) - db.add(ft) - db.commit() + try: + db = get_session() + type_type, type_identifier = type_tuple + + ft = db.query(FileType).filter_by(identifier = type_identifier).first() + if not ft: + ft = FileType( + type = toUnicode(type_type), + identifier = type_identifier, + name = toUnicode(type_identifier[0].capitalize() + type_identifier[1:]) + ) + db.add(ft) + db.commit() + + type_dict = ft.to_dict() + + return type_dict + except: + log.error('Failed getting type: %s, %s', (type_tuple, traceback.format_exc())) + db.rollback() + finally: + db.close() - type_dict = ft.to_dict() - return type_dict def getTypes(self): diff --git a/couchpotato/core/plugins/profile/main.py b/couchpotato/core/plugins/profile/main.py index 3132185..914d46f 100644 --- a/couchpotato/core/plugins/profile/main.py +++ b/couchpotato/core/plugins/profile/main.py @@ -1,3 +1,4 @@ +import traceback from couchpotato import get_session from couchpotato.api import addApiView from couchpotato.core.event import addEvent, fireEvent @@ -37,16 +38,20 @@ class ProfilePlugin(Plugin): # Get all active movies without profile active_status = fireEvent('status.get', 'active', single = True) - db = get_session() - movies = db.query(Media).filter(Media.status_id == active_status.get('id'), Media.profile == None).all() - - if len(movies) > 0: - default_profile = self.default() - for movie in movies: - movie.profile_id = default_profile.get('id') - db.commit() - - db.expire_all() + try: + db = get_session() + movies = db.query(Media).filter(Media.status_id == active_status.get('id'), Media.profile == None).all() + + if len(movies) > 0: + default_profile = self.default() + for movie in movies: + movie.profile_id = default_profile.get('id') + db.commit() + except: + log.error('Failed: %s', traceback.format_exc()) + db.rollback() + finally: + db.close() def allView(self, **kwargs): @@ -66,44 +71,53 @@ class ProfilePlugin(Plugin): for profile in profiles: temp.append(profile.to_dict(self.to_dict)) - db.expire_all() return temp def save(self, **kwargs): - db = get_session() - - p = db.query(Profile).filter_by(id = kwargs.get('id')).first() - if not p: - p = Profile() - db.add(p) - - p.label = toUnicode(kwargs.get('label')) - p.order = kwargs.get('order', p.order if p.order else 0) - p.core = kwargs.get('core', False) - - #delete old types - [db.delete(t) for t in p.types] + try: + db = get_session() + + p = db.query(Profile).filter_by(id = kwargs.get('id')).first() + if not p: + p = Profile() + db.add(p) + + p.label = toUnicode(kwargs.get('label')) + p.order = kwargs.get('order', p.order if p.order else 0) + p.core = kwargs.get('core', False) + + #delete old types + [db.delete(t) for t in p.types] + + order = 0 + for type in kwargs.get('types', []): + t = ProfileType( + order = order, + finish = type.get('finish') if order > 0 else 1, + wait_for = kwargs.get('wait_for'), + quality_id = type.get('quality_id') + ) + p.types.append(t) - order = 0 - for type in kwargs.get('types', []): - t = ProfileType( - order = order, - finish = type.get('finish') if order > 0 else 1, - wait_for = kwargs.get('wait_for'), - quality_id = type.get('quality_id') - ) - p.types.append(t) + order += 1 - order += 1 + db.commit() - db.commit() + profile_dict = p.to_dict(self.to_dict) - profile_dict = p.to_dict(self.to_dict) + return { + 'success': True, + 'profile': profile_dict + } + except: + log.error('Failed: %s', traceback.format_exc()) + db.rollback() + finally: + db.close() return { - 'success': True, - 'profile': profile_dict + 'success': False } def default(self): @@ -114,93 +128,119 @@ class ProfilePlugin(Plugin): .first() default_dict = default.to_dict(self.to_dict) - db.expire_all() return default_dict def saveOrder(self, **kwargs): - db = get_session() + try: + db = get_session() - order = 0 - for profile in kwargs.get('ids', []): - p = db.query(Profile).filter_by(id = profile).first() - p.hide = kwargs.get('hidden')[order] - p.order = order + order = 0 + for profile in kwargs.get('ids', []): + p = db.query(Profile).filter_by(id = profile).first() + p.hide = kwargs.get('hidden')[order] + p.order = order - order += 1 + order += 1 - db.commit() + db.commit() + + return { + 'success': True + } + except: + log.error('Failed: %s', traceback.format_exc()) + db.rollback() + finally: + db.close() return { - 'success': True + 'success': False } def delete(self, id = None, **kwargs): - db = get_session() - - success = False - message = '' try: - p = db.query(Profile).filter_by(id = id).first() + db = get_session() - db.delete(p) - db.commit() + success = False + message = '' + try: + p = db.query(Profile).filter_by(id = id).first() + + db.delete(p) + db.commit() + + # Force defaults on all empty profile movies + self.forceDefaults() - # Force defaults on all empty profile movies - self.forceDefaults() + success = True + except Exception as e: + message = log.error('Failed deleting Profile: %s', e) - success = True - except Exception as e: - message = log.error('Failed deleting Profile: %s', e) + return { + 'success': success, + 'message': message + } + except: + log.error('Failed: %s', traceback.format_exc()) + db.rollback() + finally: + db.close() - db.expire_all() return { - 'success': success, - 'message': message + 'success': False } def fill(self): - db = get_session() - - profiles = [{ - 'label': 'Best', - 'qualities': ['720p', '1080p', 'brrip', 'dvdrip'] - }, { - 'label': 'HD', - 'qualities': ['720p', '1080p'] - }, { - 'label': 'SD', - 'qualities': ['dvdrip', 'dvdr'] - }] - - # Create default quality profile - order = -2 - for profile in profiles: - log.info('Creating default profile: %s', profile.get('label')) - p = Profile( - label = toUnicode(profile.get('label')), - order = order - ) - db.add(p) - - quality_order = 0 - for quality in profile.get('qualities'): - quality = fireEvent('quality.single', identifier = quality, single = True) - profile_type = ProfileType( - quality_id = quality.get('id'), - profile = p, - finish = True, - wait_for = 0, - order = quality_order + try: + db = get_session() + + profiles = [{ + 'label': 'Best', + 'qualities': ['720p', '1080p', 'brrip', 'dvdrip'] + }, { + 'label': 'HD', + 'qualities': ['720p', '1080p'] + }, { + 'label': 'SD', + 'qualities': ['dvdrip', 'dvdr'] + }] + + # Create default quality profile + order = -2 + for profile in profiles: + log.info('Creating default profile: %s', profile.get('label')) + p = Profile( + label = toUnicode(profile.get('label')), + order = order ) - p.types.append(profile_type) + db.add(p) - quality_order += 1 + quality_order = 0 + for quality in profile.get('qualities'): + quality = fireEvent('quality.single', identifier = quality, single = True) + profile_type = ProfileType( + quality_id = quality.get('id'), + profile = p, + finish = True, + wait_for = 0, + order = quality_order + ) + p.types.append(profile_type) - order += 1 + quality_order += 1 + + order += 1 + + db.commit() - db.commit() + return True + except: + log.error('Failed: %s', traceback.format_exc()) + db.rollback() + finally: + db.close() - return True + return False diff --git a/couchpotato/core/plugins/quality/main.py b/couchpotato/core/plugins/quality/main.py index a49c17e..d56ff89 100644 --- a/couchpotato/core/plugins/quality/main.py +++ b/couchpotato/core/plugins/quality/main.py @@ -1,3 +1,4 @@ +import traceback from couchpotato import get_session from couchpotato.api import addApiView from couchpotato.core.event import addEvent @@ -98,70 +99,88 @@ class QualityPlugin(Plugin): def saveSize(self, **kwargs): - db = get_session() - quality = db.query(Quality).filter_by(identifier = kwargs.get('identifier')).first() + try: + db = get_session() + quality = db.query(Quality).filter_by(identifier = kwargs.get('identifier')).first() - if quality: - setattr(quality, kwargs.get('value_type'), kwargs.get('value')) - db.commit() + if quality: + setattr(quality, kwargs.get('value_type'), kwargs.get('value')) + db.commit() + + self.cached_qualities = None - self.cached_qualities = None + return { + 'success': True + } + except: + log.error('Failed: %s', traceback.format_exc()) + db.rollback() + finally: + db.close() return { - 'success': True + 'success': False } def fill(self): - db = get_session() + try: + db = get_session() - order = 0 - for q in self.qualities: + order = 0 + for q in self.qualities: + + # Create quality + qual = db.query(Quality).filter_by(identifier = q.get('identifier')).first() + + if not qual: + log.info('Creating quality: %s', q.get('label')) + qual = Quality() + qual.order = order + qual.identifier = q.get('identifier') + qual.label = toUnicode(q.get('label')) + qual.size_min, qual.size_max = q.get('size') + + db.add(qual) + + # Create single quality profile + prof = db.query(Profile).filter( + Profile.core == True + ).filter( + Profile.types.any(quality = qual) + ).all() + + if not prof: + log.info('Creating profile: %s', q.get('label')) + prof = Profile( + core = True, + label = toUnicode(qual.label), + order = order + ) + db.add(prof) + + profile_type = ProfileType( + quality = qual, + profile = prof, + finish = True, + order = 0 + ) + prof.types.append(profile_type) + + order += 1 + + db.commit() + + time.sleep(0.3) # Wait a moment + + return True + except: + log.error('Failed: %s', traceback.format_exc()) + db.rollback() + finally: + db.close() - # Create quality - qual = db.query(Quality).filter_by(identifier = q.get('identifier')).first() - - if not qual: - log.info('Creating quality: %s', q.get('label')) - qual = Quality() - qual.order = order - qual.identifier = q.get('identifier') - qual.label = toUnicode(q.get('label')) - qual.size_min, qual.size_max = q.get('size') - - db.add(qual) - - # Create single quality profile - prof = db.query(Profile).filter( - Profile.core == True - ).filter( - Profile.types.any(quality = qual) - ).all() - - if not prof: - log.info('Creating profile: %s', q.get('label')) - prof = Profile( - core = True, - label = toUnicode(qual.label), - order = order - ) - db.add(prof) - - profile_type = ProfileType( - quality = qual, - profile = prof, - finish = True, - order = 0 - ) - prof.types.append(profile_type) - - order += 1 - - db.commit() - - time.sleep(0.3) # Wait a moment - - return True + return False def guess(self, files, extra = None): if not extra: extra = {} diff --git a/couchpotato/core/plugins/release/main.py b/couchpotato/core/plugins/release/main.py index 4726dbf..a478b64 100644 --- a/couchpotato/core/plugins/release/main.py +++ b/couchpotato/core/plugins/release/main.py @@ -88,63 +88,69 @@ class Release(Plugin): elif rel.status_id in [snatched_status.get('id'), downloaded_status.get('id')]: self.updateStatus(id = rel.id, status = ignored_status) - db.expire_all() def add(self, group): - db = get_session() - - identifier = '%s.%s.%s' % (group['library']['identifier'], group['meta_data'].get('audio', 'unknown'), group['meta_data']['quality']['identifier']) - - done_status, snatched_status = fireEvent('status.get', ['done', 'snatched'], single = True) - - # Add movie - media = db.query(Media).filter_by(library_id = group['library'].get('id')).first() - if not media: - media = Media( - library_id = group['library'].get('id'), - profile_id = 0, - status_id = done_status.get('id') - ) - db.add(media) - db.commit() - - # Add Release - rel = db.query(Relea).filter( - or_( - Relea.identifier == identifier, - and_(Relea.identifier.startswith(group['library']['identifier']), Relea.status_id == snatched_status.get('id')) - ) - ).first() - if not rel: - rel = Relea( - identifier = identifier, - movie = media, - quality_id = group['meta_data']['quality'].get('id'), - status_id = done_status.get('id') - ) - db.add(rel) - db.commit() - - # Add each file type - added_files = [] - for type in group['files']: - for cur_file in group['files'][type]: - added_file = self.saveFile(cur_file, type = type, include_media_info = type is 'movie') - added_files.append(added_file.get('id')) - - # Add the release files in batch try: - added_files = db.query(File).filter(or_(*[File.id == x for x in added_files])).all() - rel.files.extend(added_files) - db.commit() - except: - log.debug('Failed to attach "%s" to release: %s', (added_files, traceback.format_exc())) + db = get_session() - fireEvent('media.restatus', media.id) + identifier = '%s.%s.%s' % (group['library']['identifier'], group['meta_data'].get('audio', 'unknown'), group['meta_data']['quality']['identifier']) - db.expire_all() - return True + done_status, snatched_status = fireEvent('status.get', ['done', 'snatched'], single = True) + + # Add movie + media = db.query(Media).filter_by(library_id = group['library'].get('id')).first() + if not media: + media = Media( + library_id = group['library'].get('id'), + profile_id = 0, + status_id = done_status.get('id') + ) + db.add(media) + db.commit() + + # Add Release + rel = db.query(Relea).filter( + or_( + Relea.identifier == identifier, + and_(Relea.identifier.startswith(group['library']['identifier']), Relea.status_id == snatched_status.get('id')) + ) + ).first() + if not rel: + rel = Relea( + identifier = identifier, + movie = media, + quality_id = group['meta_data']['quality'].get('id'), + status_id = done_status.get('id') + ) + db.add(rel) + db.commit() + + # Add each file type + added_files = [] + for type in group['files']: + for cur_file in group['files'][type]: + added_file = self.saveFile(cur_file, type = type, include_media_info = type is 'movie') + added_files.append(added_file.get('id')) + + # Add the release files in batch + try: + added_files = db.query(File).filter(or_(*[File.id == x for x in added_files])).all() + rel.files.extend(added_files) + db.commit() + except: + log.debug('Failed to attach "%s" to release: %s', (added_files, traceback.format_exc())) + + fireEvent('media.restatus', media.id) + + return True + except: + log.error('Failed: %s', traceback.format_exc()) + db.rollback() + finally: + db.close() + + return False def saveFile(self, filepath, type = 'unknown', include_media_info = False): @@ -165,31 +171,43 @@ class Release(Plugin): def delete(self, id): - db = get_session() + try: + db = get_session() - rel = db.query(Relea).filter_by(id = id).first() - if rel: - rel.delete() - db.commit() - return True + rel = db.query(Relea).filter_by(id = id).first() + if rel: + rel.delete() + db.commit() + return True + except: + log.error('Failed: %s', traceback.format_exc()) + db.rollback() + finally: + db.close() return False def clean(self, id): - db = get_session() + try: + db = get_session() - rel = db.query(Relea).filter_by(id = id).first() - if rel: - for release_file in rel.files: - if not os.path.isfile(ss(release_file.path)): - db.delete(release_file) - db.commit() + rel = db.query(Relea).filter_by(id = id).first() + if rel: + for release_file in rel.files: + if not os.path.isfile(ss(release_file.path)): + db.delete(release_file) + db.commit() - if len(rel.files) == 0: - self.delete(id) + if len(rel.files) == 0: + self.delete(id) - return True + return True + except: + log.error('Failed: %s', traceback.format_exc()) + db.rollback() + finally: + db.close() return False @@ -338,9 +356,10 @@ class Release(Plugin): except: log.error('Failed storing download status: %s', traceback.format_exc()) + db.rollback() return False finally: - db.expire_all() + db.close() return True @@ -371,49 +390,58 @@ class Release(Plugin): def createFromSearch(self, search_results, media, quality_type): available_status = fireEvent('status.get', ['available'], single = True) - db = get_session() - found_releases = [] + try: + db = get_session() - for rel in search_results: + found_releases = [] - rel_identifier = md5(rel['url']) - found_releases.append(rel_identifier) + for rel in search_results: - rls = db.query(Relea).filter_by(identifier = rel_identifier).first() - if not rls: - rls = Relea( - identifier = rel_identifier, - movie_id = media.get('id'), - #media_id = media.get('id'), - quality_id = quality_type.get('quality_id'), - status_id = available_status.get('id') - ) - db.add(rls) - else: - [db.delete(old_info) for old_info in rls.info] - rls.last_edit = int(time.time()) + rel_identifier = md5(rel['url']) + found_releases.append(rel_identifier) - db.commit() + rls = db.query(Relea).filter_by(identifier = rel_identifier).first() + if not rls: + rls = Relea( + identifier = rel_identifier, + movie_id = media.get('id'), + #media_id = media.get('id'), + quality_id = quality_type.get('quality_id'), + status_id = available_status.get('id') + ) + db.add(rls) + else: + [db.delete(old_info) for old_info in rls.info] + rls.last_edit = int(time.time()) - for info in rel: - try: - if not isinstance(rel[info], (str, unicode, int, long, float)): - continue + db.commit() - rls_info = ReleaseInfo( - identifier = info, - value = toUnicode(rel[info]) - ) - rls.info.append(rls_info) - except InterfaceError: - log.debug('Couldn\'t add %s to ReleaseInfo: %s', (info, traceback.format_exc())) + for info in rel: + try: + if not isinstance(rel[info], (str, unicode, int, long, float)): + continue - db.commit() + rls_info = ReleaseInfo( + identifier = info, + value = toUnicode(rel[info]) + ) + rls.info.append(rls_info) + except InterfaceError: + log.debug('Couldn\'t add %s to ReleaseInfo: %s', (info, traceback.format_exc())) - rel['status_id'] = rls.status_id + db.commit() - return found_releases + rel['status_id'] = rls.status_id + + return found_releases + except: + log.error('Failed: %s', traceback.format_exc()) + db.rollback() + finally: + db.close() + + return [] def forMovie(self, id = None): @@ -442,32 +470,39 @@ class Release(Plugin): def updateStatus(self, id, status = None): if not status: return False - db = get_session() + try: + db = get_session() - rel = db.query(Relea).filter_by(id = id).first() - if rel and status and rel.status_id != status.get('id'): - - item = {} - for info in rel.info: - item[info.identifier] = info.value - - release_name = None - if rel.files: - for file_item in rel.files: - if file_item.type.identifier == 'movie': - release_name = os.path.basename(file_item.path) - break - else: - release_name = item['name'] + rel = db.query(Relea).filter_by(id = id).first() + if rel and status and rel.status_id != status.get('id'): + + item = {} + for info in rel.info: + item[info.identifier] = info.value + + release_name = None + if rel.files: + for file_item in rel.files: + if file_item.type.identifier == 'movie': + release_name = os.path.basename(file_item.path) + break + else: + release_name = item['name'] + + #update status in Db + log.debug('Marking release %s as %s', (release_name, status.get("label"))) + rel.status_id = status.get('id') + rel.last_edit = int(time.time()) + db.commit() - #update status in Db - log.debug('Marking release %s as %s', (release_name, status.get("label"))) - rel.status_id = status.get('id') - rel.last_edit = int(time.time()) - db.commit() + #Update all movie info as there is no release update function + fireEvent('notify.frontend', type = 'release.update_status', data = rel.to_dict()) - #Update all movie info as there is no release update function - fireEvent('notify.frontend', type = 'release.update_status', data = rel.to_dict()) + return True + except: + log.error('Failed: %s', traceback.format_exc()) + db.rollback() + finally: + db.close() - db.expire_all() - return True + return False diff --git a/couchpotato/core/plugins/renamer/main.py b/couchpotato/core/plugins/renamer/main.py index f9f44d8..f86beba 100755 --- a/couchpotato/core/plugins/renamer/main.py +++ b/couchpotato/core/plugins/renamer/main.py @@ -439,6 +439,7 @@ class Renamer(Plugin): db.commit() except Exception as e: log.error('Failed marking movie finished: %s %s', (e, traceback.format_exc())) + db.rollback() # Go over current movie releases for release in movie.releases: diff --git a/couchpotato/core/plugins/scanner/main.py b/couchpotato/core/plugins/scanner/main.py index 16c9e1d..daff091 100644 --- a/couchpotato/core/plugins/scanner/main.py +++ b/couchpotato/core/plugins/scanner/main.py @@ -597,6 +597,7 @@ class Scanner(Plugin): # Check if path is already in db if not imdb_id: + db = get_session() for cf in files['movie']: f = db.query(File).filter_by(path = toUnicode(cf)).first() @@ -607,7 +608,6 @@ class Scanner(Plugin): break except: pass - db.expire_all() # Search based on identifiers if not imdb_id: diff --git a/couchpotato/core/plugins/status/main.py b/couchpotato/core/plugins/status/main.py index 3ec2b45..08f4698 100644 --- a/couchpotato/core/plugins/status/main.py +++ b/couchpotato/core/plugins/status/main.py @@ -1,3 +1,4 @@ +import traceback from couchpotato import get_session from couchpotato.api import addApiView from couchpotato.core.event import addEvent @@ -79,47 +80,57 @@ class StatusPlugin(Plugin): if not isinstance(identifiers, list): identifiers = [identifiers] - db = get_session() - return_list = [] + try: + db = get_session() + return_list = [] - for identifier in identifiers: + for identifier in identifiers: - if self.status_cached.get(identifier): - return_list.append(self.status_cached.get(identifier)) - continue + if self.status_cached.get(identifier): + return_list.append(self.status_cached.get(identifier)) + continue - s = db.query(Status).filter_by(identifier = identifier).first() - if not s: - s = Status( - identifier = identifier, - label = toUnicode(identifier.capitalize()) - ) - db.add(s) - db.commit() + s = db.query(Status).filter_by(identifier = identifier).first() + if not s: + s = Status( + identifier = identifier, + label = toUnicode(identifier.capitalize()) + ) + db.add(s) + db.commit() - status_dict = s.to_dict() + status_dict = s.to_dict() - self.status_cached[identifier] = status_dict - return_list.append(status_dict) + self.status_cached[identifier] = status_dict + return_list.append(status_dict) - return return_list if len(identifiers) > 1 else return_list[0] + return return_list if len(identifiers) > 1 else return_list[0] + except: + log.error('Failed: %s', traceback.format_exc()) + db.rollback() + finally: + db.close() def fill(self): - db = get_session() - - for identifier, label in self.statuses.items(): - s = db.query(Status).filter_by(identifier = identifier).first() - if not s: - log.info('Creating status: %s', label) - s = Status( - identifier = identifier, - label = toUnicode(label) - ) - db.add(s) + try: + db = get_session() - s.label = toUnicode(label) - db.commit() + for identifier, label in self.statuses.items(): + s = db.query(Status).filter_by(identifier = identifier).first() + if not s: + log.info('Creating status: %s', label) + s = Status( + identifier = identifier, + label = toUnicode(label) + ) + db.add(s) - #db.close() + s.label = toUnicode(label) + db.commit() + except: + log.error('Failed: %s', traceback.format_exc()) + db.rollback() + finally: + db.close() diff --git a/couchpotato/core/settings/__init__.py b/couchpotato/core/settings/__init__.py index 5e4952a..3b57517 100644 --- a/couchpotato/core/settings/__init__.py +++ b/couchpotato/core/settings/__init__.py @@ -1,4 +1,5 @@ from __future__ import with_statement +import traceback from couchpotato.api import addApiView from couchpotato.core.event import addEvent, fireEvent from couchpotato.core.helpers.encoding import toUnicode @@ -220,14 +221,20 @@ class Settings(object): def setProperty(self, identifier, value = ''): from couchpotato import get_session - db = get_session() + try: + db = get_session() - p = db.query(Properties).filter_by(identifier = identifier).first() - if not p: - p = Properties() - db.add(p) + p = db.query(Properties).filter_by(identifier = identifier).first() + if not p: + p = Properties() + db.add(p) - p.identifier = identifier - p.value = toUnicode(value) + p.identifier = identifier + p.value = toUnicode(value) - db.commit() + db.commit() + except: + self.log.error('Failed: %s', traceback.format_exc()) + db.rollback() + finally: + db.close() diff --git a/couchpotato/environment.py b/couchpotato/environment.py index c409da8..1c5863d 100644 --- a/couchpotato/environment.py +++ b/couchpotato/environment.py @@ -2,7 +2,6 @@ from couchpotato.core.event import fireEvent, addEvent from couchpotato.core.loader import Loader from couchpotato.core.settings import Settings from sqlalchemy.engine import create_engine -from sqlalchemy.orm import scoped_session from sqlalchemy.orm.session import sessionmaker import os @@ -24,7 +23,7 @@ class Env(object): _quiet = False _daemonized = False _desktop = None - _session = None + _engine = None ''' Data paths and directories ''' _app_dir = "" @@ -54,20 +53,20 @@ class Env(object): return setattr(Env, '_' + attr, value) @staticmethod - def getSession(engine = None): - existing_session = Env.get('session') - if existing_session: - return existing_session - - engine = Env.getEngine() - session = scoped_session(sessionmaker(bind = engine)) - Env.set('session', session) - - return session + def getSession(): + session = sessionmaker(bind = Env.getEngine()) + return session() @staticmethod def getEngine(): - return create_engine(Env.get('db_path'), echo = False) + existing_engine = Env.get('engine') + if existing_engine: + return existing_engine + + engine = create_engine(Env.get('db_path'), echo = False) + Env.set('engine', engine) + + return engine @staticmethod def setting(attr, section = 'core', value = None, default = '', type = None):