Change when adding a show, display show title instead of '[]'.

Change consolidate show data validator into base class.
Change move validator test to inside the respective tvinfo source getter for future proofing.
This commit is contained in:
JackDandy 2018-04-07 20:49:12 +01:00
parent 3b61e5e821
commit bd8f0a7b61
10 changed files with 76 additions and 61 deletions

View file

@ -1,4 +1,10 @@
### 0.15.8 (2018-04-07 00:14:00 UTC) ### 0.15.9 (2018-04-07 20:45:00 UTC)
* Fix metadata show not found
* Change when adding a show, display show title instead of '[]'
### 0.15.8 (2018-04-07 00:14:00 UTC)
* Change improve tvinfo source meta handling for cases where server is either down, or no results are returned * Change improve tvinfo source meta handling for cases where server is either down, or no results are returned

View file

@ -155,6 +155,9 @@ class Show(dict):
# doesn't exist, so attribute error. # doesn't exist, so attribute error.
raise tvdb_attributenotfound('Cannot find attribute %s' % (repr(key))) raise tvdb_attributenotfound('Cannot find attribute %s' % (repr(key)))
def __nonzero__(self):
return any(self.data.keys())
def aired_on(self, date): def aired_on(self, date):
ret = self.search(str(date), 'firstaired') ret = self.search(str(date), 'firstaired')
if 0 == len(ret): if 0 == len(ret):
@ -643,9 +646,15 @@ class Tvdb:
""" """
try: try:
src = self._load_url(url, params=params, language=language) src = self._load_url(url, params=params, language=language)
return src if isinstance(src, dict):
except (StandardError, Exception): data = src['data'] or {}
return [] if isinstance(data, list):
data = data[0] or {}
if 1 > len(data.keys()):
raise ValueError
return src
except (KeyError, IndexError, Exception):
pass
def _set_item(self, sid, seas, ep, attrib, value): def _set_item(self, sid, seas, ep, attrib, value):
"""Creates a new episode, creating Show(), Season() and """Creates a new episode, creating Show(), Season() and
@ -803,7 +812,7 @@ class Tvdb:
url = self.config['url_episodeInfo'] % epid url = self.config['url_episodeInfo'] % epid
episode_data = self._getetsrc(url, language=self.config['language']) episode_data = self._getetsrc(url, language=self.config['language'])
if isinstance(episode_data, dict) and 'data' in episode_data: if episode_data and 'data' in episode_data:
data = episode_data['data'] data = episode_data['data']
if isinstance(data, dict): if isinstance(data, dict):
for k, v in data.iteritems(): for k, v in data.iteritems():
@ -830,7 +839,7 @@ class Tvdb:
show_data = self._getetsrc(url, language=language) show_data = self._getetsrc(url, language=language)
# check and make sure we have data to process and that it contains a series name # check and make sure we have data to process and that it contains a series name
if not isinstance(show_data, dict) or 'data' not in show_data or not isinstance(show_data['data'], dict) or 'seriesname' not in show_data['data']: if not (show_data and 'seriesname' in show_data.get('data', {}) or {}):
return False return False
for k, v in show_data['data'].iteritems(): for k, v in show_data['data'].iteritems():
@ -839,7 +848,7 @@ class Tvdb:
p = '' p = ''
if self.config['posters_enabled']: if self.config['posters_enabled']:
poster_data = self._getetsrc(self.config['url_seriesBanner'] % (sid, 'poster'), language=language) poster_data = self._getetsrc(self.config['url_seriesBanner'] % (sid, 'poster'), language=language)
if poster_data and 'data' in poster_data and poster_data['data'] and len(poster_data['data']) > 0: if poster_data and len(poster_data.get('data', '') or '') > 0:
poster_data['data'] = sorted(poster_data['data'], reverse=True, poster_data['data'] = sorted(poster_data['data'], reverse=True,
key=lambda x: (x['ratingsinfo']['average'], x['ratingsinfo']['count'])) key=lambda x: (x['ratingsinfo']['average'], x['ratingsinfo']['count']))
p = self.config['url_artworkPrefix'] % poster_data['data'][0]['filename'] p = self.config['url_artworkPrefix'] % poster_data['data'][0]['filename']
@ -850,7 +859,7 @@ class Tvdb:
b = '' b = ''
if self.config['banners_enabled']: if self.config['banners_enabled']:
poster_data = self._getetsrc(self.config['url_seriesBanner'] % (sid, 'series'), language=language) poster_data = self._getetsrc(self.config['url_seriesBanner'] % (sid, 'series'), language=language)
if poster_data and 'data' in poster_data and poster_data['data'] and len(poster_data['data']) > 0: if poster_data and len(poster_data.get('data', '') or '') > 0:
poster_data['data'] = sorted(poster_data['data'], reverse=True, poster_data['data'] = sorted(poster_data['data'], reverse=True,
key=lambda x: (x['ratingsinfo']['average'], x['ratingsinfo']['count'])) key=lambda x: (x['ratingsinfo']['average'], x['ratingsinfo']['count']))
b = self.config['url_artworkPrefix'] % poster_data['data'][0]['filename'] b = self.config['url_artworkPrefix'] % poster_data['data'][0]['filename']
@ -860,14 +869,14 @@ class Tvdb:
if self.config['seasons_enabled']: if self.config['seasons_enabled']:
poster_data = self._getetsrc(self.config['url_seriesBanner'] % (sid, 'season'), language=language) poster_data = self._getetsrc(self.config['url_seriesBanner'] % (sid, 'season'), language=language)
if poster_data and 'data' in poster_data and poster_data['data'] and len(poster_data['data']) > 0: if poster_data and len(poster_data.get('data', '') or '') > 0:
poster_data['data'] = sorted(poster_data['data'], reverse=True, poster_data['data'] = sorted(poster_data['data'], reverse=True,
key=lambda x: (-1 * tryInt(x['subkey']), x['ratingsinfo']['average'], x['ratingsinfo']['count'])) key=lambda x: (-1 * tryInt(x['subkey']), x['ratingsinfo']['average'], x['ratingsinfo']['count']))
self._parse_banners(sid, poster_data['data']) self._parse_banners(sid, poster_data['data'])
if self.config['seasonwides_enabled']: if self.config['seasonwides_enabled']:
poster_data = self._getetsrc(self.config['url_seriesBanner'] % (sid, 'seasonwide'), language=language) poster_data = self._getetsrc(self.config['url_seriesBanner'] % (sid, 'seasonwide'), language=language)
if poster_data and 'data' in poster_data and poster_data['data'] and len(poster_data['data']) > 0: if poster_data and len(poster_data.get('data', '') or '') > 0:
poster_data['data'] = sorted(poster_data['data'], reverse=True, poster_data['data'] = sorted(poster_data['data'], reverse=True,
key=lambda x: (-1 * tryInt(x['subkey']), x['ratingsinfo']['average'], x['ratingsinfo']['count'])) key=lambda x: (-1 * tryInt(x['subkey']), x['ratingsinfo']['average'], x['ratingsinfo']['count']))
self._parse_banners(sid, poster_data['data']) self._parse_banners(sid, poster_data['data'])
@ -875,7 +884,7 @@ class Tvdb:
f = '' f = ''
if self.config['fanart_enabled']: if self.config['fanart_enabled']:
fanart_data = self._getetsrc(self.config['url_seriesBanner'] % (sid, 'fanart'), language=language) fanart_data = self._getetsrc(self.config['url_seriesBanner'] % (sid, 'fanart'), language=language)
if fanart_data and 'data' in fanart_data and fanart_data['data'] and len(fanart_data['data']) > 0: if fanart_data and len(fanart_data.get('data', '') or '') > 0:
fanart_data['data'] = sorted(fanart_data['data'], reverse=True, fanart_data['data'] = sorted(fanart_data['data'], reverse=True,
key=lambda x: (x['ratingsinfo']['average'], x['ratingsinfo']['count'])) key=lambda x: (x['ratingsinfo']['average'], x['ratingsinfo']['count']))
f = self.config['url_artworkPrefix'] % fanart_data['data'][0]['filename'] f = self.config['url_artworkPrefix'] % fanart_data['data'][0]['filename']
@ -885,7 +894,7 @@ class Tvdb:
if self.config['actors_enabled']: if self.config['actors_enabled']:
actor_data = self._getetsrc(self.config['url_actorsInfo'] % sid, language=language) actor_data = self._getetsrc(self.config['url_actorsInfo'] % sid, language=language)
if actor_data and 'data' in actor_data and actor_data['data'] and len(actor_data['data']) > 0: if actor_data and len(actor_data.get('data', '') or '') > 0:
a = '|%s|' % '|'.join([n.get('name', '') for n in sorted( a = '|%s|' % '|'.join([n.get('name', '') for n in sorted(
actor_data['data'], key=lambda x: x['sortorder'])]) actor_data['data'], key=lambda x: x['sortorder'])])
self._parse_actors(sid, actor_data['data']) self._parse_actors(sid, actor_data['data'])
@ -901,12 +910,11 @@ class Tvdb:
episodes = [] episodes = []
while page is not None: while page is not None:
episode_data = self._getetsrc(self.config['url_epInfo'] % (sid, page), language=language) episode_data = self._getetsrc(self.config['url_epInfo'] % (sid, page), language=language)
if [] is episode_data: if None is episode_data:
raise tvdb_error('Exception retrieving episodes for show') raise tvdb_error('Exception retrieving episodes for show')
if isinstance(episode_data, dict) and episode_data['data'] is not None: if None is not episode_data.get('data'):
episodes.extend(episode_data['data']) episodes.extend(episode_data['data'])
page = episode_data['links']['next'] if isinstance(episode_data, dict) \ page = episode_data.get('links', {}).get('next')
and 'links' in episode_data and 'next' in episode_data['links'] else None
ep_map_keys = {'absolutenumber': u'absolute_number', 'airedepisodenumber': u'episodenumber', ep_map_keys = {'absolutenumber': u'absolute_number', 'airedepisodenumber': u'episodenumber',
'airedseason': u'seasonnumber', 'airedseasonid': u'seasonid', 'airedseason': u'seasonnumber', 'airedseasonid': u'seasonid',

View file

@ -264,6 +264,24 @@ class GenericMetadata():
""" """
return None return None
@staticmethod
def _valid_show(fetched_show_obj, show_obj):
"""
Test the integrity of fetched show data
:param fetched_show_obj: the object returned from the tvinfo source
:type fetched_show_obj: TVShow()
:param show_obj: Show that the fetched data relates to
:type show_obj: TVShow()
:return: True if fetched_show_obj is valid data otherwise False
:rtype: Boolean
"""
if not fetched_show_obj:
logger.log(u'Show %s not found on %s ' %
(show_obj.name, sickbeard.indexerApi(show_obj.indexer).name), logger.WARNING)
return False
return True
def _ep_data(self, ep_obj): def _ep_data(self, ep_obj):
""" """
This should be overridden by the implementing class. It should This should be overridden by the implementing class. It should
@ -789,9 +807,7 @@ class GenericMetadata():
show_obj.indexer).name + ", not downloading images: " + ex(e), logger.ERROR) show_obj.indexer).name + ", not downloading images: " + ex(e), logger.ERROR)
return None return None
if not isinstance(indexer_show_obj, dict) or None is getattr(indexer_show_obj, 'seriesname', None): if not self._valid_show(indexer_show_obj, show_obj):
logger.log(u'Show %s not found on %s ' %
(show_obj.name, sickbeard.indexerApi(show_obj.indexer).name), logger.WARNING)
return None return None
return_links = False return_links = False
@ -851,8 +867,7 @@ class GenericMetadata():
return None return None
@staticmethod def _season_image_dict(self, show_obj, season, image_type):
def _season_image_dict(show_obj, season, image_type):
""" """
image_type : Type of image to fetch, 'seasons' or 'seasonwides' image_type : Type of image to fetch, 'seasons' or 'seasonwides'
image_type type : String image_type type : String
@ -881,9 +896,7 @@ class GenericMetadata():
show_obj.indexer).name + ', not downloading images: ' + ex(e), logger.ERROR) show_obj.indexer).name + ', not downloading images: ' + ex(e), logger.ERROR)
return result return result
if not isinstance(indexer_show_obj, dict) or None is getattr(indexer_show_obj, 'seriesname', None): if not self._valid_show(indexer_show_obj, show_obj):
logger.log(u'Show %s not found on %s ' %
(show_obj.name, sickbeard.indexerApi(show_obj.indexer).name), logger.WARNING)
return result return result
season_images = getattr(indexer_show_obj, '_banners', {}).get( season_images = getattr(indexer_show_obj, '_banners', {}).get(

View file

@ -124,9 +124,7 @@ class KODIMetadata(generic.GenericMetadata):
logger.ERROR) logger.ERROR)
raise raise
if not isinstance(myShow, dict) or None is getattr(myShow, 'seriesname', None): if not self._valid_show(myShow, show_obj):
logger.log(u'Show %s not found on %s ' % (show_obj.name, sickbeard.indexerApi(show_obj.indexer).name),
logger.WARNING)
return return
# check for title and id # check for title and id
@ -246,9 +244,7 @@ class KODIMetadata(generic.GenericMetadata):
ep_obj.show.indexer).name + ' while creating meta files - skipping - ' + ex(e), logger.ERROR) ep_obj.show.indexer).name + ' while creating meta files - skipping - ' + ex(e), logger.ERROR)
return return
if not isinstance(myShow, dict) or None is getattr(myShow, 'seriesname', None): if not self._valid_show(myShow, ep_obj.show):
logger.log(u'Show %s not found on %s ' %
(ep_obj.show.name, sickbeard.indexerApi(ep_obj.show.indexer).name), logger.WARNING)
return return
if len(eps_to_write) > 1: if len(eps_to_write) > 1:

