Commit 7e93285b authored by echel0n's avatar echel0n

Added cache to TVShow class for episodes.

parent 9a98f2d4
......@@ -44,6 +44,7 @@ from tornado.ioloop import IOLoop
import sickrage
from sickrage.core.announcements import Announcements
from sickrage.core.api import API
from sickrage.core.caches import tv_episodes_cache, MutexLock
from sickrage.core.caches.name_cache import NameCache
from sickrage.core.caches.quicksearch_cache import QuicksearchCache
from sickrage.core.common import SD, SKIPPED, WANTED
......@@ -82,6 +83,7 @@ from sickrage.providers import SearchProviders
class Core(object):
def __init__(self):
self.started = False
self.loading_shows = False
self.daemon = None
self.io_loop = None
self.pid = os.getpid()
......@@ -176,11 +178,15 @@ class Core(object):
def start(self):
self.started = True
self.io_loop = IOLoop.current()
# thread name
threading.currentThread().setName('CORE')
tv_episodes_cache.configure('dogpile.cache.dbm', replace_existing_backend=False,
arguments={'filename': os.path.join(self.cache_dir, 'tv_episodes.dbm'), 'lock_factory': MutexLock})
# init core classes
self.api = API()
self.main_db = MainDB(self.db_type, self.db_prefix, self.db_host, self.db_port, self.db_username, self.db_password)
......@@ -287,9 +293,6 @@ class Core(object):
self.log.info("Performing cleanup on {} database".format(db.name))
db.cleanup()
# load shows
self.load_shows()
# user agent
if self.config.random_user_agent:
self.user_agent = UserAgent().random
......@@ -309,7 +312,7 @@ class Core(object):
# cleanup cache folder
for folder in ['mako', 'sessions', 'indexers']:
try:
shutil.rmtree(os.path.join(sickrage.app.cache_dir, folder), ignore_errors=True)
shutil.rmtree(os.path.join(self.cache_dir, folder), ignore_errors=True)
except Exception:
continue
......@@ -521,16 +524,17 @@ class Core(object):
self.show_queue.start()
self.postprocessor_queue.start()
# fire off startup events
self.scheduler.add_job(self.load_shows)
self.scheduler.add_job(self.quicksearch_cache.run)
self.scheduler.add_job(self.name_cache.run)
self.scheduler.add_job(self.version_updater.run)
self.scheduler.add_job(self.tz_updater.run)
self.scheduler.add_job(self.announcements.run)
# start scheduler service
self.scheduler.start()
# fire off startup events
self.io_loop.run_in_executor(None, self.quicksearch_cache.run)
self.io_loop.run_in_executor(None, self.name_cache.run)
self.io_loop.run_in_executor(None, self.version_updater.run)
self.io_loop.run_in_executor(None, self.tz_updater.run)
self.io_loop.run_in_executor(None, self.announcements.run)
# start web server
self.wserver.start()
......@@ -553,18 +557,26 @@ class Core(object):
self.io_loop.start()
def load_shows(self):
threading.currentThread().setName('CORE')
session = self.main_db.session()
self.log.info('Loading initial shows list')
self.loading_shows = True
self.shows = {}
for show in session.query(MainDB.TVShow).with_entities(MainDB.TVShow.indexer_id, MainDB.TVShow.indexer, MainDB.TVShow.name):
try:
self.log.info('Loading show {}'.format(show.name))
self.shows.update({(show.indexer_id, show.indexer): TVShow(show.indexer_id, show.indexer)})
self.log.info('Loading show {} and populating episode cache'.format(show.name))
show = TVShow(show.indexer_id, show.indexer)
self.shows.update({(show.indexer_id, show.indexer): show})
show.episodes()
except Exception:
self.log.debug('There was an error loading show: {}'.format(show.name))
self.loading_shows = False
def shutdown(self, restart=False):
if self.started:
self.log.info('SiCKRAGE IS SHUTTING DOWN!!!')
......
from dogpile.cache import make_region
from dogpile.cache.backends.file import AbstractFileLock
from dogpile.util import ReadWriteMutex
class MutexLock(AbstractFileLock):
""":class:`MutexLock` is a thread-based rw lock based on :class:`dogpile.core.ReadWriteMutex`."""
def __init__(self, filename):
"""Constructor.
:param filename:
"""
self.mutex = ReadWriteMutex()
def acquire_read_lock(self, wait):
"""Default acquire_read_lock."""
ret = self.mutex.acquire_read_lock(wait)
return wait or ret
def acquire_write_lock(self, wait):
"""Default acquire_write_lock."""
ret = self.mutex.acquire_write_lock(wait)
return wait or ret
def release_read_lock(self):
"""Default release_read_lock."""
return self.mutex.release_read_lock()
def release_write_lock(self):
"""Default release_write_lock."""
return self.mutex.release_write_lock()
def region_key_generator(namespace, fn):
if not namespace:
namespace = fn.__name__
elif isinstance(namespace, tuple):
namespace = ':'.join(str(x) for x in namespace)
def generate_keys(*arg):
return "{namespace}:{identity}".format(namespace=namespace, identity=':'.join(str(x) for x in arg))
return generate_keys
tv_episodes_cache = make_region(function_key_generator=region_key_generator)
......@@ -74,7 +74,7 @@ class QuicksearchCache(object):
qsData = {
'category': 'shows',
'showid': indexer_id,
'seasons': len(show.episodes),
'seasons': len(set([s.season for s in show.episodes()])),
'name': show.name,
'img': sickrage.app.config.web_root + showImage(indexer_id, 'poster_thumb').url
}
......@@ -84,7 +84,7 @@ class QuicksearchCache(object):
session.commit()
sql_t = []
for e in show.episodes:
for e in show.episodes():
qsData = {
'category': 'episodes',
'showid': e.showid,
......
......@@ -198,7 +198,7 @@ def make_scene_season_search_string(show_id, season, episode, extraSearchType=No
seasonStrings.append("%02d" % ab_number)
else:
numseasons = len({x.season for x in show_object.episodes if x.season > 0})
numseasons = len(set([s.season for s in show_object.episodes() if s.season > 0]))
seasonStrings = ["S%02d" % int(episode_object.scene_season)]
showNames = set(make_scene_show_search_strings(show_id, episode_object.scene_season))
......@@ -232,7 +232,7 @@ def make_scene_search_string(show_id, season, episode):
show_object = find_show(show_id)
show_object = show_object.get_episode(season, episode)
numseasons = len({x.season for x in show_object.episodes if x.season > 0})
numseasons = len(set([s.season for s in show_object.episodes() if s.season > 0]))
# see if we should use dates instead of episodes
if (show_object.air_by_date or show_object.sports) and show_object.airdate > datetime.date.min:
......
......@@ -319,13 +319,10 @@ class QueueItemAdd(ShowQueueItem):
return self._finish_early()
# add show to database
sickrage.app.shows.update({(self.indexer_id, self.indexer): TVShow(self.indexer_id, self.indexer, lang=self.lang, location=self.showDir)})
show_obj = find_show(self.indexer_id, self.indexer)
if not show_obj:
return self._finish_early()
try:
# add show to database
show_obj = TVShow(self.indexer_id, self.indexer, lang=self.lang, location=self.showDir)
# set up initial values
show_obj.subtitles = self.subtitles or sickrage.app.config.subtitles_default
show_obj.sub_use_sr_metadata = self.sub_use_sr_metadata
......@@ -351,18 +348,13 @@ class QueueItemAdd(ShowQueueItem):
show_obj.release_groups.set_white_keywords(self.whitelist)
except indexer_exception as e:
sickrage.app.log.warning(_("Unable to add show due to an error with ") + IndexerApi(self.indexer).name + ": {}".format(e))
if show_obj:
sickrage.app.alerts.error(_("Unable to add ") + str(show_obj.name) + _(" due to an error with ") + IndexerApi(self.indexer).name + "")
else:
sickrage.app.alerts.error(_("Unable to add show due to an error with ") + IndexerApi(self.indexer).name + "")
sickrage.app.alerts.error(_("Unable to add show due to an error with ") + IndexerApi(self.indexer).name + "")
return self._finish_early()
except MultipleShowObjectsException:
sickrage.app.log.warning(_("The show in ") + self.showDir + _(" is already in your show list, skipping"))
sickrage.app.alerts.error(_('Show skipped'),
_("The show in ") + self.showDir + _(" is already in your show list"))
return self._finish_early()
except Exception as e:
sickrage.app.log.error(_("Error trying to add show: {}").format(e))
sickrage.app.log.debug(traceback.format_exc())
......@@ -476,7 +468,7 @@ class QueueItemRename(ShowQueueItem):
ep_obj_rename_list = []
for cur_ep_obj in (x for x in show_obj.episodes if x.location):
for cur_ep_obj in (x for x in show_obj.episodes() if x.location):
# Only want to rename if we have a location
if cur_ep_obj.location:
if cur_ep_obj.related_episodes:
......@@ -543,7 +535,7 @@ class QueueItemUpdate(ShowQueueItem):
# get episodes from database
db_episodes = {}
for data in show_obj.episodes:
for data in show_obj.episodes():
if data.season not in db_episodes:
db_episodes[data.season] = {}
db_episodes[data.season].update({data.episode: True})
......@@ -569,7 +561,7 @@ class QueueItemUpdate(ShowQueueItem):
for curEpisode in db_episodes[curSeason]:
sickrage.app.log.info("Permanently deleting episode " + str(curSeason) + "x" + str(curEpisode) + " from the database")
try:
show_obj.delete_episode(curSeason, curEpisode)
show_obj.get_episode(curSeason, curEpisode).delete_episode()
except EpisodeDeletedException:
continue
......
......@@ -211,7 +211,7 @@ def pick_best_result(results, season_pack=False):
quality_size = sickrage.app.config.quality_sizes[cur_result.quality]
if season_pack and not len(cur_result.episodes):
episode_count = len([x for x in show_obj.episodes if x.season == cur_result.season])
episode_count = len([x for x in show_obj.episodes() if x.season == cur_result.season])
file_size = float(cur_result.size / episode_count / 1000000)
else:
file_size = float(cur_result.size / len(cur_result.episodes) / 1000000)
......@@ -426,7 +426,7 @@ def search_providers(show_id, season, episode, manualSearch=False, downCurQualit
season_qual = best_season_result.quality
sickrage.app.log.debug("The quality of the season " + best_season_result.provider.type + " is " + Quality.qualityStrings[season_qual])
all_episodes = set([x.episode for x in show_object.episodes if x.season == best_season_result.season])
all_episodes = set([x.episode for x in show_object.episodes() if x.season == best_season_result.season])
sickrage.app.log.debug("Episodes list: {}".format(','.join(map(str, all_episodes))))
......
......@@ -109,7 +109,7 @@ class BacklogSearcher(object):
# check through the list of statuses to see if we want any
wanted = []
for episode_object in show.episodes:
for episode_object in show.episodes():
if not episode_object.season > 0 or not datetime.date.today() > episode_object.airdate > from_date:
continue
......
......@@ -92,7 +92,7 @@ class DailySearcher(object):
sickrage.app.log.debug("Seeing if we need anything for today from {}".format(show.name))
# check through the list of statuses to see if we want any
for episode_object in show.episodes:
for episode_object in show.episodes():
if not episode_object.season > 0 or not episode_object.airdate >= from_date:
continue
......
......@@ -189,7 +189,7 @@ class TraktSearcher(object):
sickrage.app.log.debug("COLLECTION::SYNC::START - Look for Episodes to Add to Trakt Collection")
for s in get_show_list():
for e in s.episodes:
for e in s.episodes():
trakt_id = IndexerApi(s.indexer).trakt_id
if not self._check_in_list(trakt_id, str(e.showid), e.season, e.episode, 'Collection'):
sickrage.app.log.debug("Adding Episode %s S%02dE%02d to collection" % (s.name, e.season, e.episode))
......@@ -211,7 +211,7 @@ class TraktSearcher(object):
"COLLECTION::REMOVE::START - Look for Episodes to Remove From Trakt Collection")
for s in get_show_list():
for e in s.episodes:
for e in s.episodes():
if e.location:
continue
......@@ -238,7 +238,7 @@ class TraktSearcher(object):
"WATCHLIST::REMOVE::START - Look for Episodes to Remove from Trakt Watchlist")
for s in get_show_list():
for e in s.episodes:
for e in s.episodes():
trakt_id = IndexerApi(s.indexer).trakt_id
if self._check_in_list(trakt_id, str(e.showid), e.season, e.episode):
sickrage.app.log.debug(
......
......@@ -24,7 +24,6 @@ import os
import re
import traceback
from collections import OrderedDict
from threading import Lock
from xml.etree.ElementTree import ElementTree
from mutagen.mp4 import MP4, MP4StreamInfoError
......@@ -49,8 +48,6 @@ from sickrage.subtitles import Subtitles
class TVEpisode(object):
def __init__(self, showid, indexer, season, episode, location=''):
self.lock = Lock
with sickrage.app.main_db.session() as session:
try:
query = session.query(MainDB.TVEpisode).filter_by(showid=showid, indexer=indexer, season=season, episode=episode).one()
......@@ -68,6 +65,11 @@ class TVEpisode(object):
query = session.query(MainDB.TVEpisode).filter_by(showid=showid, indexer=indexer, season=season, episode=episode).one()
self._data_local = query.as_dict()
episodes = self.show.episodes()
episodes.append(self)
self.show.episodes.set(episodes)
self.populate_episode(season, episode)
# self.checkForMetaFiles()
......@@ -274,7 +276,7 @@ class TVEpisode(object):
@property
def related_episodes(self):
return [x for x in self.show.episodes if x.location and x.location == self.location and x.season == self.season and x.episode != self.episode]
return [x for x in self.show.episodes() if x.location and x.location == self.location and x.season == self.season and x.episode != self.episode]
def save(self):
with sickrage.app.main_db.session() as session:
......@@ -287,6 +289,12 @@ class TVEpisode(object):
session.commit()
episodes = self.show.episodes()
index = next((i for i, x in enumerate(episodes) if
x.showid == self.showid and x.indexer == self.indexer and x.season == self.season and x.episode == self.episode))
episodes[index] = self
self.show.episodes.set(episodes)
def delete(self):
with sickrage.app.main_db.session() as session:
session.query(MainDB.TVEpisode).filter_by(showid=self.showid,
......@@ -295,6 +303,9 @@ class TVEpisode(object):
episode=self.episode).delete()
session.commit()
self.show.episodes.set([x for x in self.show.episodes() if
x.showid != self.showid and x.indexer != self.indexer and x.season != self.season and x.episode != self.episode])
def refresh_subtitles(self):
"""Look for subtitles files and refresh the subtitles property"""
subtitles, save_subtitles = Subtitles().refresh_subtitles(self.showid, self.season, self.episode)
......@@ -434,13 +445,13 @@ class TVEpisode(object):
# if I'm no longer on the Indexers but I once was then delete myself from the DB
if self.indexer_id != -1:
self.show.delete_episode(season, episode)
self.show.get_episode(season, episode).delete_episode()
return False
self.indexer_id = try_int(safe_getattr(myEp, 'id'), self.indexer_id)
if not self.indexer_id:
sickrage.app.log.warning("Failed to retrieve ID from " + IndexerApi(self.indexer).name)
self.show.delete_episode(season, episode)
self.show.get_episode(season, episode).delete_episode()
return False
self.name = safe_getattr(myEp, 'episodename', self.name)
......@@ -483,7 +494,7 @@ class TVEpisode(object):
firstaired, indexer_name, self.show.name, season or 0, episode or 0))
# if I'm incomplete on the indexer but I once was complete then just delete myself from the DB for now
self.show.delete_episode(season, episode)
self.show.get_episode(season, episode).delete_episode()
return False
# don't update show status if show dir is missing, unless it's missing on purpose
......@@ -665,7 +676,7 @@ class TVEpisode(object):
except OSError as e:
sickrage.app.log.warning('Unable to delete episode file %s: %s / %s' % (self.location, repr(e), str(e)))
# delete myself from the DB
# delete myself from the database and show episode cache
sickrage.app.log.debug("Deleting %s S%02dE%02d from the DB" % (self.show.name, self.season or 0, self.episode or 0))
self.delete()
......
......@@ -33,6 +33,7 @@ from sqlalchemy import orm
from unidecode import unidecode
import sickrage
from sickrage.core import tv_episodes_cache
from sickrage.core.api import APIError
from sickrage.core.blackandwhitelist import BlackAndWhiteList
from sickrage.core.caches.image_cache import ImageCache
......@@ -49,9 +50,6 @@ from sickrage.indexers.exceptions import indexer_attributenotfound
class TVShow(object):
def __init__(self, indexer_id, indexer, lang='en', location=''):
self.lock = Lock()
self._episodes = {}
with sickrage.app.main_db.session() as session:
try:
query = session.query(MainDB.TVShow).filter_by(indexer_id=indexer_id, indexer=indexer).one()
......@@ -69,6 +67,8 @@ class TVShow(object):
query = session.query(MainDB.TVShow).filter_by(indexer_id=indexer_id, indexer=indexer).one()
self._data_local = query.as_dict()
sickrage.app.shows.update({(self.indexer_id, self.indexer): self})
self.load_from_indexer()
@property
......@@ -343,13 +343,11 @@ class TVShow(object):
def last_proper_search(self, value):
self._data_local['last_proper_search'] = value
@property
@tv_episodes_cache.cache_on_arguments(namespace=(__name__, 'episodes'))
def episodes(self):
if not self._episodes:
with sickrage.app.main_db.session() as session:
query = session.query(MainDB.TVShow).filter_by(indexer_id=self.indexer_id, indexer=self.indexer).one()
[self._episodes.update({(x.season, x.episode): self.get_episode(x.season, x.episode)}) for x in query.episodes]
return self._episodes.values()
with sickrage.app.main_db.session() as session:
query = session.query(MainDB.TVShow).filter_by(indexer_id=self.indexer_id, indexer=self.indexer).one()
return [TVEpisode(showid=self.indexer_id, indexer=self.indexer, season=x.season, episode=x.episode) for x in query.episodes]
@property
def imdb_info(self):
......@@ -476,7 +474,7 @@ class TVShow(object):
cur_time = datetime.datetime.now(sickrage.app.tz)
new_episodes = []
for episode_object in self.episodes:
for episode_object in self.episodes():
if episode_object.status != UNAIRED or episode_object.season == 0 or episode_object.airdate < datetime.date.min:
continue
......@@ -505,7 +503,7 @@ class TVShow(object):
def total_size(self):
_total_size = 0
_related_episodes = set()
for episode_object in self.episodes:
for episode_object in self.episodes():
[_related_episodes.add(related_episode.indexer_id) for related_episode in episode_object.related_episodes]
if episode_object.indexer_id not in _related_episodes:
_total_size += episode_object.file_size
......@@ -534,9 +532,7 @@ class TVShow(object):
session.commit()
def flush_episodes(self):
for item in self._episodes.copy():
self._episodes[item] = None
del self._episodes[item]
self.episodes.set([x for x in self.episodes() if x.showid != self.indexer_id and x.indexer != self.indexer])
def load_from_indexer(self, cache=True, tvapi=None):
if self.indexer is not INDEXER_TVRAGE:
......@@ -641,10 +637,19 @@ class TVShow(object):
season = query.season
episode = query.episode
if (season, episode) not in self._episodes:
self._episodes.update({(season, episode): TVEpisode(showid=self.indexer_id, indexer=self.indexer, season=season, episode=episode)})
episodes = self.episodes()
try:
index = next((i for i, x in enumerate(episodes) if
x.showid == self.indexer_id and x.indexer == self.indexer and x.season == season and x.episode == episode))
return self._episodes[(season, episode)]
tv_episode = episodes[index]
except StopIteration:
tv_episode = TVEpisode(showid=self.indexer_id, indexer=self.indexer, season=season, episode=episode)
episodes.append(tv_episode)
self.episodes.set(episodes)
return tv_episode
except orm.exc.MultipleResultsFound:
if absolute_number is not None:
sickrage.app.log.debug("Multiple entries for absolute number: " + str(absolute_number) + " in show: " + self.name + " found ")
......@@ -654,12 +659,6 @@ class TVShow(object):
sickrage.app.log.debug("No entries for absolute number: " + str(absolute_number) + " in show: " + self.name + " found.")
raise EpisodeNotFoundException
def delete_episode(self, season, episode, full=False):
tv_episode = self.get_episode(season, episode)
tv_episode.delete_episode(full)
sickrage.app.log.debug("Deleting %s S%02dE%02d from shows episode cache" % (self.name, season, episode))
del self._episodes[(season, episode)]
def write_show_nfo(self, force=False):
result = False
......@@ -693,7 +692,7 @@ class TVShow(object):
sickrage.app.log.debug(str(self.indexer_id) + ": Writing NFOs for all episodes")
for episode_obj in self.episodes:
for episode_obj in self.episodes():
if episode_obj.location == '':
continue
......@@ -708,7 +707,7 @@ class TVShow(object):
sickrage.app.log.debug(str(self.indexer_id) + ": Updating video metadata for all episodes")
for episode_obj in self.episodes:
for episode_obj in self.episodes():
if episode_obj.location == '':
continue
......@@ -882,15 +881,7 @@ class TVShow(object):
try:
episode_obj = self.get_episode(season, episode)
except EpisodeNotFoundException:
with sickrage.app.main_db.session() as session:
session.add(MainDB.TVEpisode(**{'showid': self.indexer_id,
'indexer': self.indexer,
'season': season,
'episode': episode,
'location': filename}))
session.commit()
episode_obj = self.get_episode(season, episode)
episode_obj = TVEpisode(showid=self.indexer_id, indexer=self.indexer, season=season, episode=episode, location=filename)
# if there is a new file associated with this ep then re-check the quality
if episode_obj.location and os.path.normpath(episode_obj.location) != os.path.normpath(filename):
......@@ -983,6 +974,9 @@ class TVShow(object):
session.query(MainDB.SceneNumbering).filter_by(indexer_id=self.indexer_id).delete()
self.save()
# remove episodes from show episode cache
self.flush_episodes()
# remove from show cache
del sickrage.app.shows[(self.indexer_id, self.indexer)]
......@@ -1049,7 +1043,7 @@ class TVShow(object):
# run through all locations from DB, check that they exist
sickrage.app.log.debug(str(self.indexer_id) + ": Loading all episodes with a location from the database")
for curEp in self.episodes:
for curEp in self.episodes():
if curEp.location == '':
continue
......@@ -1105,7 +1099,7 @@ class TVShow(object):
sickrage.app.log.debug("%s: Downloading subtitles" % self.indexer_id)
try:
for episode in self.episodes:
for episode in self.episodes():
episode.download_subtitles()
except Exception:
sickrage.app.log.error("%s: Error occurred when downloading subtitles for %s" % (self.indexer_id, self.name))
......
......@@ -868,7 +868,7 @@ class CMD_EpisodeSetStatus(ApiCall):
return await _responds(RESULT_FAILURE, msg="Episode not found")
else:
# get all episode numbers in specified season
ep_list = [x for x in show_obj.episodes if x.season == self.s]
ep_list = [x for x in show_obj.episodes() if x.season == self.s]
def _epResult(result_code, ep, msg=""):
return {'season': ep.season, 'episode': ep.episode, 'status': _get_status_strings(ep.status),
......@@ -1128,7 +1128,7 @@ class CMD_Backlog(ApiCall):
if s.paused:
continue
for e in sorted(s.episodes, key=lambda x: (x.season, x.episode), reverse=True):
for e in sorted(s.episodes(), key=lambda x: (x.season, x.episode), reverse=True):
curEpCat = s.get_overview(int(e.status or -1))
if curEpCat and curEpCat in (Overview.WANTED, Overview.QUAL):
showEps += [e]
......@@ -2678,7 +2678,7 @@ class CMD_ShowsStats(ApiCall):
overall_stats['episodes']['snatched'] += show.episodes_snatched or 0
overall_stats['episodes']['downloaded'] += show.episodes_downloaded or 0
overall_stats['episodes']['total'] += show.episodes.count() or 0
overall_stats['episodes']['total'] += len(show.episodes()) or 0
overall_stats['total_size'] += show.total_size or 0
return await _responds(RESULT_SUCCESS, {
......
......@@ -66,7 +66,7 @@ class CalendarHandler(BaseHandler, ABC):
if show.status.lower() not in ['continuing', 'returning series'] or show.paused:
continue
for episode in show.episodes:
for episode in show.episodes():
if not past_date <= episode.airdate < future_date:
continue
......
......@@ -116,7 +116,7 @@ class HomeHandler(BaseHandler, ABC):
'ep_airs_prev': show.airs_prev or datetime.date.min,
'ep_snatched': show.episodes_snatched or 0,
'ep_downloaded': show.episodes_downloaded or 0,
'ep_total': len(show.episodes),
'ep_total': len(show.episodes()),
'total_size': show.total_size or 0
}
......@@ -133,9 +133,12 @@ class ShowProgressHandler(BaseHandler, ABC):
show_id = self.get_argument('show-id')
show = find_show(int(show_id))
if not show:
return
episodes_snatched = show.episodes_snatched
episodes_downloaded = show.episodes_downloaded
episodes_total = len(show.episodes) - show.episodes_special - show.episodes_unaired
episodes_total = len(show.episodes()) - show.episodes_special - show.episodes_unaired
progressbar_percent = int(episodes_downloaded * 100 / episodes_total if episodes_total > 0 else 1)
progress_text = '?'
......@@ -775,7 +778,7 @@ class DisplayShowHandler(BaseHandler, ABC):
if not show_obj:
return self._genericMessage(_("Error"), _("Show not in show list"))
episode_objects = sorted(show_obj.episodes, key=lambda x: (x.season, x.episode), reverse=True)
episode_objects = sorted(show_obj.episodes(), key=lambda x: (x.season, x.episode), reverse=True)
season_results = list({x.season for x in episode_objects})
......@@ -1190,7 +1193,8 @@ class DeleteEpisodeHandler(BaseHandler, ABC):
episode = int(ep_info[1])
try:
show_obj.show.delete_episode(season, episode, full=True)
tv_episode = show_obj.get_episode(season, episode)
tv_episode.delete_episode(full=True)
except EpisodeNotFoundException:
return self._genericMessage(_("Error"), _("Episode couldn't be retrieved"))
except EpisodeDeletedException:
......@@ -1217,7 +1221,7 @@ class TestRenameHandler(BaseHandler, ABC):
episode_objects = []
for cur_ep_obj in (x for x in show_object.episodes if x.location):
for cur_ep_obj in (x for x in show_object.episodes() if x.location):
if cur_ep_obj.location:
if cur_ep_obj.related_episodes:
for cur_related_ep in cur_ep_obj.related_episodes + [cur_ep_obj]:
......
......@@ -102,6 +102,8 @@ def set_episode_status(show, eps, status, direct=None):
episode_object.status = int(status)
episode_object.save()
trakt_data += [(episode_object.season, episode_object.episode)]
data = sickrage.app.notifier_providers['trakt'].trakt_episode_data_generate(trakt_data)
......@@ -366,7 +368,7 @@ class EpisodeStatusesHandler(BaseHandler, ABC):
# if we have no status then this is as far as we need to go
if len(status_list):
for show in sorted(get_show_list(), key=lambda d: d.name):
for episode in show.episodes:
for episode in show.episodes():
if episode.season != 0 and episode.status in status_list:
if show.indexer_id not in ep_counts:
ep_counts[show.indexer_id] = 1
......@@ -490,7 +492,7 @@ class SubtitleMissedHandler(BaseHandler, ABC):
if not s.subtitles == 1:
continue
for e in s.episodes:
for e in s.episodes():
if e.season != 0 and (str(e.status).endswith('4') or str(e.status).endswith('6')):
status_results += [{
'show_name': s.name,
......@@ -596,7 +598,7 @@ class BacklogOverviewHandler(BaseHandler, ABC):
show_results[curShow.indexer_id] = []
for curResult in sorted(curShow.episodes, key=lambda x: (x.season, x.episode), reverse=True):
for curResult in sorted(curShow.episodes(), key=lambda x: (x.season, x.episode), reverse=True):
cur_ep_cat = curShow.get_overview(int(curResult.status or -1))
if cur_ep_cat:
ep_cats["{}x{}".format(curResult.season, curResult.episode)] = cur_ep_cat
......