Browse Source

Change put some vars into kwargs if not used in a method.

Change swap _tvid around with tvid, in order to deprecate using _tvid and remove pyc private var use warnings (bad practice) which was being pushed into use due to perf, so now sg will use direct access public property by default.
Change rename misused varnames `_sql` that are not SQL but rather an sql result set.
Change various other clean ups and simplifications.
Fix invalid case warnings.
tags/release_0.25.1
JackDandy 4 years ago
parent
commit
a8f89ca98d
  1. 20
      sickbeard/_legacy_classes.py
  2. 24
      sickbeard/helpers.py
  3. 14
      sickbeard/image_cache.py
  4. 106
      sickbeard/indexermapper.py
  5. 2
      sickbeard/people_queue.py
  6. 514
      sickbeard/scene_numbering.py
  7. 2
      sickbeard/search.py
  8. 6
      sickbeard/search_queue.py
  9. 291
      sickbeard/show_queue.py
  10. 1227
      sickbeard/tv.py
  11. 70
      sickbeard/tv_base.py
  12. 2
      sickbeard/webserve.py
  13. 2
      sickgear.py
  14. 6
      tests/name_parser_tests.py

20
sickbeard/_legacy_classes.py

@ -64,19 +64,19 @@ class LegacyTVShow(object):
@property @property
@deprecated('(TVShow) Use tvid_prodid or tvid __getter__ instead') @deprecated('(TVShow) Use tvid_prodid or tvid __getter__ instead')
def indexer(self): def indexer(self):
return self.tvid return self._tvid
@property @property
def tvid(self): def _tvid(self):
raise NotImplementedError raise NotImplementedError
@indexer.setter @indexer.setter
@deprecated('(TVShow) Use tvid_prodid or tvid __setter__ instead') @deprecated('(TVShow) Use tvid_prodid or tvid __setter__ instead')
def indexer(self, val): def indexer(self, val):
self.tvid = val self._tvid = val
@tvid.setter @_tvid.setter
def tvid(self, val): def _tvid(self, val):
raise NotImplementedError raise NotImplementedError
# TODO: deprecating TVShow.indexerid # TODO: deprecating TVShow.indexerid
@ -84,19 +84,19 @@ class LegacyTVShow(object):
@property @property
@deprecated('(TVShow) Use tvid_prodid or prodid __getter__ instead') @deprecated('(TVShow) Use tvid_prodid or prodid __getter__ instead')
def indexerid(self): def indexerid(self):
return self.prodid return self._prodid
@property @property
def prodid(self): def _prodid(self):
raise NotImplementedError raise NotImplementedError
@indexerid.setter @indexerid.setter
@deprecated('(TVShow) Use tvid_prodid or prodid __setter__ instead') @deprecated('(TVShow) Use tvid_prodid or prodid __setter__ instead')
def indexerid(self, val): def indexerid(self, val):
self.prodid = val self._prodid = val
@prodid.setter @_prodid.setter
def prodid(self, val): def _prodid(self, val):
raise NotImplementedError raise NotImplementedError

24
sickbeard/helpers.py

@ -273,27 +273,27 @@ def search_infosrc_for_show_id(reg_show_name, tvid=None, prodid=None, ui=None):
show_names = [re.sub('[. -]', ' ', reg_show_name)] show_names = [re.sub('[. -]', ' ', reg_show_name)]
# Query Indexers for each search term and build the list of results # Query Indexers for each search term and build the list of results
for _tvid in (sickbeard.TVInfoAPI().sources if not tvid else [int(tvid)]) or []: for cur_tvid in (sickbeard.TVInfoAPI().sources if not tvid else [int(tvid)]) or []:
# Query Indexers for each search term and build the list of results # Query Indexers for each search term and build the list of results
tvinfo_config = sickbeard.TVInfoAPI(_tvid).api_params.copy() tvinfo_config = sickbeard.TVInfoAPI(cur_tvid).api_params.copy()
if ui is not None: if ui is not None:
tvinfo_config['custom_ui'] = ui tvinfo_config['custom_ui'] = ui
t = sickbeard.TVInfoAPI(_tvid).setup(**tvinfo_config) t = sickbeard.TVInfoAPI(cur_tvid).setup(**tvinfo_config)
for name in show_names: for cur_name in show_names:
logger.log('Trying to find %s on %s' % (name, sickbeard.TVInfoAPI(_tvid).name), logger.DEBUG) logger.debug('Trying to find %s on %s' % (cur_name, sickbeard.TVInfoAPI(cur_tvid).name))
try: try:
show_info_list = t[prodid] if prodid else t[name] show_info_list = t[prodid] if prodid else t[cur_name]
show_info_list = show_info_list if isinstance(show_info_list, list) else [show_info_list] show_info_list = show_info_list if isinstance(show_info_list, list) else [show_info_list]
except (BaseException, Exception): except (BaseException, Exception):
continue continue
seriesname = _prodid = None seriesname = _prodid = None
for show_info in show_info_list: # type: dict for cur_show_info in show_info_list: # type: dict
try: try:
seriesname = show_info['seriesname'] seriesname = cur_show_info['seriesname']
_prodid = show_info['id'] _prodid = cur_show_info['id']
except (BaseException, Exception): except (BaseException, Exception):
_prodid = seriesname = None _prodid = seriesname = None
continue continue
@ -303,10 +303,10 @@ def search_infosrc_for_show_id(reg_show_name, tvid=None, prodid=None, ui=None):
if not (seriesname and _prodid): if not (seriesname and _prodid):
continue continue
if None is prodid and str(name).lower() == str(seriesname).lower(): if None is prodid and str(cur_name).lower() == str(seriesname).lower():
return seriesname, _tvid, int(_prodid) return seriesname, cur_tvid, int(_prodid)
elif None is not prodid and int(prodid) == int(_prodid): elif None is not prodid and int(prodid) == int(_prodid):
return seriesname, _tvid, int(prodid) return seriesname, cur_tvid, int(prodid)
if tvid: if tvid:
break break

14
sickbeard/image_cache.py

@ -73,11 +73,13 @@ class ImageCache(object):
# """ # """
# return ek.ek(os.path.abspath, ek.ek(os.path.join, sickbeard.CACHE_DIR, 'images')) # return ek.ek(os.path.abspath, ek.ek(os.path.join, sickbeard.CACHE_DIR, 'images'))
def _persons_dir(self): @staticmethod
def _persons_dir():
# type: (...) -> AnyStr # type: (...) -> AnyStr
return ek.ek(os.path.join, sickbeard.CACHE_DIR, 'images', 'person') return ek.ek(os.path.join, sickbeard.CACHE_DIR, 'images', 'person')
def _characters_dir(self): @staticmethod
def _characters_dir():
# type: (...) -> AnyStr # type: (...) -> AnyStr
return ek.ek(os.path.join, sickbeard.CACHE_DIR, 'images', 'characters') return ek.ek(os.path.join, sickbeard.CACHE_DIR, 'images', 'characters')
@ -110,15 +112,17 @@ class ImageCache(object):
""" """
return ek.ek(os.path.abspath, ek.ek(os.path.join, self.shows_dir, '%s-%s' % (tvid, prodid), 'thumbnails')) return ek.ek(os.path.abspath, ek.ek(os.path.join, self.shows_dir, '%s-%s' % (tvid, prodid), 'thumbnails'))
def _person_base_name(self, person_obj): @staticmethod
def _person_base_name(person_obj):
# type: (Person) -> AnyStr # type: (Person) -> AnyStr
base_id = next((v for k, v in iteritems(cache_img_base) base_id = next((v for k, v in iteritems(cache_img_base)
if k in (person_obj.image_url or '') or person_obj.thumb_url), 0) if k in (person_obj.image_url or '') or person_obj.thumb_url), 0)
return '%s-%s' % (base_id, person_obj.ids.get(base_id) or sg_helpers.sanitize_filename(person_obj.name)) return '%s-%s' % (base_id, person_obj.ids.get(base_id) or sg_helpers.sanitize_filename(person_obj.name))
def _character_base_name(self, character_obj, show_obj, tvid=None, proid=None): @staticmethod
def _character_base_name(character_obj, show_obj, tvid=None, proid=None):
# type: (Character, TVShow, integer_types, integer_types) -> AnyStr # type: (Character, TVShow, integer_types, integer_types) -> AnyStr
return '%s-%s' % (tvid or show_obj._tvid, character_obj.ids.get(tvid or show_obj._tvid) return '%s-%s' % (tvid or show_obj.tvid, character_obj.ids.get(tvid or show_obj.tvid)
or sg_helpers.sanitize_filename(character_obj.name)) or sg_helpers.sanitize_filename(character_obj.name))
def person_path(self, person_obj, base_path=None): def person_path(self, person_obj, base_path=None):

106
sickbeard/indexermapper.py