View file

@ -129,9 +129,7 @@ class Mede8erMetadata(mediabrowser.MediaBrowserMetadata):
logger.log(u"TVDB is down, can't use its data to make the NFO", logger.ERROR) logger.log(u"TVDB is down, can't use its data to make the NFO", logger.ERROR)
raise raise
if not isinstance(myShow, dict) or None is getattr(myShow, 'seriesname', None): if not self._valid_show(myShow, show_obj):
logger.log(u'Show %s not found on %s ' % (show_obj.name, sickbeard.indexerApi(show_obj.indexer).name),
logger.WARNING)
return return
# check for title and id # check for title and id
@ -247,9 +245,7 @@ class Mede8erMetadata(mediabrowser.MediaBrowserMetadata):
logger.log(u"Unable to connect to TVDB while creating meta files - skipping - " + ex(e), logger.ERROR) logger.log(u"Unable to connect to TVDB while creating meta files - skipping - " + ex(e), logger.ERROR)
return False return False
if not isinstance(myShow, dict) or None is getattr(myShow, 'seriesname', None): if not self._valid_show(myShow, ep_obj.show):
logger.log(u'Show %s not found on %s ' % (ep_obj.show.name, sickbeard.indexerApi(ep_obj.show.indexer).name),
logger.WARNING)
return return
rootNode = etree.Element("details") rootNode = etree.Element("details")

