Browse Source

Change improve find_show_by_id.

Change add find_show_by_ids tests.
Change rename _mapped_ids of TVShow objects to internal_ids.
Change add new parameter to find_show_by_id where needed.
pull/1289/head
Prinz23 5 years ago
committed by JackDandy
parent
commit
9864c7f817
  1. 11
      sickbeard/__init__.py
  2. 27
      sickbeard/helpers.py
  3. 2
      sickbeard/history.py
  4. 3
      sickbeard/processTV.py
  5. 6
      sickbeard/properFinder.py
  6. 2
      sickbeard/providers/newznab.py
  7. 5
      sickbeard/search_queue.py
  8. 1
      sickbeard/show_queue.py
  9. 21
      sickbeard/tv.py
  10. 2
      sickbeard/tvcache.py
  11. 4
      sickbeard/webserve.py
  12. 2
      sickgear.py
  13. 97
      tests/tv_tests.py

11
sickbeard/__init__.py

@ -61,6 +61,11 @@ from _23 import b64encodestring, filter_iter, list_items, map_list
from six import iteritems, PY2, string_types
import sg_helpers
# noinspection PyUnreachableCode
if False:
from typing import Dict, List
from .tv import TVShow
PID = None
ENV = {}
@ -98,7 +103,8 @@ watchedStateQueueScheduler = None
provider_ping_thread_pool = {}
showList = []
showList = [] # type: List[TVShow]
showDict = {} # type: Dict[int, TVShow]
UPDATE_SHOWS_ON_START = False
SHOW_UPDATE_HOUR = 3
@ -602,7 +608,7 @@ def initialize(console_logging=True):
def init_stage_1(console_logging):
# Misc
global showList, providerList, newznabProviderList, torrentRssProviderList, \
global showList, showDict, providerList, newznabProviderList, torrentRssProviderList, \
WEB_HOST, WEB_ROOT, ACTUAL_CACHE_DIR, CACHE_DIR, ZONEINFO_DIR, ADD_SHOWS_WO_DIR, ADD_SHOWS_METALANG, \
CREATE_MISSING_SHOW_DIRS, SHOW_DIRS_WITH_DOTS, \
RECENTSEARCH_STARTUP, NAMING_FORCE_FOLDERS, SOCKET_TIMEOUT, DEBUG, TVINFO_DEFAULT, CONFIG_FILE, \
@ -1383,6 +1389,7 @@ def init_stage_1(console_logging):
'<br>Important: You <span class="boldest">must</span> Shutdown SickGear before upgrading'
showList = []
showDict = {}
def init_stage_2():

27
sickbeard/helpers.py