@ -21,21 +21,22 @@ import os
import re import re
import traceback import traceback
# noinspection PyPep8Naming
import encodingKludge as ek
import sickbeard
from . import db, logger from . import db, logger
from .helpers import get_url, try_int from .helpers import get_url, try_int
from .indexers.indexer_config import TVINFO_TVDB, TVINFO_IMDB, TVINFO_TVMAZE, TVINFO_TVRAGE, TVINFO_TMDB, TVINFO_TRAKT from .indexers.indexer_config import TVINFO_IMDB, TVINFO_TMDB, TVINFO_TRAKT, TVINFO_TVDB, TVINFO_TVMAZE, TVINFO_TVRAGE
# noinspection PyPep8Naming
import encodingKludge as ek
import requests import requests
import sickbeard
from exceptions_helper import ConnectionSkipException
# noinspection PyPep8Naming # noinspection PyPep8Naming
from lib import tmdbsimple as TMDB from lib import tmdbsimple as TMDB
from lib.dateutil.parser import parse from lib.dateutil.parser import parse
from lib.imdbpie import Imdb from lib.imdbpie import Imdb
from libtrakt import TraktAPI from libtrakt import TraktAPI
from libtrakt.exceptions import TraktAuthException, TraktException from libtrakt.exceptions import TraktAuthException, TraktException
from exceptions_helper import ConnectionSkipException
from _23 import unidecode, urlencode from _23 import unidecode, urlencode
from six import iteritems, iterkeys, string_types, PY2 from six import iteritems, iterkeys, string_types, PY2
@ -110,8 +111,10 @@ class TraktDict(OrderedDict):
# noinspection PyUnusedLocal # noinspection PyUnusedLocal
def tvmaze_record_hook(r, *args, **kwargs): def tvmaze_record_hook(r, *args, **kwargs):
r.hook_called = True r.hook_called = True
# noinspection HttpUrlsUsage
if 301 == r.status_code and isinstance(r.headers.get('Location'), string_types) \ if 301 == r.status_code and isinstance(r.headers.get('Location'), string_types) \
and r.headers.get('Location').startswith('http://api.tvmaze'): and r.headers.get('Location').startswith('http''://api.tvmaze'):
# noinspection HttpUrlsUsage
r.headers['Location'] = r.headers['Location'].replace('http://', 'https://') r.headers['Location'] = r.headers['Location'].replace('http://', 'https://')
return r return r
@ -146,10 +149,10 @@ def get_tvmaze_ids(url_tvmaze):
try: try:
res = get_tvmaze_data(url=url_tvmaze.get_url(url_key), parse_json=True, raise_status_code=True, timeout=120) res = get_tvmaze_data(url=url_tvmaze.get_url(url_key), parse_json=True, raise_status_code=True, timeout=120)
if res and 'externals' in res: if res and 'externals' in res:
ids[TVINFO_TVRAGE] = res['externals'].get('tvrage', 0)
ids[TVINFO_TVDB] = res['externals'].get('thetvdb', 0)
ids[TVINFO_IMDB] = try_int(str(res['externals'].get('imdb')).replace('tt', '')) ids[TVINFO_IMDB] = try_int(str(res['externals'].get('imdb')).replace('tt', ''))
ids[TVINFO_TVDB] = res['externals'].get('thetvdb', 0)
ids[TVINFO_TVMAZE] = res.get('id', 0) ids[TVINFO_TVMAZE] = res.get('id', 0)
ids[TVINFO_TVRAGE] = res['externals'].get('tvrage', 0)
break break
except (BaseException, Exception): except (BaseException, Exception):
pass pass
@ -206,10 +209,10 @@ def get_tvmaze_by_name(showname, premiere_date):
if 'show' in r and 'premiered' in r['show'] and 'externals' in r['show']: if 'show' in r and 'premiered' in r['show'] and 'externals' in r['show']:
premiered = parse(r['show']['premiered'], fuzzy=True) premiered = parse(r['show']['premiered'], fuzzy=True)
if abs(premiere_date - premiered.date()) < datetime.timedelta(days=2): if abs(premiere_date - premiered.date()) < datetime.timedelta(days=2):
ids[TVINFO_TVRAGE] = r['show']['externals'].get('tvrage', 0)
ids[TVINFO_TVDB] = r['show']['externals'].get('thetvdb', 0)
ids[TVINFO_IMDB] = try_int(str(r['show']['externals'].get('imdb')).replace('tt', '')) ids[TVINFO_IMDB] = try_int(str(r['show']['externals'].get('imdb')).replace('tt', ''))
ids[TVINFO_TVDB] = r['show']['externals'].get('thetvdb', 0)
ids[TVINFO_TVMAZE] = r['show'].get('id', 0) ids[TVINFO_TVMAZE] = r['show'].get('id', 0)
ids[TVINFO_TVRAGE] = r['show']['externals'].get('tvrage', 0)
break break
except (BaseException, Exception): except (BaseException, Exception):
pass pass
@ -232,11 +235,11 @@ def get_trakt_ids(url_trakt):
found = False found = False
for r in res: for r in res:
if 'show' == r.get('type', '') and 'show' in r and 'ids' in r['show']: if 'show' == r.get('type', '') and 'show' in r and 'ids' in r['show']:
ids[TVINFO_TVDB] = try_int(r['show']['ids'].get('tvdb', 0))
ids[TVINFO_TVRAGE] = try_int(r['show']['ids'].get('tvrage', 0))
ids[TVINFO_IMDB] = try_int(str(r['show']['ids'].get('imdb')).replace('tt', '')) ids[TVINFO_IMDB] = try_int(str(r['show']['ids'].get('imdb')).replace('tt', ''))
ids[TVINFO_TRAKT] = try_int(r['show']['ids'].get('trakt', 0))
ids[TVINFO_TMDB] = try_int(r['show']['ids'].get('tmdb', 0)) ids[TVINFO_TMDB] = try_int(r['show']['ids'].get('tmdb', 0))
ids[TVINFO_TRAKT] = try_int(r['show']['ids'].get('trakt', 0))
ids[TVINFO_TVDB] = try_int(r['show']['ids'].get('tvdb', 0))
ids[TVINFO_TVRAGE] = try_int(r['show']['ids'].get('tvrage', 0))
found = True found = True
break break
if found: if found:
@ -318,19 +321,16 @@ def check_missing_trakt_id(n_ids, show_obj, url_trakt):
return n_ids return n_ids
def map_indexers_to_show(show_obj, update=False, force=False, recheck=False, sql=None): def map_indexers_to_show(show_obj, update=False, force=False, recheck=False, im_sql_result=None):
# type: (sickbeard.tv.TVShow, Optional[bool], Optional[bool], Optional[bool], Optional[list]) -> dict
""" """
:param show_obj: TVShow Object :param show_obj: TVShow Object
:type show_obj: sickbeard.tv.TVShow
:param update: add missing + previously not found ids :param update: add missing + previously not found ids
:type update: bool
:param force: search for and replace all mapped/missing ids (excluding NO_AUTOMATIC_CHANGE flagged) :param force: search for and replace all mapped/missing ids (excluding NO_AUTOMATIC_CHANGE flagged)
:type force: bool
:param recheck: load all ids, don't remove existing :param recheck: load all ids, don't remove existing
:type recheck: bool :param im_sql_result:
:return: mapped ids :return: mapped ids
:rtype: Dict
""" """
mapped = {} mapped = {}
@ -341,24 +341,25 @@ def map_indexers_to_show(show_obj, update=False, force=False, recheck=False, sql
'date': datetime.date.fromordinal(1)} 'date': datetime.date.fromordinal(1)}
sql_result = [] sql_result = []
if sql: for cur_row in im_sql_result or []:
for s in sql: if show_obj.prodid == cur_row['indexer_id'] and show_obj.tvid == cur_row['indexer']:
if show_obj._prodid == s['indexer_id'] and show_obj._tvid == s['indexer']: sql_result.append(cur_row)
sql_result.append(s)
if not sql_result: if not sql_result:
my_db = db.DBConnection() my_db = db.DBConnection()
sql_result = my_db.select('SELECT *' sql_result = my_db.select(
' FROM indexer_mapping' """
' WHERE indexer = ? AND indexer_id = ?', SELECT *
[show_obj.tvid, show_obj.prodid]) FROM indexer_mapping
WHERE indexer = ? AND indexer_id = ?
""", [show_obj.tvid, show_obj.prodid])
# for each mapped entry # for each mapped entry
for cur_result in sql_result: for cur_row in sql_result:
date = try_int(cur_result['date']) date = try_int(cur_row['date'])
mapped[int(cur_result['mindexer'])] = {'status': int(cur_result['status']), mapped[int(cur_row['mindexer'])] = {'status': int(cur_row['status']),
'id': int(cur_result['mindexer_id']), 'id': int(cur_row['mindexer_id']),
'date': datetime.date.fromordinal(date if 0 < date else 1)} 'date': datetime.date.fromordinal(date if 0 < date else 1)}
# get list of needed ids # get list of needed ids
mis_map = [k for k, v in iteritems(mapped) if (v['status'] not in [ mis_map = [k for k, v in iteritems(mapped) if (v['status'] not in [
@ -453,9 +454,9 @@ def map_indexers_to_show(show_obj, update=False, force=False, recheck=False, sql
TMDB.API_KEY = sickbeard.TMDB_API_KEY TMDB.API_KEY = sickbeard.TMDB_API_KEY
tmdb_data = TMDB.Search().tv(**{'query': clean_show_name(show_obj.name), tmdb_data = TMDB.Search().tv(**{'query': clean_show_name(show_obj.name),
'first_air_date_year': show_obj.startyear}) 'first_air_date_year': show_obj.startyear})
for s in tmdb_data.get('results'): for cur_row in tmdb_data.get('results'):
if clean_show_name(s['name']) == clean_show_name(show_obj.name): if clean_show_name(cur_row['name']) == clean_show_name(show_obj.name):
new_ids[TVINFO_TMDB] = try_int(s['id']) new_ids[TVINFO_TMDB] = try_int(cur_row['id'])
break break
except (BaseException, Exception): except (BaseException, Exception):
pass pass
@ -484,16 +485,17 @@ def map_indexers_to_show(show_obj, update=False, force=False, recheck=False, sql
if 0 != mapped[tvid]['id'] or MapStatus.NONE != mapped[tvid]['status']: if 0 != mapped[tvid]['id'] or MapStatus.NONE != mapped[tvid]['status']:
mapped[tvid]['date'] = today mapped[tvid]['date'] = today
sql_l.append([ sql_l.append([
'INSERT OR REPLACE INTO indexer_mapping (' + """
'indexer_id, indexer, mindexer_id, mindexer, date, status) VALUES (?,?,?,?,?,?)', INSERT OR REPLACE
[show_obj.prodid, show_obj.tvid, mapped[tvid]['id'], INTO indexer_mapping (indexer_id, indexer, mindexer_id, mindexer, date, status)
tvid, date, mapped[tvid]['status']]]) VALUES (?,?,?,?,?,?)
""", [show_obj.prodid, show_obj.tvid, mapped[tvid]['id'], tvid, date, mapped[tvid]['status']]])
else: else:
sql_l.append([ sql_l.append([
'DELETE FROM indexer_mapping' """
' WHERE indexer = ? AND indexer_id = ?' DELETE FROM indexer_mapping
' AND mindexer = ?', WHERE indexer = ? AND indexer_id = ? AND mindexer = ?
[show_obj.tvid, show_obj.prodid, tvid]]) """, [show_obj.tvid, show_obj.prodid, tvid]])
if 0 < len(sql_l): if 0 < len(sql_l):
logger.log('Adding TV info mapping to DB for show: %s' % show_obj.name, logger.DEBUG) logger.log('Adding TV info mapping to DB for show: %s' % show_obj.name, logger.DEBUG)
@ -528,10 +530,10 @@ def save_mapping(show_obj, save_map=None):
tvid, date, show_obj.ids[tvid]['status']]]) tvid, date, show_obj.ids[tvid]['status']]])
else: else:
sql_l.append([ sql_l.append([
'DELETE FROM indexer_mapping' """
' WHERE indexer = ? AND indexer_id = ?' DELETE FROM indexer_mapping
' AND mindexer = ?', WHERE indexer = ? AND indexer_id = ? AND mindexer = ?
[show_obj.tvid, show_obj.prodid, tvid]]) """, [show_obj.tvid, show_obj.prodid, tvid]])
if 0 < len(sql_l): if 0 < len(sql_l):
logger.log('Saving TV info mapping to DB for show: %s' % show_obj.name, logger.DEBUG) logger.log('Saving TV info mapping to DB for show: %s' % show_obj.name, logger.DEBUG)
@ -548,9 +550,11 @@ def del_mapping(tvid, prodid):
:type prodid: int or long :type prodid: int or long
""" """
my_db = db.DBConnection() my_db = db.DBConnection()
my_db.action('DELETE FROM indexer_mapping' my_db.action(
' WHERE indexer = ? AND indexer_id = ?', """
[tvid, prodid]) DELETE FROM indexer_mapping
WHERE indexer = ? AND indexer_id = ?
""", [tvid, prodid])
def should_recheck_update_ids(show_obj): def should_recheck_update_ids(show_obj):
@ -593,7 +597,7 @@ def load_mapped_ids(**kwargs):
if 'update' in kwargs and should_recheck_update_ids(cur_show_obj): if 'update' in kwargs and should_recheck_update_ids(cur_show_obj):
n_kargs['recheck'] = True n_kargs['recheck'] = True
if sql_result: if sql_result:
n_kargs['sql'] = sql_result n_kargs['im_sql_result'] = sql_result
try: try:
cur_show_obj.ids = sickbeard.indexermapper.map_indexers_to_show(cur_show_obj, **n_kargs) cur_show_obj.ids = sickbeard.indexermapper.map_indexers_to_show(cur_show_obj, **n_kargs)
except (BaseException, Exception): except (BaseException, Exception):

2
sickbeard/people_queue.py

@ -74,7 +74,7 @@ class PeopleQueue(generic_queue.GenericQueue):
return [ return [
['INSERT OR IGNORE INTO people_queue (indexer, indexer_id, action_id, forced, scheduled, uid)' ['INSERT OR IGNORE INTO people_queue (indexer, indexer_id, action_id, forced, scheduled, uid)'
' VALUES (?,?,?,?,?,?)', ' VALUES (?,?,?,?,?,?)',
[item.show_obj._tvid, item.show_obj._prodid, item.action_id, int(item.force), int(item.scheduled_update), [item.show_obj.tvid, item.show_obj.prodid, item.action_id, int(item.force), int(item.scheduled_update),
item.uid]] item.uid]]
] ]

514
sickbeard/scene_numbering.py

@ -23,9 +23,11 @@
import datetime import datetime
import traceback import traceback
from sqlite3 import Row
from exceptions_helper import ex from exceptions_helper import ex
import sickbeard import sickbeard
from . import db, logger from . import db, logger
from .helpers import try_int from .helpers import try_int
@ -39,14 +41,16 @@ if False:
from typing import Dict, Tuple from typing import Dict, Tuple
def get_scene_numbering(tvid, prodid, season, episode, fallback_to_xem=True, show_sql=None, scene_sql=None, def get_scene_numbering(tvid, prodid, season, episode, fallback_to_xem=True, show_obj=None, **kwargs):
show_obj=None):
""" """
Returns a tuple, (season, episode), with the scene numbering (if there is one), Returns a tuple, (season, episode), with the scene numbering (if there is one),
otherwise returns the xem numbering (if fallback_to_xem is set), otherwise otherwise returns the xem numbering (if fallback_to_xem is set), otherwise
returns the TVDB numbering. returns the TVDB numbering.
(so the return values will always be set) (so the return values will always be set)
kwargs['scene_result']: type: Optional[List[Row]] passed thru
kwargs['show_result']: type: Optional[List[Row]] passed thru
:param tvid: tvid :param tvid: tvid
:type tvid: int :type tvid: int
:param prodid: prodid :param prodid: prodid
@ -57,6 +61,8 @@ def get_scene_numbering(tvid, prodid, season, episode, fallback_to_xem=True, sho
:type episode: int :type episode: int
:param fallback_to_xem: If set (the default), check xem for matches if there is no local scene numbering :param fallback_to_xem: If set (the default), check xem for matches if there is no local scene numbering
:type fallback_to_xem: bool :type fallback_to_xem: bool
:param show_obj:
:type show_obj:
:return: (int, int) a tuple with (season, episode) :return: (int, int) a tuple with (season, episode)
:rtype: Tuple[int, int] :rtype: Tuple[int, int]
""" """
@ -69,18 +75,18 @@ def get_scene_numbering(tvid, prodid, season, episode, fallback_to_xem=True, sho
if show_obj and not show_obj.is_scene: if show_obj and not show_obj.is_scene:
return season, episode return season, episode
result = find_scene_numbering(tvid, prodid, season, episode, scene_sql=scene_sql) result = find_scene_numbering(tvid, prodid, season, episode, scene_result=kwargs.get('scene_result'))
if result: if result:
return result return result
else: else:
if fallback_to_xem: if fallback_to_xem:
xem_result = find_xem_numbering(tvid, prodid, season, episode, show_sql=show_sql) xem_result = find_xem_numbering(tvid, prodid, season, episode, show_result=kwargs.get('show_result'))
if xem_result: if xem_result:
return xem_result return xem_result
return season, episode return season, episode
def find_scene_numbering(tvid, prodid, season, episode, scene_sql=None): def find_scene_numbering(tvid, prodid, season, episode, scene_result=None):
""" """
Same as get_scene_numbering(), but returns None if scene numbering is not set Same as get_scene_numbering(), but returns None if scene numbering is not set
:param tvid: tvid :param tvid: tvid
@ -91,6 +97,8 @@ def find_scene_numbering(tvid, prodid, season, episode, scene_sql=None):
:type season: int :type season: int
:param episode: episode number :param episode: episode number
:type episode: int :type episode: int
:param scene_result:
:type scene_result:
:return: :return:
:rtype: Tuple[int, int] or None :rtype: Tuple[int, int] or None
""" """
@ -99,36 +107,39 @@ def find_scene_numbering(tvid, prodid, season, episode, scene_sql=None):
tvid, prodid = int(tvid), int(prodid) tvid, prodid = int(tvid), int(prodid)
rows = None sql_result = None
if None is not scene_sql: if None is not scene_result:
for e in scene_sql: for cur_row in scene_result:
if e['season'] == season and e['episode'] == episode: if cur_row['season'] == season and cur_row['episode'] == episode:
if e['scene_season'] or e['scene_episode']: if cur_row['scene_season'] or cur_row['scene_episode']:
rows = [e] sql_result = [cur_row]
break break
else: else:
my_db = db.DBConnection() my_db = db.DBConnection()
rows = my_db.select( sql_result = my_db.select(
'SELECT scene_season, scene_episode' """
' FROM scene_numbering' SELECT scene_season, scene_episode
' WHERE indexer = ? AND indexer_id = ?' FROM scene_numbering
' AND season = ? AND episode = ? AND (scene_season OR scene_episode) != 0', WHERE indexer = ? AND indexer_id = ? AND season = ? AND episode = ? AND (scene_season OR scene_episode) != 0
[tvid, prodid, season, episode]) """, [tvid, prodid, season, episode])
if rows: if sql_result:
s_s, s_e = try_int(rows[0]['scene_season'], None), try_int(rows[0]['scene_episode'], None) s_s, s_e = try_int(sql_result[0]['scene_season'], None), try_int(sql_result[0]['scene_episode'], None)
if None is not s_s and None is not s_e: if None is not s_s and None is not s_e:
return s_s, s_e return s_s, s_e
def get_scene_absolute_numbering(tvid, prodid, absolute_number, season, episode, fallback_to_xem=True, show_sql=None, def get_scene_absolute_numbering(tvid, prodid, absolute_number, season, episode, fallback_to_xem=True,
scene_sql=None, show_obj=None): show_obj=None, **kwargs):
""" """
Returns a tuple, (season, episode), with the scene numbering (if there is one), Returns a tuple, (season, episode), with the scene numbering (if there is one),
otherwise returns the xem numbering (if fallback_to_xem is set), otherwise otherwise returns the xem numbering (if fallback_to_xem is set), otherwise
returns the TVDB numbering. returns the TVDB numbering.
(so the return values will always be set) (so the return values will always be set)
kwargs['scene_result']: type: Optional[List[Row]] passed thru
kwargs['show_result']: type: Optional[List[Row]] passed thru
:param tvid: tvid :param tvid: tvid
:type tvid: int :type tvid: int
:param prodid: prodid :param prodid: prodid
@ -142,6 +153,8 @@ def get_scene_absolute_numbering(tvid, prodid, absolute_number, season, episode,
:param fallback_to_xem: fallback_to_xem: bool If set (the default), check xem for matches if there is no :param fallback_to_xem: fallback_to_xem: bool If set (the default), check xem for matches if there is no
local scene numbering local scene numbering
:type fallback_to_xem: bool :type fallback_to_xem: bool
:param show_obj:
:type show_obj:
:return: (int, int) a tuple with (season, episode) :return: (int, int) a tuple with (season, episode)
:rtype: Tuple[int, int] or None :rtype: Tuple[int, int] or None
""" """
@ -156,18 +169,20 @@ def get_scene_absolute_numbering(tvid, prodid, absolute_number, season, episode,
if show_obj and not show_obj.is_scene and not has_sxe: if show_obj and not show_obj.is_scene and not has_sxe:
return absolute_number return absolute_number
result = find_scene_absolute_numbering(tvid, prodid, absolute_number, season, episode, scene_sql=scene_sql) result = find_scene_absolute_numbering(tvid, prodid, absolute_number, season, episode,
scene_result=kwargs.get('scene_result'))
if result: if result:
return result return result
else:
if fallback_to_xem: if fallback_to_xem:
xem_result = find_xem_absolute_numbering(tvid, prodid, absolute_number, season, episode, show_sql=show_sql) xem_result = find_xem_absolute_numbering(tvid, prodid, absolute_number, season, episode,
if xem_result: show_result=kwargs.get('show_result'))
return xem_result if xem_result:
return absolute_number return xem_result
return absolute_number
def find_scene_absolute_numbering(tvid, prodid, absolute_number, season=None, episode=None, scene_sql=None): def find_scene_absolute_numbering(tvid, prodid, absolute_number, season=None, episode=None, scene_result=None):
""" """
Same as get_scene_numbering(), but returns None if scene numbering is not set Same as get_scene_numbering(), but returns None if scene numbering is not set
@ -181,6 +196,8 @@ def find_scene_absolute_numbering(tvid, prodid, absolute_number, season=None, ep
:type season: int :type season: int
:param episode: :param episode:
:type episode: int :type episode: int
:param scene_result:
:type scene_result:
:return: :return:
:rtype: None or int :rtype: None or int
""" """
@ -190,26 +207,26 @@ def find_scene_absolute_numbering(tvid, prodid, absolute_number, season=None, ep
tvid, prodid = int(tvid), int(prodid) tvid, prodid = int(tvid), int(prodid)
rows = None sql_result = None
if None is not scene_sql: if None is not scene_result:
for e in scene_sql: for cur_row in scene_result:
if e['season'] == season and e['episode'] == episode: if cur_row['season'] == season and cur_row['episode'] == episode:
if e['scene_absolute_number']: if cur_row['scene_absolute_number']:
rows = [e] sql_result = [cur_row]
break break
else: else:
my_db = db.DBConnection() my_db = db.DBConnection()
sql_vars, cond = (([absolute_number], 'AND absolute_number = ?'), sql_vars, cond = (([absolute_number], 'absolute_number = ?'),
([season, episode], 'AND season = ? AND episode = ?'))[has_sxe] ([season, episode], 'season = ? AND episode = ?'))[has_sxe]
rows = my_db.select( sql_result = my_db.select(
'SELECT scene_absolute_number' """
' FROM scene_numbering' SELECT scene_absolute_number
' WHERE indexer = ? AND indexer_id = ?' FROM scene_numbering
' %s AND scene_absolute_number != 0' % cond, WHERE indexer = ? AND indexer_id = ? AND %s AND scene_absolute_number != 0
[tvid, prodid] + sql_vars) """ % cond, [tvid, prodid] + sql_vars)
if rows: if sql_result:
return try_int(rows[0]['scene_absolute_number'], None) return try_int(sql_result[0]['scene_absolute_number'], None)
def get_indexer_numbering(tvid, prodid, scene_season, scene_episode, fallback_to_xem=True): def get_indexer_numbering(tvid, prodid, scene_season, scene_episode, fallback_to_xem=True):
@ -235,15 +252,15 @@ def get_indexer_numbering(tvid, prodid, scene_season, scene_episode, fallback_to
tvid, prodid = int(tvid), int(prodid) tvid, prodid = int(tvid), int(prodid)
my_db = db.DBConnection() my_db = db.DBConnection()
rows = my_db.select( sql_result = my_db.select(
'SELECT season, episode' """
' FROM scene_numbering' SELECT season, episode
' WHERE indexer = ? AND indexer_id = ?' FROM scene_numbering
' AND scene_season = ? AND scene_episode = ?', WHERE indexer = ? AND indexer_id = ? AND scene_season = ? AND scene_episode = ?
[tvid, prodid, scene_season, scene_episode]) """, [tvid, prodid, scene_season, scene_episode])
if rows: if sql_result:
ss, se = try_int(rows[0]['season'], None), try_int(rows[0]['episode'], None) ss, se = try_int(sql_result[0]['season'], None), try_int(sql_result[0]['episode'], None)
if None is not ss and None is not se: if None is not ss and None is not se:
return ss, se return ss, se
if fallback_to_xem: if fallback_to_xem:
@ -274,23 +291,19 @@ def get_indexer_absolute_numbering(tvid, prodid, scene_absolute_number, fallback
tvid, prodid = int(tvid), int(prodid) tvid, prodid = int(tvid), int(prodid)
my_db = db.DBConnection() my_db = db.DBConnection()
if None is scene_season:
rows = my_db.select( sql = """
'SELECT absolute_number' SELECT absolute_number
' FROM scene_numbering' FROM scene_numbering
' WHERE indexer = ? AND indexer_id = ?' WHERE indexer = ? AND indexer_id = ? AND scene_absolute_number = ?
' AND scene_absolute_number = ?', """
[tvid, prodid, scene_absolute_number]) params = [tvid, prodid, scene_absolute_number]
else: if None is not scene_season:
rows = my_db.select( sql += ' AND scene_season = ?'
'SELECT absolute_number' params += [scene_season]
' FROM scene_numbering'
' WHERE indexer = ? AND indexer_id = ?' for cur_row in (my_db.select(sql, params) or []):
' AND scene_absolute_number = ? AND scene_season = ?', an = try_int(cur_row['absolute_number'], None)
[tvid, prodid, scene_absolute_number, scene_season])
if rows:
an = try_int(rows[0]['absolute_number'], None)
if None is not an: if None is not an:
return an return an
if fallback_to_xem: if fallback_to_xem:
@ -329,60 +342,64 @@ def set_scene_numbering(tvid=None, prodid=None, season=None, episode=None, absol
my_db = db.DBConnection() my_db = db.DBConnection()
if None is not season and None is not episode: if None is not season and None is not episode:
my_db.action( my_db.action(
'INSERT OR IGNORE INTO scene_numbering' """
' (indexer, indexer_id, season, episode) VALUES (?,?,?,?)', INSERT OR IGNORE INTO scene_numbering
[tvid, prodid, season, episode]) (indexer, indexer_id, season, episode) VALUES (?,?,?,?)
""", [tvid, prodid, season, episode])
# sxe replaced abs_num as key, migrate data with only abs # sxe replaced abs_num as key, migrate data with only abs
_, _, ep_absolute_number = _get_sea(tvid, prodid, season, episode) _, _, ep_absolute_number = _get_sea(tvid, prodid, season, episode)
rows = my_db.select( sql_result = my_db.select(
'SELECT scene_season, scene_episode, scene_absolute_number' """
' FROM scene_numbering' SELECT scene_season, scene_episode, scene_absolute_number
' WHERE indexer = ? AND indexer_id = ?' FROM scene_numbering
' AND season IS NULL AND episode IS NULL AND absolute_number = ?', WHERE indexer = ? AND indexer_id = ? AND season IS NULL AND episode IS NULL AND absolute_number = ?
[tvid, prodid, ep_absolute_number]) """, [tvid, prodid, ep_absolute_number])
if not len(rows): if not len(sql_result):
update, values = (('scene_absolute_number = ?', [scene_absolute]), update, values = (('scene_absolute_number = ?', [scene_absolute]),
('scene_season = ?, scene_episode = ?', [scene_season, scene_episode]))[not anime] ('scene_season = ?, scene_episode = ?', [scene_season, scene_episode]))[not anime]
else: else:
for row in rows: for cur_row in sql_result:
scene_season = scene_season or row['scene_season'] scene_season = scene_season or cur_row['scene_season']
scene_episode = scene_episode or row['scene_episode'] scene_episode = scene_episode or cur_row['scene_episode']
scene_absolute = scene_absolute or row['scene_absolute_number'] scene_absolute = scene_absolute or cur_row['scene_absolute_number']
update, values = ('scene_season = ?, scene_episode = ?, scene_absolute_number = ?', update, values = ('scene_season = ?, scene_episode = ?, scene_absolute_number = ?',
[scene_season, scene_episode, scene_absolute]) [scene_season, scene_episode, scene_absolute])
my_db.action( my_db.action(
'UPDATE scene_numbering' """
' SET %s' % update + UPDATE scene_numbering
' WHERE indexer = ? AND indexer_id = ?' SET %s
' AND season = ? AND episode = ?', WHERE indexer = ? AND indexer_id = ?
values + [tvid, prodid, season, episode]) AND season = ? AND episode = ?
""" % update, values + [tvid, prodid, season, episode])
my_db.action( my_db.action(
'DELETE' """
' FROM scene_numbering' DELETE
' WHERE indexer = ? AND indexer_id = ?' FROM scene_numbering
' AND ((absolute_number = ? OR (season = ? AND episode = ?))' WHERE indexer = ? AND indexer_id = ?
' AND scene_season IS NULL AND scene_episode IS NULL AND scene_absolute_number IS NULL)', AND ((absolute_number = ? OR (season = ? AND episode = ?))
[tvid, prodid, ep_absolute_number, season, episode]) AND scene_season IS NULL AND scene_episode IS NULL AND scene_absolute_number IS NULL)
""", [tvid, prodid, ep_absolute_number, season, episode])
elif absolute_number: elif absolute_number:
my_db.action( my_db.action(
'INSERT OR IGNORE INTO scene_numbering' """
' (indexer, indexer_id, absolute_number) VALUES (?,?,?)', INSERT OR IGNORE INTO scene_numbering
[tvid, prodid, absolute_number]) (indexer, indexer_id, absolute_number) VALUES (?,?,?)
""", [tvid, prodid, absolute_number])
my_db.action( my_db.action(
'UPDATE scene_numbering' """
' SET scene_absolute_number = ?' UPDATE scene_numbering
' WHERE indexer = ? AND indexer_id = ?' SET scene_absolute_number = ?
' AND absolute_number = ?', WHERE indexer = ? AND indexer_id = ? AND absolute_number = ?
[scene_absolute, tvid, prodid, absolute_number]) """, [scene_absolute, tvid, prodid, absolute_number])
def find_xem_numbering(tvid, prodid, season, episode, show_sql=None): def find_xem_numbering(tvid, prodid, season, episode, show_result=None):
""" """
Returns the scene numbering, as retrieved from xem. Returns the scene numbering, as retrieved from xem.
Refreshes/Loads as needed. Refreshes/Loads as needed.
@ -395,6 +412,8 @@ def find_xem_numbering(tvid, prodid, season, episode, show_sql=None):
:type season: int :type season: int
:param episode: :param episode:
:type episode: int :type episode: int
:param show_result:
:type show_result:
:return: :return:
:rtype: (int, int) a tuple of scene_season, scene_episode, or None if there is no special mapping. :rtype: (int, int) a tuple of scene_season, scene_episode, or None if there is no special mapping.
""" """
@ -405,29 +424,27 @@ def find_xem_numbering(tvid, prodid, season, episode, show_sql=None):
xem_refresh(tvid, prodid) xem_refresh(tvid, prodid)
rows = None sql_result = None
if None is not show_sql: if None is not show_result:
for e in show_sql: if isinstance(show_result, Row) and (season, episode) == (show_result['season'], show_result['episode']) \
if e['season'] == season and e['episode'] == episode: and (show_result['scene_season'] or show_result['scene_episode']):
if e['scene_season'] or e['scene_episode']: sql_result = [show_result]
rows = [e]
break
else: else:
my_db = db.DBConnection() my_db = db.DBConnection()
rows = my_db.select( sql_result = my_db.select(
'SELECT scene_season, scene_episode' """
' FROM tv_episodes' SELECT scene_season, scene_episode
' WHERE indexer = ? AND showid = ?' FROM tv_episodes
' AND season = ? AND episode = ? AND (scene_season OR scene_episode) != 0', WHERE indexer = ? AND showid = ? AND season = ? AND episode = ? AND (scene_season OR scene_episode) != 0
[tvid, prodid, season, episode]) """, [tvid, prodid, season, episode])
if rows: if sql_result:
s_s, s_e = try_int(rows[0]['scene_season'], None), try_int(rows[0]['scene_episode'], None) s_s, s_e = try_int(sql_result[0]['scene_season'], None), try_int(sql_result[0]['scene_episode'], None)
if None is not s_s and None is not s_e: if None is not s_s and None is not s_e:
return s_s, s_e return s_s, s_e
def find_xem_absolute_numbering(tvid, prodid, absolute_number, season, episode, show_sql=None): def find_xem_absolute_numbering(tvid, prodid, absolute_number, season, episode, show_result=None):
""" """
Returns the scene numbering, as retrieved from xem. Returns the scene numbering, as retrieved from xem.
Refreshes/Loads as needed. Refreshes/Loads as needed.
@ -442,6 +459,8 @@ def find_xem_absolute_numbering(tvid, prodid, absolute_number, season, episode,
:type season: int :type season: int
:param episode: :param episode:
:type episode: int :type episode: int
:param show_result:
:type show_result:
:return: :return:
:rtype: int :rtype: int
""" """
@ -452,24 +471,22 @@ def find_xem_absolute_numbering(tvid, prodid, absolute_number, season, episode,
xem_refresh(tvid, prodid) xem_refresh(tvid, prodid)
rows = None sql_result = None
if None is not show_sql: if None is not show_result:
for e in show_sql: if isinstance(show_result, Row) and (season, episode) == (show_result['season'], show_result['episode']) \
if e['season'] == season and e['episode'] == episode: and show_result['scene_absolute_number']:
if e['scene_absolute_number']: sql_result = [show_result]
rows = [e]
break
else: else:
my_db = db.DBConnection() my_db = db.DBConnection()
rows = my_db.select( sql_result = my_db.select(
'SELECT scene_absolute_number' """
' FROM tv_episodes' SELECT scene_absolute_number
' WHERE indexer = ? AND showid = ?' FROM tv_episodes
' AND season = ? AND episode = ? AND scene_absolute_number != 0', WHERE indexer = ? AND showid = ? AND season = ? AND episode = ? AND scene_absolute_number != 0
[tvid, prodid, season, episode]) """, [tvid, prodid, season, episode])
if rows: if sql_result:
return try_int(rows[0]['scene_absolute_number'], None) return try_int(sql_result[0]['scene_absolute_number'], None)
def get_indexer_numbering_for_xem(tvid, prodid, scene_season, scene_episode): def get_indexer_numbering_for_xem(tvid, prodid, scene_season, scene_episode):
@ -495,17 +512,18 @@ def get_indexer_numbering_for_xem(tvid, prodid, scene_season, scene_episode):
xem_refresh(tvid, prodid) xem_refresh(tvid, prodid)
my_db = db.DBConnection() my_db = db.DBConnection()
rows = my_db.select( sql_result = my_db.select(
'SELECT season, episode' """
' FROM tv_episodes' SELECT season, episode
' WHERE indexer = ? AND showid = ?' FROM tv_episodes
' AND scene_season = ? AND scene_episode = ?', WHERE indexer = ? AND showid = ? AND scene_season = ? AND scene_episode = ?
[tvid, prodid, scene_season, scene_episode]) """, [tvid, prodid, scene_season, scene_episode])
if rows: for cur_row in (sql_result or []):
ss, se = try_int(rows[0]['season'], None), try_int(rows[0]['episode'], None) ss, se = try_int(cur_row['season'], None), try_int(cur_row['episode'], None)
if None is not ss and None is not se: if None is not ss and None is not se:
return ss, se return ss, se
break
return scene_season, scene_episode return scene_season, scene_episode
@ -533,25 +551,21 @@ def get_indexer_absolute_numbering_for_xem(tvid, prodid, scene_absolute_number,
xem_refresh(tvid, prodid) xem_refresh(tvid, prodid)
my_db = db.DBConnection() my_db = db.DBConnection()
if None is scene_season: sql = """
rows = my_db.select( SELECT absolute_number
'SELECT absolute_number' FROM tv_episodes
' FROM tv_episodes' WHERE indexer = ? AND showid = ? AND scene_absolute_number = ?
' WHERE indexer = ? AND showid = ?' """
' AND scene_absolute_number = ?', params = [tvid, prodid, scene_absolute_number]
[tvid, prodid, scene_absolute_number]) if None is not scene_season:
else: sql += ' AND scene_season = ?'
rows = my_db.select( params += [scene_season]
'SELECT absolute_number'
' FROM tv_episodes' for cur_row in (my_db.select(sql, params) or []):
' WHERE indexer = ? AND showid = ?' an = try_int(cur_row['absolute_number'], None)
' AND scene_absolute_number = ? AND scene_season = ?',
[tvid, prodid, scene_absolute_number, scene_season])
if rows:
an = try_int(rows[0]['absolute_number'], None)
if None is not an: if None is not an:
return an return an
break
return scene_absolute_number return scene_absolute_number
@ -620,18 +634,19 @@ def _get_numbering_for_show(tbl, tvid, prodid):
my_db = db.DBConnection() my_db = db.DBConnection()
# noinspection SqlResolve # noinspection SqlResolve
rows = my_db.select( sql_result = my_db.select(
'SELECT season, episode, scene_season, scene_episode' """
' FROM %s' % tbl + SELECT season, episode, scene_season, scene_episode
' WHERE indexer = ? AND %s = ?' % ('indexer_id', 'showid')['tv_episodes' == tbl] + FROM %s
' AND (scene_season OR scene_episode) != 0' WHERE indexer = ? AND %s = ? AND (scene_season OR scene_episode) != 0
' ORDER BY season, episode', ORDER BY season, episode
[int(tvid), int(prodid)]) """ % (tbl, ('indexer_id', 'showid')['tv_episodes' == tbl]), [int(tvid), int(prodid)])
for row in rows: for cur_row in sql_result:
season, episode = try_int(row['season'], None), try_int(row['episode'], None) season, episode = try_int(cur_row['season'], None), try_int(cur_row['episode'], None)
if None is not season and None is not episode: if None is not season and None is not episode:
scene_season, scene_episode = try_int(row['scene_season'], None), try_int(row['scene_episode'], None) scene_season, scene_episode = try_int(cur_row['scene_season'], None), \
try_int(cur_row['scene_episode'], None)
if None is not scene_season and None is not scene_episode: if None is not scene_season and None is not scene_episode:
result[(season, episode)] = (scene_season, scene_episode) result[(season, episode)] = (scene_season, scene_episode)
@ -686,22 +701,22 @@ def _get_absolute_numbering_for_show(tbl, tvid, prodid):
my_db = db.DBConnection() my_db = db.DBConnection()
# noinspection SqlResolve # noinspection SqlResolve
rows = my_db.select( sql_result = my_db.select(
'SELECT season, episode, absolute_number, scene_absolute_number' """
' FROM %s' % tbl + SELECT season, episode, absolute_number, scene_absolute_number
' WHERE indexer = ? AND %s = ?' % ('indexer_id', 'showid')['tv_episodes' == tbl] + FROM %s
' AND scene_absolute_number != 0' WHERE indexer = ? AND %s = ? AND scene_absolute_number != 0
' ORDER BY season, episode', ORDER BY season, episode
[int(tvid), int(prodid)]) """ % (tbl, ('indexer_id', 'showid')['tv_episodes' == tbl]), [int(tvid), int(prodid)])
for row in rows: for cur_row in sql_result:
season, episode, abs_num = map_list(lambda x: try_int(row[x], None), season, episode, abs_num = map_list(lambda x: try_int(cur_row[x], None),
('season', 'episode', 'absolute_number')) ('season', 'episode', 'absolute_number'))
if None is season and None is episode and None is not abs_num: if None is season and None is episode and None is not abs_num:
season, episode, _ = _get_sea(tvid, prodid, absolute_number=abs_num) season, episode, _ = _get_sea(tvid, prodid, absolute_number=abs_num)
if None is not season and None is not episode: if None is not season and None is not episode:
scene_absolute_number = try_int(row['scene_absolute_number'], None) scene_absolute_number = try_int(cur_row['scene_absolute_number'], None)
if None is not scene_absolute_number: if None is not scene_absolute_number:
result[(season, episode)] = scene_absolute_number result[(season, episode)] = scene_absolute_number
@ -759,18 +774,20 @@ def xem_refresh(tvid, prodid, force=False):
xem_origin = tvinfo.config['xem_origin'] xem_origin = tvinfo.config['xem_origin']
# XEM API URL # XEM API URL
# noinspection HttpUrlsUsage
url = 'http://thexem.de/map/all?id=%s&origin=%s&destination=scene' % (prodid, xem_origin) url = 'http://thexem.de/map/all?id=%s&origin=%s&destination=scene' % (prodid, xem_origin)
max_refresh_age_secs = 86400 # 1 day max_refresh_age_secs = 86400 # 1 day
my_db = db.DBConnection() my_db = db.DBConnection()
rows = my_db.select( sql_result = my_db.select(
'SELECT last_refreshed' """
' FROM xem_refresh' SELECT last_refreshed
' WHERE indexer = ? AND indexer_id = ?', FROM xem_refresh
[tvid, prodid]) WHERE indexer = ? AND indexer_id = ?
if rows: """, [tvid, prodid])
last_refresh = int(rows[0]['last_refreshed']) if sql_result:
last_refresh = int(sql_result[0]['last_refreshed'])
refresh = int(timestamp_near(datetime.datetime.now())) > last_refresh + max_refresh_age_secs refresh = int(timestamp_near(datetime.datetime.now())) > last_refresh + max_refresh_age_secs
else: else:
refresh = True refresh = True
@ -791,17 +808,14 @@ def xem_refresh(tvid, prodid, force=False):
if 'success' in parsed_json['result']: if 'success' in parsed_json['result']:
cl = map_list(lambda entry: [ cl = map_list(lambda entry: [
'UPDATE tv_episodes' """
' SET scene_season = ?, scene_episode = ?, scene_absolute_number = ?' UPDATE tv_episodes
' WHERE indexer = ? AND showid = ?' SET scene_season = ?, scene_episode = ?, scene_absolute_number = ?
' AND season = ? AND episode = ?', WHERE indexer = ? AND showid = ? AND season = ? AND episode = ?
[entry """, [entry.get('scene%s' % ('', '_2')['scene_2' in entry]).get(v)
.get('scene%s' % ('', '_2')['scene_2' in entry]) for v in ('season', 'episode', 'absolute')]
.get(v) for v in ('season', 'episode', 'absolute')] + + [tvid, prodid]
[tvid, prodid] + + [entry.get(xem_origin).get(v) for v in ('season', 'episode')]
[entry
.get(xem_origin)
.get(v) for v in ('season', 'episode')]
], filter_iter(lambda x: 'scene' in x, parsed_json['data'])) ], filter_iter(lambda x: 'scene' in x, parsed_json['data']))
if 0 < len(cl): if 0 < len(cl):
@ -829,11 +843,12 @@ def fix_xem_numbering(tvid, prodid):
tvid, prodid = int(tvid), int(prodid) tvid, prodid = int(tvid), int(prodid)
my_db = db.DBConnection() my_db = db.DBConnection()
rows = my_db.select( sql_result = my_db.select(
'SELECT season, episode, absolute_number, scene_season, scene_episode, scene_absolute_number' """
' FROM tv_episodes' SELECT season, episode, absolute_number, scene_season, scene_episode, scene_absolute_number
' WHERE indexer = ? AND showid = ?', FROM tv_episodes
[tvid, prodid]) WHERE indexer = ? AND showid = ?
""", [tvid, prodid])
last_absolute_number = None last_absolute_number = None
last_scene_season = None last_scene_season = None
@ -850,43 +865,43 @@ def fix_xem_numbering(tvid, prodid):
logger.DEBUG) logger.DEBUG)
cl = [] cl = []
for row in rows: for cur_row in sql_result:
season = int(row['season']) season = int(cur_row['season'])
episode = int(row['episode']) episode = int(cur_row['episode'])
if not int(row['scene_season']) and last_scene_season: if not int(cur_row['scene_season']) and last_scene_season:
scene_season = last_scene_season + 1 scene_season = last_scene_season + 1
update_scene_season = True update_scene_season = True
else: else:
scene_season = int(row['scene_season']) scene_season = int(cur_row['scene_season'])
if last_scene_season and scene_season < last_scene_season: if last_scene_season and scene_season < last_scene_season:
scene_season = last_scene_season + 1 scene_season = last_scene_season + 1
update_scene_season = True update_scene_season = True
if not int(row['scene_episode']) and last_scene_episode: if not int(cur_row['scene_episode']) and last_scene_episode:
scene_episode = last_scene_episode + 1 scene_episode = last_scene_episode + 1
update_scene_episode = True update_scene_episode = True
else: else:
scene_episode = int(row['scene_episode']) scene_episode = int(cur_row['scene_episode'])
if last_scene_episode and scene_episode < last_scene_episode: if last_scene_episode and scene_episode < last_scene_episode:
scene_episode = last_scene_episode + 1 scene_episode = last_scene_episode + 1
update_scene_episode = True update_scene_episode = True
# check for unset values and correct them # check for unset values and correct them
if not int(row['absolute_number']) and last_absolute_number: if not int(cur_row['absolute_number']) and last_absolute_number:
absolute_number = last_absolute_number + 1 absolute_number = last_absolute_number + 1
update_absolute_number = True update_absolute_number = True
else: else:
absolute_number = int(row['absolute_number']) absolute_number = int(cur_row['absolute_number'])
if last_absolute_number and absolute_number < last_absolute_number: if last_absolute_number and absolute_number < last_absolute_number:
absolute_number = last_absolute_number + 1 absolute_number = last_absolute_number + 1
update_absolute_number = True update_absolute_number = True
if not int(row['scene_absolute_number']) and last_scene_absolute_number: if not int(cur_row['scene_absolute_number']) and last_scene_absolute_number:
scene_absolute_number = last_scene_absolute_number + 1 scene_absolute_number = last_scene_absolute_number + 1
update_scene_absolute_number = True update_scene_absolute_number = True
else: else:
scene_absolute_number = int(row['scene_absolute_number']) scene_absolute_number = int(cur_row['scene_absolute_number'])
if last_scene_absolute_number and scene_absolute_number < last_scene_absolute_number: if last_scene_absolute_number and scene_absolute_number < last_scene_absolute_number:
scene_absolute_number = last_scene_absolute_number + 1 scene_absolute_number = last_scene_absolute_number + 1
update_scene_absolute_number = True update_scene_absolute_number = True
@ -899,51 +914,42 @@ def fix_xem_numbering(tvid, prodid):
if update_absolute_number: if update_absolute_number:
cl.append([ cl.append([
'UPDATE tv_episodes' """
' SET absolute_number = ?' UPDATE tv_episodes
' WHERE indexer = ? AND showid = ?' SET absolute_number = ?
' AND season = ? AND episode = ?', WHERE indexer = ? AND showid = ? AND season = ? AND episode = ?
[absolute_number, """, [absolute_number, tvid, prodid, season, episode]
tvid, prodid, ])
season, episode
]])
update_absolute_number = False update_absolute_number = False
if update_scene_season: if update_scene_season:
cl.append([ cl.append([
'UPDATE tv_episodes' """
' SET scene_season = ?' UPDATE tv_episodes
' WHERE indexer = ? AND showid = ?' SET scene_season = ?
' AND season = ? AND episode = ?', WHERE indexer = ? AND showid = ? AND season = ? AND episode = ?
[scene_season, """, [scene_season, tvid, prodid, season, episode]
tvid, prodid, ])
season, episode
]])
update_scene_season = False update_scene_season = False
if update_scene_episode: if update_scene_episode:
cl.append([ cl.append([
'UPDATE tv_episodes' """
' SET scene_episode = ?' UPDATE tv_episodes
' WHERE indexer = ? AND showid = ?' SET scene_episode = ?
' AND season = ? AND episode = ?', WHERE indexer = ? AND showid = ? AND season = ? AND episode = ?
[scene_episode, """, [scene_episode, tvid, prodid, season, episode]
tvid, prodid, ])
season,
episode
]])
update_scene_episode = False update_scene_episode = False
if update_scene_absolute_number: if update_scene_absolute_number:
cl.append([ cl.append([
'UPDATE tv_episodes' """
' SET scene_absolute_number = ?' UPDATE tv_episodes
' WHERE indexer = ? AND showid = ?' SET scene_absolute_number = ?
' AND season = ? AND episode = ?', WHERE indexer = ? AND showid = ? AND season = ? AND episode = ?
[scene_absolute_number, """, [scene_absolute_number, tvid, prodid, season, episode]
tvid, prodid, ])
season, episode
]])
update_scene_absolute_number = False update_scene_absolute_number = False
if 0 < len(cl): if 0 < len(cl):

2
sickbeard/search.py

@ -547,7 +547,7 @@ def wanted_episodes(show_obj, # type: TVShow
ep_sql_result = None ep_sql_result = None
for result in sql_result: for result in sql_result:
ep_obj = show_obj.get_episode(int(result['season']), int(result['episode']), ep_sql=ep_sql_result) ep_obj = show_obj.get_episode(int(result['season']), int(result['episode']), ep_result=ep_sql_result)
cur_status, cur_quality = common.Quality.splitCompositeStatus(ep_obj.status) cur_status, cur_quality = common.Quality.splitCompositeStatus(ep_obj.status)
ep_obj.wanted_quality = get_wanted_qualities(ep_obj, cur_status, cur_quality, unaired=unaired) ep_obj.wanted_quality = get_wanted_qualities(ep_obj, cur_status, cur_quality, unaired=unaired)
if not ep_obj.wanted_quality: if not ep_obj.wanted_quality:

6
sickbeard/search_queue.py

@ -102,7 +102,7 @@ class SearchQueue(generic_queue.GenericQueue):
return [ return [
['INSERT OR IGNORE INTO search_queue (indexer, indexer_id, segment, standard_backlog, limited_backlog,' ['INSERT OR IGNORE INTO search_queue (indexer, indexer_id, segment, standard_backlog, limited_backlog,'
' forced, torrent_only, action_id, uid) VALUES (?,?,?,?,?,?,?,?,?)', ' forced, torrent_only, action_id, uid) VALUES (?,?,?,?,?,?,?,?,?)',
[item.show_obj._tvid, item.show_obj._prodid, [item.show_obj.tvid, item.show_obj.prodid,
','.join('%sx%s' % (i.season, i.episode) for i in item.segment), int(item.standard_backlog), ','.join('%sx%s' % (i.season, i.episode) for i in item.segment), int(item.standard_backlog),
int(item.limited_backlog), int(item.forced), int(item.torrent_only), BACKLOG_SEARCH, item.uid]] int(item.limited_backlog), int(item.forced), int(item.torrent_only), BACKLOG_SEARCH, item.uid]]
] ]
@ -110,14 +110,14 @@ class SearchQueue(generic_queue.GenericQueue):
return [ return [
['INSERT OR IGNORE INTO search_queue (indexer, indexer_id, segment, action_id, uid)' ['INSERT OR IGNORE INTO search_queue (indexer, indexer_id, segment, action_id, uid)'
' VALUES (?,?,?,?,?)', ' VALUES (?,?,?,?,?)',
[item.show_obj._tvid, item.show_obj._prodid, [item.show_obj.tvid, item.show_obj.prodid,
','.join('%sx%s' % (i.season, i.episode) for i in item.segment), FAILED_SEARCH, item.uid]] ','.join('%sx%s' % (i.season, i.episode) for i in item.segment), FAILED_SEARCH, item.uid]]
] ]
elif isinstance(item, ManualSearchQueueItem): elif isinstance(item, ManualSearchQueueItem):
return [ return [
['INSERT OR IGNORE INTO search_queue (indexer, indexer_id, segment, action_id, uid)' ['INSERT OR IGNORE INTO search_queue (indexer, indexer_id, segment, action_id, uid)'
' VALUES (?,?,?,?,?)', ' VALUES (?,?,?,?,?)',
[item.show_obj._tvid, item.show_obj._prodid, '%sx%s' % (item.segment.season, item.segment.episode), [item.show_obj.tvid, item.show_obj.prodid, '%sx%s' % (item.segment.season, item.segment.episode),
MANUAL_SEARCH, item.uid]] MANUAL_SEARCH, item.uid]]
] ]
return [] return []

291
sickbeard/show_queue.py

@ -81,39 +81,55 @@ class ShowQueue(generic_queue.GenericQueue):
def load_queue(self): def load_queue(self):
try: try:
my_db = db.DBConnection('cache.db') my_db = db.DBConnection('cache.db')
queue_sql = my_db.select('SELECT * FROM show_queue') sql_result = my_db.select('SELECT * FROM show_queue')
for q in queue_sql: for cur_row in sql_result:
if ShowQueueActions.ADD != q['action_id']: show_obj = None
if ShowQueueActions.ADD != cur_row['action_id']:
try: try:
show_obj = find_show_by_id({q['tvid']: q['prodid']}) show_obj = find_show_by_id({cur_row['tvid']: cur_row['prodid']})
except (BaseException, Exception): except (BaseException, Exception):
continue continue
if not show_obj: if not show_obj:
continue continue
if q['action_id'] in (ShowQueueActions.UPDATE, ShowQueueActions.FORCEUPDATE,
ShowQueueActions.WEBFORCEUPDATE): if cur_row['action_id'] in (ShowQueueActions.UPDATE, ShowQueueActions.FORCEUPDATE,
self.updateShow(show_obj=show_obj, force=bool(q['force']), ShowQueueActions.WEBFORCEUPDATE):
web=ShowQueueActions.WEBFORCEUPDATE == q['action_id'], self.updateShow(add_to_db=False, force=bool(cur_row['force']),
scheduled_update=bool(q['scheduled_update']), skip_refresh=bool(q['skip_refresh']), pausestatus_after=bool_none(cur_row['pausestatus_after']),
pausestatus_after=bool_none(q['pausestatus_after']), uid=q['uid'], add_to_db=False) scheduled_update=bool(cur_row['scheduled_update']),
elif ShowQueueActions.REFRESH == q['action_id']: show_obj=show_obj, skip_refresh=bool(cur_row['skip_refresh']),
self.refreshShow(show_obj=show_obj, force=bool(q['force']), uid=cur_row['uid'],
scheduled_update=bool(q['scheduled_update']), priority=q['priority'], web=ShowQueueActions.WEBFORCEUPDATE == cur_row['action_id'])
force_image_cache=bool(q['force_image_cache']), uid=q['uid'], add_to_db=False)
elif ShowQueueActions.RENAME == q['action_id']: elif ShowQueueActions.REFRESH == cur_row['action_id']:
self.renameShowEpisodes(show_obj=show_obj, uid=q['uid'], add_to_db=False) self.refreshShow(add_to_db=False, force=bool(cur_row['force']),
elif ShowQueueActions.SUBTITLE == q['action_id']: force_image_cache=bool(cur_row['force_image_cache']),
self.download_subtitles(show_obj=show_obj, uid=q['uid'], add_to_db=False) priority=cur_row['priority'],
elif ShowQueueActions.ADD == q['action_id']: scheduled_update=bool(cur_row['scheduled_update']),
self.addShow(tvid=q['tvid'], prodid=q['prodid'], show_dir=q['show_dir'], show_obj=show_obj,
default_status=q['default_status'], quality=q['quality'], uid=cur_row['uid'])
flatten_folders=bool_none(q['flatten_folders']), lang=q['lang'],
subtitles=q['subtitles'], anime=bool_none(q['anime']), scene=bool_none(q['scene']), elif ShowQueueActions.RENAME == cur_row['action_id']:
paused=bool_none(q['paused']), blocklist=q['blocklist'], allowlist=q['allowlist'], self.renameShowEpisodes(add_to_db=False, show_obj=show_obj, uid=cur_row['uid'])
wanted_begin=q['wanted_begin'], wanted_latest=q['wanted_latest'],
prune=q['prune'], tag=q['tag'], new_show=bool(q['new_show']), elif ShowQueueActions.SUBTITLE == cur_row['action_id']:
show_name=q['show_name'], upgrade_once=bool(q['upgrade_once']), uid=q['uid'], self.download_subtitles(add_to_db=False, show_obj=show_obj, uid=cur_row['uid'])
add_to_db=False)
elif ShowQueueActions.ADD == cur_row['action_id']:
self.addShow(tvid=cur_row['tvid'], prodid=cur_row['prodid'],
add_to_db=False, allowlist=cur_row['allowlist'],
anime=bool_none(cur_row['anime']),
blocklist=cur_row['blocklist'], default_status=cur_row['default_status'],
flatten_folders=bool_none(cur_row['flatten_folders']), lang=cur_row['lang'],
new_show=bool(cur_row['new_show']), paused=bool_none(cur_row['paused']),
prune=cur_row['prune'], quality=cur_row['quality'],
scene=bool_none(cur_row['scene']), show_dir=cur_row['show_dir'],
show_name=cur_row['show_name'], subtitles=cur_row['subtitles'],
tag=cur_row['tag'], uid=cur_row['uid'],
upgrade_once=bool(cur_row['upgrade_once']),
wanted_begin=cur_row['wanted_begin'],
wanted_latest=cur_row['wanted_latest'])
except (BaseException, Exception) as e: except (BaseException, Exception) as e:
logger.log('Exception loading queue %s: %s' % (self.__class__.__name__, ex(e)), logger.ERROR) logger.log('Exception loading queue %s: %s' % (self.__class__.__name__, ex(e)), logger.ERROR)
@ -121,19 +137,20 @@ class ShowQueue(generic_queue.GenericQueue):
# type: (ShowQueueItem) -> None # type: (ShowQueueItem) -> None
if ShowQueueActions.SWITCH == item.action_id: if ShowQueueActions.SWITCH == item.action_id:
my_db = db.DBConnection() my_db = db.DBConnection()
my_db.action('REPLACE INTO tv_src_switch (old_indexer, old_indexer_id, new_indexer,' my_db.action(
' new_indexer_id, action_id, status, uid, mark_wanted, set_pause, force_id)' """
' VALUES (?,?,?,?,?,?,?,?,?,?)', REPLACE INTO tv_src_switch (old_indexer, old_indexer_id, new_indexer, new_indexer_id,
[item.show_obj._tvid, item.show_obj._prodid, item.new_tvid, item.new_prodid, action_id, status, uid, mark_wanted, set_pause, force_id)
ShowQueueActions.SWITCH, 0, item.uid, int(item.mark_wanted), int(item.set_pause), VALUES (?,?,?,?,?,?,?,?,?,?)
int(item.force_id)]) """, [item.show_obj.tvid, item.show_obj.prodid, item.new_tvid, item.new_prodid,
ShowQueueActions.SWITCH, 0, item.uid, int(item.mark_wanted), int(item.set_pause),
int(item.force_id)])
else: else:
generic_queue.GenericQueue.save_item(self, item) generic_queue.GenericQueue.save_item(self, item)
def _clear_sql(self): def _clear_sql(self):
return [ # noinspection SqlWithoutWhere
['DELETE FROM show_queue'] return [['DELETE FROM show_queue']]
]
def _get_item_sql(self, item): def _get_item_sql(self, item):
# type: (ShowQueueItem) -> List[List] # type: (ShowQueueItem) -> List[List]
@ -143,53 +160,62 @@ class ShowQueue(generic_queue.GenericQueue):
pause_status_after = item.kwargs.get('pausestatus_after') pause_status_after = item.kwargs.get('pausestatus_after')
if None is not pause_status_after: if None is not pause_status_after:
pause_status_after = int(pause_status_after) pause_status_after = int(pause_status_after)
return [ return [[
['INSERT OR IGNORE INTO show_queue (tvid, prodid, priority, force, scheduled_update, skip_refresh,' """
' pausestatus_after, action_id, uid) VALUES (?,?,?,?,?,?,?,?,?)', INSERT OR IGNORE INTO show_queue (tvid, prodid, priority, force,
[item.show_obj._tvid, item.show_obj._prodid, item.priority, int(item.force), scheduled_update, skip_refresh, pausestatus_after,
int(item.scheduled_update), int(item.kwargs.get('skip_refresh', False)), pause_status_after, action_id, uid) VALUES (?,?,?,?,?,?,?,?,?)
item.action_id, item.uid]] """, [item.show_obj.tvid, item.show_obj.prodid, item.priority, int(item.force),
] int(item.scheduled_update), int(item.kwargs.get('skip_refresh', False)), pause_status_after,
item.action_id, item.uid]
]]
elif isinstance(item, QueueItemRefresh): elif isinstance(item, QueueItemRefresh):
if item.switch: if item.switch:
return [] return []
pause_status_after = item.kwargs.get('pausestatus_after') pause_status_after = item.kwargs.get('pausestatus_after')
if None is not pause_status_after: if None is not pause_status_after:
pause_status_after = int(pause_status_after) pause_status_after = int(pause_status_after)
return [ return [[
['INSERT OR IGNORE INTO show_queue (tvid, prodid, priority, force, scheduled_update,' """
' force_image_cache, pausestatus_after, action_id, uid) VALUES (?,?,?,?,?,?,?,?,?)', INSERT OR IGNORE INTO show_queue (tvid, prodid, priority, force,
[item.show_obj._tvid, item.show_obj._prodid, item.priority, int(item.force), scheduled_update, force_image_cache, pausestatus_after,
int(item.scheduled_update), int(item.force_image_cache), pause_status_after, action_id, uid) VALUES (?,?,?,?,?,?,?,?,?)
item.action_id, item.uid]] """, [item.show_obj.tvid, item.show_obj.prodid, item.priority, int(item.force),
] int(item.scheduled_update), int(item.force_image_cache), pause_status_after,
item.action_id, item.uid]
]]
elif isinstance(item, QueueItemRename): elif isinstance(item, QueueItemRename):
return [ return [[
['INSERT OR IGNORE INTO show_queue (tvid, prodid, priority, scheduled_update, action_id, uid)' """
' VALUES (?,?,?,?,?,?)', INSERT OR IGNORE INTO show_queue (tvid, prodid, priority, scheduled_update, action_id, uid)
[item.show_obj._tvid, item.show_obj._prodid, item.priority, int(item.scheduled_update), VALUES (?,?,?,?,?,?)
item.action_id, item.uid]] """, [item.show_obj.tvid, item.show_obj.prodid, item.priority, int(item.scheduled_update),
] item.action_id, item.uid]
]]
elif isinstance(item, QueueItemSubtitle): elif isinstance(item, QueueItemSubtitle):
return [ return [[
['INSERT OR IGNORE INTO show_queue (tvid, prodid, priority, scheduled_update, action_id, uid)' """
' VALUES (?,?,?,?,?,?)', INSERT OR IGNORE INTO show_queue (tvid, prodid, priority, scheduled_update, action_id, uid)
[item.show_obj._tvid, item.show_obj._prodid, item.priority, int(item.scheduled_update), VALUES (?,?,?,?,?,?)
item.action_id, item.uid]] """, [item.show_obj.tvid, item.show_obj.prodid, item.priority, int(item.scheduled_update),
] item.action_id, item.uid]
]]
elif isinstance(item, QueueItemAdd): elif isinstance(item, QueueItemAdd):
return [ return [[
['INSERT OR IGNORE INTO show_queue (tvid, prodid, priority, scheduled_update, ' """
' show_dir, default_status, quality, flatten_folders, lang, subtitles, anime,' INSERT OR IGNORE INTO show_queue (tvid, prodid, priority, scheduled_update,
' scene, paused, blocklist, allowlist, wanted_begin, wanted_latest, prune, tag, new_show, show_name,' show_dir, default_status, quality, flatten_folders, lang,
' upgrade_once, action_id, uid) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)', subtitles, anime, scene, paused,
[item.tvid, item.prodid, item.priority, int(item.scheduled_update), item.showDir, blocklist, allowlist, wanted_begin, wanted_latest,
item.default_status, item.quality, try_int(item.flatten_folders, None), item.lang, item.subtitles, prune, tag, new_show, show_name, upgrade_once,
try_int(item.anime, None), try_int(item.scene, None), try_int(item.paused, None), action_id, uid) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)
item.blocklist, item.allowlist, item.default_wanted_begin, item.default_wanted_latest, """, [item.tvid, item.prodid, item.priority, int(item.scheduled_update),
item.prune, item.tag, int(item.new_show), item.show_name, int(item.upgrade_once), item.showDir, item.default_status, item.quality, try_int(item.flatten_folders, None), item.lang,
item.action_id, item.uid]] item.subtitles, try_int(item.anime, None), try_int(item.scene, None), try_int(item.paused, None),
] item.blocklist, item.allowlist, item.default_wanted_begin, item.default_wanted_latest,
item.prune, item.tag, int(item.new_show), item.show_name, int(item.upgrade_once),
item.action_id, item.uid]
]]
return [] return []
def delete_item(self, item, finished_run=False): def delete_item(self, item, finished_run=False):
@ -407,10 +433,10 @@ class ShowQueue(generic_queue.GenericQueue):
length['add'].append(result_item) length['add'].append(result_item)
else: else:
result_item.update({ result_item.update({
'tvid': cur_item.show_obj._tvid, 'tvid': cur_item.show_obj.tvid,
'prodid': cur_item.show_obj._prodid, 'tvid_prodid': cur_item.show_obj.tvid_prodid, 'prodid': cur_item.show_obj.prodid, 'tvid_prodid': cur_item.show_obj.tvid_prodid,
# legacy keys for api responses # legacy keys for api responses
'indexer': cur_item.show_obj._tvid, 'indexerid': cur_item.show_obj._prodid}) 'indexer': cur_item.show_obj.tvid, 'indexerid': cur_item.show_obj.prodid})
if isinstance(cur_item, QueueItemUpdate): if isinstance(cur_item, QueueItemUpdate):
update_type = 'Normal' update_type = 'Normal'
if isinstance(cur_item, QueueItemForceUpdate): if isinstance(cur_item, QueueItemForceUpdate):
@ -433,9 +459,16 @@ class ShowQueue(generic_queue.GenericQueue):
loadingShowList = property(_getLoadingShowList) loadingShowList = property(_getLoadingShowList)
def updateShow(self, show_obj, force=False, web=False, scheduled_update=False, def updateShow(self,
priority=generic_queue.QueuePriorities.NORMAL, uid=None, add_to_db=True, **kwargs): show_obj, # type: TVShow
# type: (TVShow, bool, bool, bool, integer_types, integer_types, bool, Any) -> Union[QueueItemUpdate, QueueItemForceUpdate, QueueItemForceUpdateWeb] force=False, # type: bool
web=False, # type: bool
scheduled_update=False, # type: bool
priority=generic_queue.QueuePriorities.NORMAL, # type: integer_types
uid=None, # type: integer_types
add_to_db=True, # type: bool
**kwargs # type: Any
): # type: (...) -> Union[QueueItemUpdate, QueueItemForceUpdate, QueueItemForceUpdateWeb]
""" """
:param show_obj: show object :param show_obj: show object
@ -512,7 +545,7 @@ class ShowQueue(generic_queue.GenericQueue):
""" """
with self.lock: with self.lock:
if (self.isBeingRefreshed(show_obj) or self.isInRefreshQueue(show_obj)) and not force: if (self.isBeingRefreshed(show_obj) or self.isInRefreshQueue(show_obj)) and not force:
raise exceptions_helper.CantRefreshException('This show is already being refreshed, not refreshing again.') raise exceptions_helper.CantRefreshException('This show is being refreshed, not refreshing again.')
if ((not after_update and self.isBeingUpdated(show_obj)) or self.isInUpdateQueue(show_obj)) and not force: if ((not after_update and self.isBeingUpdated(show_obj)) or self.isInUpdateQueue(show_obj)) and not force:
logger.log('Skipping this refresh as there is already an update queued or' logger.log('Skipping this refresh as there is already an update queued or'
@ -548,11 +581,20 @@ class ShowQueue(generic_queue.GenericQueue):
return queue_item_obj return queue_item_obj
def switch_show(self, show_obj, new_tvid, new_prodid, force_id=False, uid=None, set_pause=False, mark_wanted=False, def switch_show(self,
resume=False, old_tvid=None, old_prodid=None, add_to_db=True): show_obj, # type: TVShow
# type: (TVShow, integer_types, integer_types, bool, AnyStr, bool, bool, bool, integer_types, integer_types, bool) -> QueueItemSwitchSource new_tvid, # type: integer_types
new_prodid, # type: integer_types
force_id=False, # type: bool
uid=None, # type: AnyStr
set_pause=False, # type: bool
mark_wanted=False, # type: bool
resume=False, # type: bool
old_tvid=None, # type: integer_types
old_prodid=None, # type: integer_types
add_to_db=True # type: bool
): # type: (...) -> QueueItemSwitchSource
""" """
:param show_obj: :param show_obj:
:param new_tvid: :param new_tvid:
:param new_prodid: :param new_prodid:
@ -800,26 +842,25 @@ class QueueItemAdd(ShowQueueItem):
""" """
self.tvid = tvid # type: int self.tvid = tvid # type: int
self.prodid = prodid # type: int self.prodid = prodid # type: int
self.showDir = show_dir # type: AnyStr self.allowlist = allowlist
self.anime = anime
self.blocklist = blocklist
self.default_status = default_status self.default_status = default_status
self.default_wanted_begin = (0, default_wanted_begin)[isinstance(default_wanted_begin, integer_types)] self.default_wanted_begin = (0, default_wanted_begin)[isinstance(default_wanted_begin, integer_types)]
self.default_wanted_latest = (0, default_wanted_latest)[isinstance(default_wanted_latest, integer_types)] self.default_wanted_latest = (0, default_wanted_latest)[isinstance(default_wanted_latest, integer_types)]
self.quality = quality # type: int
self.upgrade_once = upgrade_once
self.flatten_folders = flatten_folders self.flatten_folders = flatten_folders
self.lang = lang self.lang = lang
self.subtitles = subtitles self.new_show = new_show
self.anime = anime
self.scene = scene
self.paused = paused self.paused = paused
self.blocklist = blocklist
self.allowlist = allowlist
self.prune = prune self.prune = prune
self.tag = tag self.quality = quality # type: int
self.new_show = new_show self.scene = scene
self.showname = show_name # type: AnyStr or None
self.show_obj = None self.show_obj = None
self.showDir = show_dir # type: AnyStr
self.showname = show_name # type: AnyStr or None
self.subtitles = subtitles
self.tag = tag
self.upgrade_once = upgrade_once
# this will initialize self.show_obj to None # this will initialize self.show_obj to None
ShowQueueItem.__init__(self, ShowQueueActions.ADD, self.show_obj, scheduled_update, uid=uid) ShowQueueItem.__init__(self, ShowQueueActions.ADD, self.show_obj, scheduled_update, uid=uid)
@ -846,9 +887,7 @@ class QueueItemAdd(ShowQueueItem):
if we still only know the folder name. if we still only know the folder name.
:rtype: bool :rtype: bool
""" """
if None is self.show_obj: return None is self.show_obj
return True
return False
isLoading = property(_isLoading) isLoading = property(_isLoading)
@ -863,9 +902,12 @@ class QueueItemAdd(ShowQueueItem):
wanted_updates = [] wanted_updates = []
if latest: if latest:
# find season number with latest aired episode # find season number with latest aired episode
latest_result = db_obj.select('SELECT MAX(season) AS latest_season FROM tv_episodes WHERE season > 0 ' latest_result = db_obj.select(
'AND indexer = ? AND showid = ? AND status != ?', """
[self.show_obj.tvid, self.show_obj.prodid, UNAIRED]) SELECT MAX(season) AS latest_season
FROM tv_episodes
WHERE season > 0 AND indexer = ? AND showid = ? AND status != ?
""", [self.show_obj.tvid, self.show_obj.prodid, UNAIRED])
if latest_result and None is not latest_result[0]['latest_season']: if latest_result and None is not latest_result[0]['latest_season']:
latest_season = int(latest_result[0]['latest_season']) latest_season = int(latest_result[0]['latest_season'])
else: else:
@ -876,11 +918,12 @@ class QueueItemAdd(ShowQueueItem):
compare_op = '' # equal, we only want the specific season compare_op = '' # equal, we only want the specific season
else: else:
compare_op = ('>', '<')[latest] # less/more then equal season compare_op = ('>', '<')[latest] # less/more then equal season
base_sql = 'SELECT indexerid, season, episode, status FROM tv_episodes WHERE indexer = ?' \ base_sql = """
' AND showid = ? AND season != 0 AND season %s= ? AND status != ?' \ SELECT indexerid, season, episode, status
' ORDER BY season%s, episode%s%s' % \ FROM tv_episodes
(compare_op, ('', ' DESC')[latest], ('', ' DESC')[latest], WHERE indexer = ? AND showid = ? AND season != 0 AND season %s= ? AND status != ?
(' LIMIT ?', '')[-1 == wanted_max]) ORDER BY season%s, episode%s%s
""" % (compare_op, ('', ' DESC')[latest], ('', ' DESC')[latest], (' LIMIT ?', '')[-1 == wanted_max])
selected_res = db_obj.select(base_sql, [self.show_obj.tvid, self.show_obj.prodid, selected_res = db_obj.select(base_sql, [self.show_obj.tvid, self.show_obj.prodid,
(1, latest_season)[latest], UNAIRED] + (1, latest_season)[latest], UNAIRED] +
@ -904,10 +947,10 @@ class QueueItemAdd(ShowQueueItem):
db_obj.action(update, [WANTED, self.show_obj.tvid] + selected_ids) db_obj.action(update, [WANTED, self.show_obj.tvid] + selected_ids)
# noinspection SqlResolve # noinspection SqlResolve
result = db_obj.select('SELECT changes() as last FROM [tv_episodes]') sql_result = db_obj.select('SELECT changes() as last FROM [tv_episodes]')
for cur_result in result: for cur_row in sql_result:
actual = cur_result['last'] actual = cur_row['last']
break break
action_log = 'didn\'t find any episodes that need to be set wanted' action_log = 'didn\'t find any episodes that need to be set wanted'
@ -1046,7 +1089,7 @@ class QueueItemAdd(ShowQueueItem):
try: try:
self.show_obj.load_episodes_from_tvinfo(tvinfo_data=(None, result)[ self.show_obj.load_episodes_from_tvinfo(tvinfo_data=(None, result)[
self.show_obj._prodid == getattr(result, 'id', None)]) self.show_obj.prodid == getattr(result, 'id', None)])
except (BaseException, Exception) as e: except (BaseException, Exception) as e:
logger.log( logger.log(
'Error with %s, not creating episode list: %s' % (sickbeard.TVInfoAPI(self.show_obj.tvid).name, ex(e)), 'Error with %s, not creating episode list: %s' % (sickbeard.TVInfoAPI(self.show_obj.tvid).name, ex(e)),
@ -1064,13 +1107,12 @@ class QueueItemAdd(ShowQueueItem):
if self.default_status != SKIPPED: if self.default_status != SKIPPED:
logger.log('Setting all episodes to the specified default status: %s' logger.log('Setting all episodes to the specified default status: %s'
% sickbeard.common.statusStrings[self.default_status]) % sickbeard.common.statusStrings[self.default_status])
my_db.action('UPDATE tv_episodes' my_db.action(
' SET status = ?' """
' WHERE status = ?' UPDATE tv_episodes
' AND indexer = ? AND showid = ?' SET status = ?
' AND season != 0', WHERE status = ? AND indexer = ? AND showid = ? AND season != 0
[self.default_status, SKIPPED, """, [self.default_status, SKIPPED, self.show_obj.tvid, self.show_obj.prodid])
self.show_obj.tvid, self.show_obj.prodid])
items_wanted = self._get_wanted(my_db, self.default_wanted_begin, latest=False) items_wanted = self._get_wanted(my_db, self.default_wanted_begin, latest=False)
items_wanted += self._get_wanted(my_db, self.default_wanted_latest, latest=True) items_wanted += self._get_wanted(my_db, self.default_wanted_latest, latest=True)
@ -1348,7 +1390,7 @@ class QueueItemUpdate(ShowQueueItem):
scheduled_update=self.scheduled_update, switch=self.switch) scheduled_update=self.scheduled_update, switch=self.switch)
if result in (None, False): if result in (None, False):
return return
elif not self.show_obj._prodid == getattr(self.tvinfo_data, 'id', None): elif not self.show_obj.prodid == getattr(self.tvinfo_data, 'id', None):
self.tvinfo_data = result self.tvinfo_data = result
except BaseTVinfoAttributenotfound as e: except BaseTVinfoAttributenotfound as e:
logger.log('Data retrieved from %s was incomplete, aborting: %s' % logger.log('Data retrieved from %s was incomplete, aborting: %s' %
@ -1509,7 +1551,6 @@ class QueueItemSwitchSource(ShowQueueItem):
:param old_prodid: old prodid if resume set :param old_prodid: old prodid if resume set
:param kwargs: :param kwargs:
""" """
# type: (TVShow, int, integer_types, bool, AnyStr, bool, bool, bool, Dict) -> None
ShowQueueItem.__init__(self, ShowQueueActions.SWITCH, show_obj, uid=uid) ShowQueueItem.__init__(self, ShowQueueActions.SWITCH, show_obj, uid=uid)
self.new_tvid = new_tvid # type: int self.new_tvid = new_tvid # type: int
self.new_prodid = new_prodid # type: integer_types self.new_prodid = new_prodid # type: integer_types
@ -1635,7 +1676,7 @@ class QueueItemSwitchSource(ShowQueueItem):
t = sickbeard.TVInfoAPI(self.new_tvid).setup(**tvinfo_config) t = sickbeard.TVInfoAPI(self.new_tvid).setup(**tvinfo_config)
try: try:
td = t.get_show(show_id=new_prodid, actors=True) td = t.get_show(show_id=new_prodid, actors=True)
except (BaseException, Exception) as e: except (BaseException, Exception):
td = None td = None
if not self.force_id: if not self.force_id:
map_indexers_to_show(self.show_obj, recheck=True) map_indexers_to_show(self.show_obj, recheck=True)
@ -1710,8 +1751,8 @@ class QueueItemSwitchSource(ShowQueueItem):
self.progress = 'Switching to new source' self.progress = 'Switching to new source'
self._set_switch_id(new_prodid) self._set_switch_id(new_prodid)
self.show_obj.remove_character_images() self.show_obj.remove_character_images()
self.show_obj.tvid = self.new_tvid self.show_obj._tvid = self.new_tvid
self.show_obj.prodid = new_prodid self.show_obj._prodid = new_prodid
new_tvid_prodid = TVidProdid({self.new_tvid: new_prodid})() new_tvid_prodid = TVidProdid({self.new_tvid: new_prodid})()
old_tvid_prodid = TVidProdid({self.old_tvid: self.old_prodid})() old_tvid_prodid = TVidProdid({self.old_tvid: self.old_prodid})()
for tp in (old_tvid_prodid, new_tvid_prodid): for tp in (old_tvid_prodid, new_tvid_prodid):

1227
sickbeard/tv.py

File diff suppressed because it is too large

70
sickbeard/tv_base.py

@ -58,37 +58,37 @@ class TVShowBase(LegacyTVShow, TVBase):
def __init__(self, tvid, prodid, lang=''): def __init__(self, tvid, prodid, lang=''):
# type: (int, int, Text) -> None # type: (int, int, Text) -> None
super(TVShowBase, self).__init__(tvid, prodid) super(TVShowBase, self).__init__(tvid, prodid)
self._name = ''
self._imdbid = ''
self.internal_network = ''
self._genre = ''
self._classification = ''
self._runtime = 0
self._imdb_info = {}
self._quality = int(sickbeard.QUALITY_DEFAULT)
self._flatten_folders = int(sickbeard.FLATTEN_FOLDERS_DEFAULT)
self._status = ''
self._airs = ''
self._startyear = 0
self._air_by_date = 0 self._air_by_date = 0
self._subtitles = int(sickbeard.SUBTITLES_DEFAULT) if sickbeard.SUBTITLES_DEFAULT else 0 self._airs = ''
self._anime = 0
self._classification = ''
self._dvdorder = 0 self._dvdorder = 0
self._upgrade_once = 0 self._flatten_folders = int(sickbeard.FLATTEN_FOLDERS_DEFAULT)
self._genre = ''
self._imdb_info = {}
self._imdbid = ''
self._lang = lang self._lang = lang
self._last_update_indexer = 1 self._last_update_indexer = 1
self._sports = 0 self._name = ''
self._anime = 0
self._scene = 0
self._rls_ignore_words = set()
self._rls_require_words = set()
self._overview = '' self._overview = ''
self._prune = 0 self._prune = 0
self._tag = '' self._quality = int(sickbeard.QUALITY_DEFAULT)
self._rls_ignore_words_regex = False
self._rls_require_words_regex = False
self._rls_global_exclude_ignore = set() self._rls_global_exclude_ignore = set()
self._rls_global_exclude_require = set() self._rls_global_exclude_require = set()
self._rls_ignore_words = set()
self._rls_ignore_words_regex = False
self._rls_require_words = set()
self._rls_require_words_regex = False
self._runtime = 0
self._scene = 0
self._sports = 0
self._startyear = 0
self._status = ''
self._subtitles = int(sickbeard.SUBTITLES_DEFAULT) if sickbeard.SUBTITLES_DEFAULT else 0
self._tag = ''
self._upgrade_once = 0
self.internal_network = ''
# name = property(lambda self: self._name, dirty_setter('_name')) # name = property(lambda self: self._name, dirty_setter('_name'))
@property @property
@ -133,7 +133,7 @@ class TVShowBase(LegacyTVShow, TVBase):
self.dirty_setter('_name')(self, *arg) self.dirty_setter('_name')(self, *arg)
if _current_name != self._name: if _current_name != self._name:
buildNameCache(self) buildNameCache(self)
# imdbid = property(lambda self: self._imdbid, dirty_setter('_imdbid')) # imdbid = property(lambda self: self._imdbid, dirty_setter('_imdbid'))
@property @property
def imdbid(self): def imdbid(self):
@ -366,23 +366,23 @@ class TVEpisodeBase(LegacyTVEpisode, TVBase):
def __init__(self, season, episode, tvid): def __init__(self, season, episode, tvid):
super(TVEpisodeBase, self).__init__(tvid) super(TVEpisodeBase, self).__init__(tvid)
self._name = ''
self._season = season
self._episode = episode
self._absolute_number = 0 self._absolute_number = 0
self._description = ''
self._subtitles = list()
self._subtitles_searchcount = 0
self._subtitles_lastsearch = str(datetime.datetime.min)
self._airdate = datetime.date.fromordinal(1) self._airdate = datetime.date.fromordinal(1)
self._description = ''
self._episode = episode
self._file_size = 0
self._hasnfo = False self._hasnfo = False
self._hastbn = False self._hastbn = False
self._status = UNKNOWN
self._file_size = 0
self._release_name = ''
self._is_proper = False self._is_proper = False
self._version = 0 self._name = ''
self._release_group = '' self._release_group = ''
self._release_name = ''
self._season = season
self._status = UNKNOWN
self._subtitles = list()
self._subtitles_lastsearch = str(datetime.datetime.min)
self._subtitles_searchcount = 0
self._version = 0
# name = property(lambda self: self._name, dirty_setter('_name', string_types)) # name = property(lambda self: self._name, dirty_setter('_name', string_types))
@property @property

2
sickbeard/webserve.py

@ -6735,7 +6735,7 @@ class Manage(MainHandler):
continue continue
else: else:
new_prodid = None new_prodid = None
if show_obj._tvid == new_tvid and (not new_prodid or new_prodid == show_obj._prodid): if show_obj.tvid == new_tvid and (not new_prodid or new_prodid == show_obj.prodid):
logger.log('Skipping %s because target same as source' % show, logger.WARNING) logger.log('Skipping %s because target same as source' % show, logger.WARNING)
errors.append('Skipping %s because target same as source' % show) errors.append('Skipping %s because target same as source' % show)
continue continue

2
sickgear.py

@ -730,7 +730,7 @@ class SickGear(object):
if _fk.startswith('ii_')} if _fk.startswith('ii_')}
else: else:
imdb_info_sql = None imdb_info_sql = None
show_obj = TVShow(tv_id, prod_id, show_sql=cur_result, imdb_info_sql=imdb_info_sql) show_obj = TVShow(tv_id, prod_id, show_result=cur_result, imdb_info_result=imdb_info_sql)
if cur_result['tsnf_indexer_id']: if cur_result['tsnf_indexer_id']:
failed_result = {_fk.replace('tsnf_', ''): _fv for _fk, _fv in iteritems(cur_result) failed_result = {_fk.replace('tsnf_', ''): _fv for _fk, _fv in iteritems(cur_result)
if _fk.startswith('tsnf_')} if _fk.startswith('tsnf_')}

6
tests/name_parser_tests.py

@ -711,9 +711,9 @@ class TVShowTest(tv.TVShow):
def __init__(self, is_anime=False, name='', prodid=0, tvid=0): def __init__(self, is_anime=False, name='', prodid=0, tvid=0):
self._anime = is_anime self._anime = is_anime
self._name = name self._name = name
self._tvid = tvid self.tvid = tvid
self._prodid = prodid self.prodid = prodid
self.sid_int = self.create_sid(self._tvid, self._prodid) self.sid_int = self.create_sid(self.tvid, self.prodid)
self.sxe_ep_obj = {} self.sxe_ep_obj = {}

Loading…
Cancel
Save