View file

@ -256,9 +256,7 @@ class MediaBrowserMetadata(generic.GenericMetadata):
logger.ERROR) logger.ERROR)
raise raise
if not isinstance(myShow, dict) or None is getattr(myShow, 'seriesname', None): if not self._valid_show(myShow, show_obj):
logger.log(u'Show %s not found on %s ' % (show_obj.name, sickbeard.indexerApi(show_obj.indexer).name),
logger.WARNING)
return return
# check for title and id # check for title and id
@ -421,9 +419,7 @@ class MediaBrowserMetadata(generic.GenericMetadata):
ep_obj.show.indexer).name + " while creating meta files - skipping - " + ex(e), logger.ERROR) ep_obj.show.indexer).name + " while creating meta files - skipping - " + ex(e), logger.ERROR)
return False return False
if not isinstance(myShow, dict) or None is getattr(myShow, 'seriesname', None): if not self._valid_show(myShow, ep_obj.show):
logger.log(u'Show %s not found on %s ' % (ep_obj.show.name, sickbeard.indexerApi(ep_obj.show.indexer).name),
logger.WARNING)
return return
rootNode = etree.Element("Item") rootNode = etree.Element("Item")

View file

@ -188,9 +188,7 @@ class TIVOMetadata(generic.GenericMetadata):
ep_obj.show.indexer).name + " while creating meta files - skipping - " + str(e), logger.ERROR) ep_obj.show.indexer).name + " while creating meta files - skipping - " + str(e), logger.ERROR)
return False return False
if not isinstance(myShow, dict) or None is getattr(myShow, 'seriesname', None): if not self._valid_show(myShow, ep_obj.show):
logger.log(u'Show %s not found on %s ' % (ep_obj.show.name, sickbeard.indexerApi(ep_obj.show.indexer).name),
logger.WARNING)
return return
for curEpToWrite in eps_to_write: for curEpToWrite in eps_to_write:

