diff --git a/CHANGES.md b/CHANGES.md index 3bf5b62c..20120ec3 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -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 diff --git a/lib/tvdb_api/tvdb_api.py b/lib/tvdb_api/tvdb_api.py index c0f958f9..9fa54db9 100644 --- a/lib/tvdb_api/tvdb_api.py +++ b/lib/tvdb_api/tvdb_api.py @@ -155,6 +155,9 @@ class Show(dict): # doesn't exist, so attribute error. raise tvdb_attributenotfound('Cannot find attribute %s' % (repr(key))) + def __nonzero__(self): + return any(self.data.keys()) + def aired_on(self, date): ret = self.search(str(date), 'firstaired') if 0 == len(ret): @@ -643,9 +646,15 @@ class Tvdb: """ try: src = self._load_url(url, params=params, language=language) - return src - except (StandardError, Exception): - return [] + if isinstance(src, dict): + data = src['data'] or {} + 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): """Creates a new episode, creating Show(), Season() and @@ -803,7 +812,7 @@ class Tvdb: url = self.config['url_episodeInfo'] % epid 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'] if isinstance(data, dict): for k, v in data.iteritems(): @@ -830,7 +839,7 @@ class Tvdb: show_data = self._getetsrc(url, language=language) # 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 for k, v in show_data['data'].iteritems(): @@ -839,7 +848,7 @@ class Tvdb: p = '' if self.config['posters_enabled']: 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, key=lambda x: (x['ratingsinfo']['average'], x['ratingsinfo']['count'])) p = self.config['url_artworkPrefix'] % poster_data['data'][0]['filename'] @@ -850,7 +859,7 @@ class Tvdb: b = '' if self.config['banners_enabled']: 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, key=lambda x: (x['ratingsinfo']['average'], x['ratingsinfo']['count'])) b = self.config['url_artworkPrefix'] % poster_data['data'][0]['filename'] @@ -860,14 +869,14 @@ class Tvdb: if self.config['seasons_enabled']: 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, key=lambda x: (-1 * tryInt(x['subkey']), x['ratingsinfo']['average'], x['ratingsinfo']['count'])) self._parse_banners(sid, poster_data['data']) if self.config['seasonwides_enabled']: 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, key=lambda x: (-1 * tryInt(x['subkey']), x['ratingsinfo']['average'], x['ratingsinfo']['count'])) self._parse_banners(sid, poster_data['data']) @@ -875,7 +884,7 @@ class Tvdb: f = '' if self.config['fanart_enabled']: 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, key=lambda x: (x['ratingsinfo']['average'], x['ratingsinfo']['count'])) f = self.config['url_artworkPrefix'] % fanart_data['data'][0]['filename'] @@ -885,7 +894,7 @@ class Tvdb: if self.config['actors_enabled']: 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( actor_data['data'], key=lambda x: x['sortorder'])]) self._parse_actors(sid, actor_data['data']) @@ -901,12 +910,11 @@ class Tvdb: episodes = [] while page is not None: 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') - 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']) - page = episode_data['links']['next'] if isinstance(episode_data, dict) \ - and 'links' in episode_data and 'next' in episode_data['links'] else None + page = episode_data.get('links', {}).get('next') ep_map_keys = {'absolutenumber': u'absolute_number', 'airedepisodenumber': u'episodenumber', 'airedseason': u'seasonnumber', 'airedseasonid': u'seasonid', diff --git a/sickbeard/metadata/generic.py b/sickbeard/metadata/generic.py index bacc97bf..bd187594 100644 --- a/sickbeard/metadata/generic.py +++ b/sickbeard/metadata/generic.py @@ -264,6 +264,24 @@ class GenericMetadata(): """ 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): """ 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) return None - if not indexer_show_obj: - logger.log(u'Show %s not found on %s ' % - (show_obj.name, sickbeard.indexerApi(show_obj.indexer).name), logger.WARNING) + if not self._valid_show(indexer_show_obj, show_obj): return None return_links = False @@ -851,8 +867,7 @@ class GenericMetadata(): return None - @staticmethod - def _season_image_dict(show_obj, season, image_type): + def _season_image_dict(self, show_obj, season, image_type): """ image_type : Type of image to fetch, 'seasons' or 'seasonwides' image_type type : String @@ -881,9 +896,7 @@ class GenericMetadata(): show_obj.indexer).name + ', not downloading images: ' + ex(e), logger.ERROR) return result - if not indexer_show_obj: - logger.log(u'Show %s not found on %s ' % - (show_obj.name, sickbeard.indexerApi(show_obj.indexer).name), logger.WARNING) + if not self._valid_show(indexer_show_obj, show_obj): return result season_images = getattr(indexer_show_obj, '_banners', {}).get( diff --git a/sickbeard/metadata/kodi.py b/sickbeard/metadata/kodi.py index e2368414..83e94d9d 100644 --- a/sickbeard/metadata/kodi.py +++ b/sickbeard/metadata/kodi.py @@ -124,9 +124,7 @@ class KODIMetadata(generic.GenericMetadata): logger.ERROR) raise - if not myShow: - logger.log(u'Show %s not found on %s ' % (show_obj.name, sickbeard.indexerApi(show_obj.indexer).name), - logger.WARNING) + if not self._valid_show(myShow, show_obj): return # 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) return - if not myShow: - logger.log(u'Show %s not found on %s ' % - (ep_obj.show.name, sickbeard.indexerApi(ep_obj.show.indexer).name), logger.WARNING) + if not self._valid_show(myShow, ep_obj.show): return if len(eps_to_write) > 1: diff --git a/sickbeard/metadata/mede8er.py b/sickbeard/metadata/mede8er.py index bf8eb71d..089b8156 100644 --- a/sickbeard/metadata/mede8er.py +++ b/sickbeard/metadata/mede8er.py @@ -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) raise - if not myShow: - logger.log(u'Show %s not found on %s ' % (show_obj.name, sickbeard.indexerApi(show_obj.indexer).name), - logger.WARNING) + if not self._valid_show(myShow, show_obj): return # 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) return False - if not myShow: - logger.log(u'Show %s not found on %s ' % (ep_obj.show.name, sickbeard.indexerApi(ep_obj.show.indexer).name), - logger.WARNING) + if not self._valid_show(myShow, ep_obj.show): return rootNode = etree.Element("details") diff --git a/sickbeard/metadata/mediabrowser.py b/sickbeard/metadata/mediabrowser.py index 7ef95e22..b9dd7afb 100644 --- a/sickbeard/metadata/mediabrowser.py +++ b/sickbeard/metadata/mediabrowser.py @@ -256,9 +256,7 @@ class MediaBrowserMetadata(generic.GenericMetadata): logger.ERROR) raise - if not myShow: - logger.log(u'Show %s not found on %s ' % (show_obj.name, sickbeard.indexerApi(show_obj.indexer).name), - logger.WARNING) + if not self._valid_show(myShow, show_obj): return # 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) return False - if not myShow: - logger.log(u'Show %s not found on %s ' % (ep_obj.show.name, sickbeard.indexerApi(ep_obj.show.indexer).name), - logger.WARNING) + if not self._valid_show(myShow, ep_obj.show): return rootNode = etree.Element("Item") diff --git a/sickbeard/metadata/tivo.py b/sickbeard/metadata/tivo.py index 3eae82ce..516452f7 100644 --- a/sickbeard/metadata/tivo.py +++ b/sickbeard/metadata/tivo.py @@ -188,9 +188,7 @@ class TIVOMetadata(generic.GenericMetadata): ep_obj.show.indexer).name + " while creating meta files - skipping - " + str(e), logger.ERROR) return False - if not myShow: - logger.log(u'Show %s not found on %s ' % (ep_obj.show.name, sickbeard.indexerApi(ep_obj.show.indexer).name), - logger.WARNING) + if not self._valid_show(myShow, ep_obj.show): return for curEpToWrite in eps_to_write: diff --git a/sickbeard/metadata/wdtv.py b/sickbeard/metadata/wdtv.py index 00817a90..9fb498aa 100644 --- a/sickbeard/metadata/wdtv.py +++ b/sickbeard/metadata/wdtv.py @@ -199,9 +199,7 @@ class WDTVMetadata(generic.GenericMetadata): ep_obj.show.indexer).name + " while creating meta files - skipping - " + ex(e), logger.ERROR) return False - if not myShow: - logger.log(u'Show %s not found on %s ' % (ep_obj.show.name, sickbeard.indexerApi(ep_obj.show.indexer).name), - logger.WARNING) + if not self._valid_show(myShow, ep_obj.show): return rootNode = etree.Element("details") diff --git a/sickbeard/metadata/xbmc_12plus.py b/sickbeard/metadata/xbmc_12plus.py index 58a3708f..28c86d4a 100644 --- a/sickbeard/metadata/xbmc_12plus.py +++ b/sickbeard/metadata/xbmc_12plus.py @@ -124,9 +124,7 @@ class XBMC_12PlusMetadata(generic.GenericMetadata): logger.ERROR) raise - if not myShow: - logger.log(u'Show %s not found on %s ' % (show_obj.name, sickbeard.indexerApi(show_obj.indexer).name), - logger.WARNING) + if not self._valid_show(myShow, show_obj): return # 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) return - if not myShow: - logger.log(u'Show %s not found on %s ' % (ep_obj.show.name, sickbeard.indexerApi(ep_obj.show.indexer).name), - logger.WARNING) + if not self._valid_show(myShow, ep_obj.show): return if len(eps_to_write) > 1: diff --git a/sickbeard/tv.py b/sickbeard/tv.py index 6957bfb9..79f5264c 100644 --- a/sickbeard/tv.py +++ b/sickbeard/tv.py @@ -877,11 +877,17 @@ class TVShow(object): myDB = db.DBConnection() sqlResults = myDB.select('SELECT * FROM tv_shows WHERE indexer_id = ?', [self.indexerid]) - if len(sqlResults) > 1: - logger.log('%s: Loading show info [%s] from database' % (self.indexerid, self.name)) - raise exceptions.MultipleDBShowsException() - elif len(sqlResults) == 0: - logger.log('%s: Unable to find the show [%s] in the database' % (self.indexerid, self.name)) + if 1 != len(sqlResults): + lINDEXER_API_PARMS = sickbeard.indexerApi(self.indexer).api_params.copy() + if self.lang: + lINDEXER_API_PARMS['language'] = self.lang + 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 else: if not self.indexer: @@ -988,8 +994,6 @@ class TVShow(object): 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 # change the cache value elsewhere if tvapi is None: @@ -1025,6 +1029,10 @@ class TVShow(object): raise sickbeard.indexer_attributenotfound( "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.genre = dict_prevent_None(myEp, 'genre', '') self.network = dict_prevent_None(myEp, 'network', '')