@ -53,7 +53,7 @@ import subliminal
from lxml_etree import etree, is_lxml
from send2trash import send2trash
from _23 import b64decodebytes, b64encodebytes, decode_bytes, DirEntry, filter_iter, filter_list, scandir
from _23 import b64decodebytes, b64encodebytes, decode_bytes, DirEntry, filter_iter, scandir
from six import iteritems, PY2, string_types, text_type
# noinspection PyUnresolvedReferences
from six.moves import zip
@ -276,14 +276,15 @@ def remove_file(filepath, tree=False, prefix_failure='', log_level=logger.MESSAG
def find_show_by_id(
show_id, # type: Union[AnyStr, Dict[int, int], int]
show_list=None, # type: Optional[List[TVShow]]
no_mapped_ids=True # type: bool
no_mapped_ids=True, # type: bool
check_multishow=False # type: bool
):
# type: (...) -> TVShow or MultipleShowObjectsException
# type: (...) -> Optional[TVShow]
"""
:param show_id: {indexer: id} or 'tvid_prodid'.
:param show_list: (optional) TVShow objects list
:param no_mapped_ids: don't check mapped ids
:return: TVShow object or MultipleShowObjectsException
:param check_multishow: check for multiple show matches
"""
results = []
if None is show_list:
@ -295,8 +296,7 @@ def find_show_by_id(
if tvid_prodid_obj and no_mapped_ids:
if None is tvid_prodid_obj.prodid:
return None
sid_int = int(tvid_prodid_obj)
results = filter_list(lambda _show_obj: sid_int == _show_obj.sid_int, show_list)
return sickbeard.showDict.get(int(tvid_prodid_obj))
else:
if tvid_prodid_obj:
if None is tvid_prodid_obj.prodid:
@ -304,12 +304,21 @@ def find_show_by_id(
show_id = tvid_prodid_obj.dict
if isinstance(show_id, dict):
show_id = {k: v for k, v in iteritems(show_id) if 0 < v}
if no_mapped_ids:
results = filter_list(lambda _show_obj: show_id == {_show_obj.tvid: _show_obj.prodid}, show_list)
sid_int_list = [sickbeard.tv.TVShow.create_sid(sk, sv) for sk, sv in iteritems(show_id) if 0 < sv
and sickbeard.tv.tvid_bitmask >= sk]
if check_multishow:
results = [sickbeard.showDict.get(_show_sid_id) for _show_sid_id in sid_int_list
if sickbeard.showDict.get(_show_sid_id)]
else:
for _show_sid_id in sid_int_list:
if _show_sid_id in sickbeard.showDict:
return sickbeard.showDict.get(_show_sid_id)
return None
else:
show_id = {k: v for k, v in iteritems(show_id) if 0 < v}
results = [_show_obj for k, v in iteritems(show_id)
for _show_obj in show_list if v == _show_obj.ids.get(k, {'id': 0})['id']]
for _show_obj in show_list if v == _show_obj.internal_ids.get(k, {'id': 0})['id']]
num_shows = len(set(results))
if 1 == num_shows:

2
sickbeard/history.py

@ -206,7 +206,7 @@ def history_snatched_proper_fix():
for r in sql_result:
show_obj = None
try:
show_obj = helpers.find_show_by_id({int(r['tv_id']): int(r['prod_id'])})
show_obj = helpers.find_show_by_id({int(r['tv_id']): int(r['prod_id'])}, check_multishow=True)
except (BaseException, Exception):
pass
np = NameParser(False, show_obj=show_obj, testing=True)

3
sickbeard/processTV.py

@ -212,7 +212,8 @@ class ProcessTVShow(object):
' ORDER BY rowid', [name])
if sql_result:
try:
show_obj = helpers.find_show_by_id({int(sql_result[-1]['indexer']): int(sql_result[-1]['showid'])})
show_obj = helpers.find_show_by_id({int(sql_result[-1]['indexer']): int(sql_result[-1]['showid'])},
check_multishow=True)
if hasattr(show_obj, 'name'):
logger.log('Found Show: %s in snatch history for: %s' % (show_obj.name, name), logger.DEBUG)
except MultipleShowObjectsException:

6
sickbeard/properFinder.py

@ -570,7 +570,8 @@ def get_needed_qualites(needed=None):
if needed.all_needed:
break
try:
show_obj = helpers.find_show_by_id({int(cur_result['tv_id']): int(cur_result['prod_id'])})
show_obj = helpers.find_show_by_id({int(cur_result['tv_id']): int(cur_result['prod_id'])},
check_multishow=True)
except MultipleShowObjectsException:
continue
if show_obj:
@ -612,7 +613,8 @@ def _recent_history(aired_since_shows, aired_since_anime):
for cur_result in sql_result:
try:
show_obj = helpers.find_show_by_id({int(cur_result['tv_id']): int(cur_result['prod_id'])})
show_obj = helpers.find_show_by_id({int(cur_result['tv_id']): int(cur_result['prod_id'])},
check_multishow=True)
except MultipleShowObjectsException:
continue
if show_obj:

2
sickbeard/providers/newznab.py

@ -602,7 +602,7 @@ class NewznabProvider(generic.NZBProvider):
if tvid_prodid:
try:
show_obj = helpers.find_show_by_id(tvid_prodid, no_mapped_ids=False)
show_obj = helpers.find_show_by_id(tvid_prodid, no_mapped_ids=False, check_multishow=True)
except MultipleShowObjectsException:
return None
return show_obj

5
sickbeard/search_queue.py

@ -369,7 +369,6 @@ class RecentSearchQueueItem(generic_queue.QueueItem):
for cur_result in sql_result:
tvid, prodid = int(cur_result['tvid']), int(cur_result['prodid'])
try:
if not show_obj or not (show_obj.tvid == tvid and show_obj.prodid == prodid):
show_obj = helpers.find_show_by_id({tvid: prodid})
@ -377,10 +376,6 @@ class RecentSearchQueueItem(generic_queue.QueueItem):
if not show_obj:
continue
except exceptions_helper.MultipleShowObjectsException:
logger.log(u'ERROR: expected to find a single show matching %s' % cur_result['showid'])
continue
try:
end_time = (network_timezones.parse_date_time(cur_result['airdate'], show_obj.airs, show_obj.network) +
datetime.timedelta(minutes=helpers.try_int(show_obj.runtime, 60)))

1
sickbeard/show_queue.py

@ -760,6 +760,7 @@ class QueueItemAdd(ShowQueueItem):
# add it to the show list
sickbeard.showList.append(self.show_obj)
sickbeard.showDict[self.show_obj.sid_int] = self.show_obj
try:
self.show_obj.load_episodes_from_tvinfo()

21
sickbeard/tv.py

@ -214,7 +214,7 @@ class TVShow(TVShowBase):
self._prodid = int(prodid)
self.sid_int = self.create_sid(self._tvid, self._prodid)
self._paused = 0
self._mapped_ids = {} # type: Dict
self.internal_ids = {} # type: Dict
self._not_found_count = None # type: None or int
self._last_found_on_indexer = -1 # type: int
@ -229,7 +229,7 @@ class TVShow(TVShowBase):
# noinspection PyTypeChecker
self.release_groups = None # type: BlackAndWhiteList
show_obj = helpers.find_show_by_id(self.sid_int)
show_obj = helpers.find_show_by_id(self.sid_int, check_multishow=True)
if None is not show_obj:
raise exceptions_helper.MultipleShowObjectsException('Can\'t create a show if it already exists')
@ -363,14 +363,14 @@ class TVShow(TVShowBase):
@property
def ids(self):
if not self._mapped_ids:
if not self.internal_ids:
acquired_lock = self.lock.acquire(False)
if acquired_lock:
try:
indexermapper.map_indexers_to_show(self)
finally:
self.lock.release()
return self._mapped_ids
return self.internal_ids
@ids.setter
def ids(self, value):
@ -383,7 +383,7 @@ class TVShow(TVShowBase):
v.get('status') not in indexermapper.MapStatus.allstatus or \
not isinstance(v.get('date'), datetime.date):
return
self._mapped_ids = value
self.internal_ids = value
@property
def is_anime(self):
@ -1514,6 +1514,10 @@ class TVShow(TVShowBase):
# remove self from show list
sickbeard.showList = filter_list(lambda so: so.tvid_prodid != self.tvid_prodid, sickbeard.showList)
try:
del sickbeard.showDict[self.sid_int]
except (BaseException, Exception):
pass
# clear the cache
ic = image_cache.ImageCache()
@ -1752,6 +1756,13 @@ class TVShow(TVShowBase):
name_cache.buildNameCache(self)
self.reset_not_found_count()
old_sid_int = self.create_sid(old_tvid, old_prodid)
if old_sid_int != self.sid_int:
try:
del sickbeard.showDict[old_sid_int]
except (BaseException, Exception):
pass
sickbeard.showDict[self.sid_int] = self
# force the update
try:

2
sickbeard/tvcache.py

@ -286,7 +286,7 @@ class TVCache(object):
show_obj = None
if tvid_prodid:
try:
show_obj = helpers.find_show_by_id(tvid_prodid, no_mapped_ids=False)
show_obj = helpers.find_show_by_id(tvid_prodid, no_mapped_ids=False, check_multishow=True)
except MultipleShowObjectsException:
return

4
sickbeard/webserve.py

@ -2279,7 +2279,7 @@ class Home(MainHandler):
m_prodid = helpers.try_int(m_prodid)
show_obj = helpers.find_show_by_id({tvid: prodid}, no_mapped_ids=True)
try:
m_show_obj = helpers.find_show_by_id({m_tvid: m_prodid}, no_mapped_ids=False)
m_show_obj = helpers.find_show_by_id({m_tvid: m_prodid}, no_mapped_ids=False, check_multishow=True)
except exceptions_helper.MultipleShowObjectsException:
msg = 'Duplicate shows in DB'
ui.notifications.message('TV info source switch', 'Error: ' + msg)
@ -2360,7 +2360,7 @@ class Home(MainHandler):
not sickbeard.TVInfoAPI(m_tvid).config.get('mapped_only') and \
(m_tvid != show_obj.tvid or m_prodid != show_obj.prodid):
try:
new_show_obj = helpers.find_show_by_id({m_tvid: m_prodid}, no_mapped_ids=False)
new_show_obj = helpers.find_show_by_id({m_tvid: m_prodid}, no_mapped_ids=False, check_multishow=True)
mtvid_prodid = TVidProdid({m_tvid: m_prodid})()
if not new_show_obj or (new_show_obj.tvid == show_obj.tvid and new_show_obj.prodid == show_obj.prodid):
master_ids += [bool(helpers.try_int(kwargs.get(x))) for x in ('paused', 'markwanted')]

2
sickgear.py

@ -626,10 +626,12 @@ class SickGear(object):
sql_result = my_db.select('SELECT indexer AS tv_id, indexer_id AS prod_id, location FROM tv_shows')
sickbeard.showList = []
sickbeard.showDict = {}
for cur_result in sql_result:
try:
show_obj = TVShow(int(cur_result['tv_id']), int(cur_result['prod_id']))
sickbeard.showList.append(show_obj)
sickbeard.showDict[show_obj.sid_int] = show_obj
except (BaseException, Exception) as err:
logger.log('There was an error creating the show in %s: %s' % (
cur_result['location'], ex(err)), logger.ERROR)

97
tests/tv_tests.py

@ -22,8 +22,20 @@ import unittest
import test_lib as test
from random import randint
import datetime
import copy
import sickbeard
from sickbeard.tv import TVEpisode, TVShow, TVidProdid, prodid_bitshift
from exceptions_helper import ex, MultipleShowObjectsException
from sickbeard.helpers import find_show_by_id
from sickbeard import indexermapper
from sickbeard.indexers.indexer_api import TVInfoAPI
from sickbeard.indexers.indexer_config import TVINFO_IMDB, TVINFO_TMDB, TVINFO_TRAKT, TVINFO_TVDB, TVINFO_TVMAZE, \
TVINFO_TVRAGE
# noinspection PyUnreachableCode
if False:
from typing import Optional
class TVShowTests(test.SickbeardTestDBCase):
@ -170,6 +182,88 @@ class TVidProdidTests(test.SickbeardTestDBCase):
self.assertEqual(prodid, str_reverse_obj.prodid, msg='reverse str prodid test%s' % msg_vars)
ids_base = {source: {'id': 0, 'status': indexermapper.MapStatus.NO_AUTOMATIC_CHANGE, 'date': datetime.date.today()}
for source in TVInfoAPI().all_sources}
shows = [{'tvid': TVINFO_TVDB, 'prodid': 123,
'ids': {TVINFO_TVMAZE: {'id': 22}, TVINFO_IMDB: {'id': 54321}, TVINFO_TMDB: {'id': 9877}}},
{'tvid': TVINFO_TVDB, 'prodid': 222,
'ids': {TVINFO_TVMAZE: {'id': 854}, TVINFO_IMDB: {'id': 9435}, TVINFO_TMDB: {'id': 2457}}},
{'tvid': TVINFO_TVMAZE, 'prodid': 123,
'ids': {TVINFO_TVMAZE: {'id': 957}, TVINFO_IMDB: {'id': 4751}, TVINFO_TMDB: {'id': 659}}},
{'tvid': TVINFO_TMDB, 'prodid': 123,
'ids': {TVINFO_TVMAZE: {'id': 428}, TVINFO_IMDB: {'id': 999}, TVINFO_TMDB: {'id': 754}}}
]
find_tests = [
{'para': {'show_id': {TVINFO_TVMAZE: 22, TVINFO_TVRAGE: 785}, 'no_mapped_ids': False},
'result': {'tvid': TVINFO_TVDB, 'prodid': 123},
'description': 'search via mapped id'},
{'para': {'show_id': {TVINFO_TVDB: 123}}, 'result': {'tvid': TVINFO_TVDB, 'prodid': 123},
'description': 'simple standard search via master id dict'},
{'para': {'show_id': {TVINFO_TVDB: 12345}}, 'result': None,
'description': 'simple standard search via master id dict, for non-existing show'},
{'para': {'show_id': {TVINFO_TVDB: 123, TVINFO_TVMAZE: 123}, 'check_multishow': True},
'result': {'success': False},
'description': 'search via 2 ids matching multiple shows and multi show check'},
{'para': {'show_id': {TVINFO_TVDB: 5555, TVINFO_TVMAZE: 123}, 'check_multishow': True},
'result': {'tvid': TVINFO_TVMAZE, 'prodid': 123},
'description': 'search via 2 ids matching only 1 show and multi show check'},
{'para': {'show_id': {TVINFO_TVDB: 123, TVINFO_TVMAZE: 123}},
'result': {'tvid': TVINFO_TVDB, 'prodid': 123},
'description': 'search via 2 ids matching only 1 show without multi show check #1'},
{'para': {'show_id': {TVINFO_TVDB: 123, TVINFO_TVRAGE: 22}},
'result': {'tvid': TVINFO_TVDB, 'prodid': 123},
'description': 'search via 2 ids matching only 1 show without multi show check #2'},
{'para': {'show_id': {TVINFO_TVMAZE: 22, TVINFO_TVRAGE: 785}},
'result': None,
'description': 'search for 2 non-existing ids without mapping'},
{'para': {'show_id': {TVINFO_TMDB: 123}},
'result': None, 'description': 'invalid sid search (tvid above tvid_bitmask)'},
{'para': {'show_id': '%s:123' % TVINFO_TVDB}, 'result': {'tvid': TVINFO_TVDB, 'prodid': 123},
'description': 'simple search via tvid_prodid string'},
{'para': {'show_id': '%s:123' % TVINFO_TVDB, 'check_multishow': True},
'result': {'tvid': TVINFO_TVDB, 'prodid': 123},
'description': 'simple search via tvid_prodid string and check multishow'},
]
class TVFindTests(test.SickbeardTestDBCase):
def setUp(self):
super(TVFindTests, self).setUp()
sickbeard.showList = []
sickbeard.showDict = {}
sickbeard.indexermapper.indexer_list = [i for i in TVInfoAPI().all_sources]
for show in shows:
sh = TVShow(show['tvid'], show['prodid'])
ids = copy.deepcopy(ids_base)
if show.get('ids'):
for sub_ids in show['ids']:
ids[sub_ids].update(show['ids'][sub_ids])
ids[show['tvid']]['status'] = indexermapper.MapStatus.SOURCE
ids[show['tvid']]['id'] = show['prodid']
sh.ids = ids
sickbeard.showList.append(sh)
sickbeard.showDict[sh.sid_int] = sh
def test_find_show_by_id(self):
result = None # type: Optional[TVShow]
for show_test in find_tests:
success = True
try:
result = find_show_by_id(**show_test['para'])
except MultipleShowObjectsException:
success = False
if isinstance(show_test['result'], dict) and None is not show_test['result'].get('success', None):
self.assertEqual(success, show_test['result'].get('success', None),
msg='error finding show (%s) with para: %s' %
(show_test.get('description'), show_test['para']))
else:
self.assertEqual(result and {'tvid': result.tvid, 'prodid': result.prodid}, show_test['result'],
msg='error finding show (%s) with para: %s' %
(show_test.get('description'), show_test['para']))
if '__main__' == __name__:
print('==================')
print('STARTING - TV TESTS')
@ -189,3 +283,6 @@ if '__main__' == __name__:
print('######################################################################')
suite = unittest.TestLoader().loadTestsFromTestCase(TVidProdidTests)
unittest.TextTestRunner(verbosity=2).run(suite)
print('######################################################################')
suite = unittest.TestLoader().loadTestsFromTestCase(TVFindTests)
unittest.TextTestRunner(verbosity=2).run(suite)

Loading…
Cancel
Save