View file

@ -199,9 +199,7 @@ class WDTVMetadata(generic.GenericMetadata):
ep_obj.show.indexer).name + " while creating meta files - skipping - " + ex(e), logger.ERROR) ep_obj.show.indexer).name + " while creating meta files - skipping - " + ex(e), logger.ERROR)
return False return False
if not isinstance(myShow, dict) or None is getattr(myShow, 'seriesname', None): if not self._valid_show(myShow, ep_obj.show):
logger.log(u'Show %s not found on %s ' % (ep_obj.show.name, sickbeard.indexerApi(ep_obj.show.indexer).name),
logger.WARNING)
return return
rootNode = etree.Element("details") rootNode = etree.Element("details")

View file

@ -124,9 +124,7 @@ class XBMC_12PlusMetadata(generic.GenericMetadata):
logger.ERROR) logger.ERROR)
raise raise
if not isinstance(myShow, dict) or None is getattr(myShow, 'seriesname', None): if not self._valid_show(myShow, show_obj):
logger.log(u'Show %s not found on %s ' % (show_obj.name, sickbeard.indexerApi(show_obj.indexer).name),
logger.WARNING)
return return
# check for title and id # check for title and id
@ -246,9 +244,7 @@ class XBMC_12PlusMetadata(generic.GenericMetadata):
ep_obj.show.indexer).name + " while creating meta files - skipping - " + ex(e), logger.ERROR) ep_obj.show.indexer).name + " while creating meta files - skipping - " + ex(e), logger.ERROR)
return return
if not isinstance(myShow, dict) or None is getattr(myShow, 'seriesname', None): if not self._valid_show(myShow, ep_obj.show):
logger.log(u'Show %s not found on %s ' % (ep_obj.show.name, sickbeard.indexerApi(ep_obj.show.indexer).name),
logger.WARNING)
return return
if len(eps_to_write) > 1: if len(eps_to_write) > 1:

View file

@ -877,11 +877,17 @@ class TVShow(object):
myDB = db.DBConnection() myDB = db.DBConnection()
sqlResults = myDB.select('SELECT * FROM tv_shows WHERE indexer_id = ?', [self.indexerid]) sqlResults = myDB.select('SELECT * FROM tv_shows WHERE indexer_id = ?', [self.indexerid])
if len(sqlResults) > 1: if 1 != len(sqlResults):
logger.log('%s: Loading show info [%s] from database' % (self.indexerid, self.name)) lINDEXER_API_PARMS = sickbeard.indexerApi(self.indexer).api_params.copy()
raise exceptions.MultipleDBShowsException() if self.lang:
elif len(sqlResults) == 0: lINDEXER_API_PARMS['language'] = self.lang
logger.log('%s: Unable to find the show [%s] in the database' % (self.indexerid, self.name)) t = sickbeard.indexerApi(self.indexer).indexer(**lINDEXER_API_PARMS)
cached_show = t[self.indexerid]
vals = (self.indexerid, '' if not cached_show else ' [%s]' % cached_show['seriesname'].strip())
if 0 != len(sqlResults):
logger.log('%s: Loading show info%s from database' % vals)
raise exceptions.MultipleDBShowsException()
logger.log('%s: Unable to find the show%s in the database' % vals)
return return
else: else:
if not self.indexer: if not self.indexer:
@ -988,8 +994,6 @@ class TVShow(object):
def loadFromIndexer(self, cache=True, tvapi=None, cachedSeason=None): def loadFromIndexer(self, cache=True, tvapi=None, cachedSeason=None):
logger.log('%s: Loading show info [%s] from %s' % (self.indexerid, self.name, sickbeard.indexerApi(self.indexer).name))
# There's gotta be a better way of doing this but we don't wanna # There's gotta be a better way of doing this but we don't wanna
# change the cache value elsewhere # change the cache value elsewhere
if tvapi is None: if tvapi is None:
@ -1025,6 +1029,10 @@ class TVShow(object):
raise sickbeard.indexer_attributenotfound( raise sickbeard.indexer_attributenotfound(
"Found %s, but attribute 'seriesname' was empty." % (self.indexerid)) "Found %s, but attribute 'seriesname' was empty." % (self.indexerid))
if myEp:
logger.log('%s: Loading show info [%s] from %s' % (
self.indexerid, self.name, sickbeard.indexerApi(self.indexer).name))
self.classification = dict_prevent_None(myEp, 'classification', 'Scripted') self.classification = dict_prevent_None(myEp, 'classification', 'Scripted')
self.genre = dict_prevent_None(myEp, 'genre', '') self.genre = dict_prevent_None(myEp, 'genre', '')
self.network = dict_prevent_None(myEp, 'network', '') self.network = dict_prevent_None(myEp, 'network', '')