From 5ff18a86524812aa1f33a71bdc8b0118076b5f66 Mon Sep 17 00:00:00 2001 From: JackDandy Date: Sun, 5 Sep 2021 20:10:58 +0100 Subject: [PATCH] Add try_date for use in attempting conversion of unspecified date format types birthdate, deathdate, aired. Change tweaks, remove one warn, order imports. Change tidy up of other warnings, mismatched types, typos, a strange arg issue with deepcopy, and PEP8. Bug fix, bad key in get_item for TVInfoSocialIDs. Fix ambiguities of `show` used in sg versus external uses. Change add cast, crew type mappings Change only take Main Actors, Hosts, Interviewers, Presenters. --- lib/api_imdb/imdb_api.py | 36 +- lib/api_tmdb/tmdb_api.py | 97 ++--- lib/api_trakt/indexerapiinterface.py | 27 +- lib/api_tvdb/tvdb_api.py | 22 +- lib/api_tvdb/tvdb_exceptions.py | 5 +- lib/api_tvmaze/tvmaze_api.py | 38 +- lib/sg_helpers.py | 20 +- lib/tvinfo_base/base.py | 153 ++++--- sickgear/tv.py | 579 ++++++++++++++------------- sickgear/webserve.py | 2 +- 10 files changed, 519 insertions(+), 460 deletions(-) diff --git a/lib/api_imdb/imdb_api.py b/lib/api_imdb/imdb_api.py index 0a97ffe7..2ca183ae 100644 --- a/lib/api_imdb/imdb_api.py +++ b/lib/api_imdb/imdb_api.py @@ -13,12 +13,13 @@ import re from bs4_parser import BS4Parser from exceptions_helper import ex from lib import imdbpie -# from lib.tvinfo_base.exceptions import BaseTVinfoShownotfound -from lib.tvinfo_base import PersonGenders, TVInfoBase, TVInfoIDs, TVInfoCharacter, TVInfoPerson, TVInfoShow, \ - TVINFO_IMDB -# , TVINFO_TMDB, TVINFO_TRAKT, TVINFO_TVDB, TVINFO_TVRAGE, \ -# TVINFO_FACEBOOK, TVINFO_INSTAGRAM, TVINFO_TWITTER, TVINFO_WIKIPEDIA from lib.dateutil.parser import parser +# from lib.tvinfo_base.exceptions import BaseTVinfoShownotfound +from lib.tvinfo_base import ( + TVInfoCharacter, TVInfoPerson, PersonGenders, TVINFO_IMDB, + # TVINFO_FACEBOOK, TVINFO_INSTAGRAM, TVINFO_TMDB, TVINFO_TRAKT, + # TVINFO_TVDB, TVINFO_TVRAGE, TVINFO_TWITTER, TVINFO_WIKIPEDIA, + TVInfoBase, TVInfoIDs, TVInfoShow) from sg_helpers import get_url, try_int from six import iteritems @@ -67,12 +68,13 @@ class IMDbIndexer(TVInfoBase): """ def _make_result_dict(s): imdb_id = try_int(re.search(r'tt(\d+)', s.get('id') or s.get('imdb_id')).group(1), None) - tvs = TVInfoShow() - tvs.seriesname, tvs.id, tvs.firstaired, tvs.genre_list, tvs.overview, tvs.poster, tvs.ids = \ + ti_show = TVInfoShow() + ti_show.seriesname, ti_show.id, ti_show.firstaired, ti_show.genre_list, ti_show.overview, \ + ti_show.poster, ti_show.ids = \ s['title'], imdb_id, s.get('releaseDetails', {}).get('date') or s.get('year'), s.get('genres'), \ s.get('plot', {}).get('outline', {}).get('text'), s.get('image') and s['image'].get('url'), \ TVInfoIDs(imdb=imdb_id) - return tvs + return ti_show results = [] if ids: @@ -112,14 +114,14 @@ class IMDbIndexer(TVInfoBase): if known_for['titleType'] not in ('tvSeries', 'tvMiniSeries'): continue for character in known_for.get('characters') or []: - show = TVInfoShow() - show.id = try_int(re.search(r'(\d+)', known_for.get('id')).group(1)) - show.ids.imdb = show.id - show.seriesname = known_for.get('title') - show.firstaired = known_for.get('year') + ti_show = TVInfoShow() + ti_show.id = try_int(re.search(r'(\d+)', known_for.get('id')).group(1)) + ti_show.ids.imdb = ti_show.id + ti_show.seriesname = known_for.get('title') + ti_show.firstaired = known_for.get('year') characters.append( - TVInfoCharacter(name=character, show=show, - start_year=known_for.get('startYear'), end_year=known_for.get('endYear')) + TVInfoCharacter(name=character, ti_show=ti_show, start_year=known_for.get('startYear'), + end_year=known_for.get('endYear')) ) try: birthdate = person_obj['base']['birthDate'] and tz_p.parse(person_obj['base']['birthDate']).date() @@ -175,7 +177,8 @@ class IMDbIndexer(TVInfoBase): results.append(self._convert_person(cp)) return results - def _get_bio(self, p_id): + @staticmethod + def _get_bio(p_id): try: bio = get_url('https://www.imdb.com/name/nm%07d/bio' % p_id, headers={'Accept-Language': 'en'}) if not bio: @@ -217,4 +220,3 @@ class IMDbIndexer(TVInfoBase): self._set_cache_entry(cache_credits_key, fg) if p: return self._convert_person(p, filmography=fg, bio=bio) - diff --git a/lib/api_tmdb/tmdb_api.py b/lib/api_tmdb/tmdb_api.py index faa41608..0fae662a 100644 --- a/lib/api_tmdb/tmdb_api.py +++ b/lib/api_tmdb/tmdb_api.py @@ -184,9 +184,9 @@ class TmdbIndexer(TVInfoBase): """This searches TMDB for the series name, """ def _make_result_dict(s): - tvs = TVInfoShow() - tvs.seriesname, tvs.id, tvs.seriesid, tvs.firstaired, tvs.genre_list, tvs.overview, tvs.poster, tvs.ids, \ - tvs.language, tvs.popularity, tvs.rating = \ + ti_show = TVInfoShow() + ti_show.seriesname, ti_show.id, ti_show.seriesid, ti_show.firstaired, ti_show.genre_list, \ + ti_show.overview, ti_show.poster, ti_show.ids, ti_show.language, ti_show.popularity, ti_show.rating = \ clean_data(s['name']), s['id'], s['id'], clean_data(s.get('first_air_date')) or None, \ clean_data([self.tv_genres.get(g) for g in s.get('genre_ids') or []]), \ clean_data(s.get('overview')), s.get('poster_path') and '%s%s%s' % ( @@ -197,8 +197,8 @@ class TmdbIndexer(TVInfoBase): imdb=s.get('external_ids') and s['external_ids'].get('imdb_id') and try_int(s['external_ids'].get('imdb_id', '').replace('tt', ''), None)), \ clean_data(s.get('original_language')), s.get('popularity'), s.get('vote_average') - tvs.genre = '|'.join(tvs.genre_list or []) - return tvs + ti_show.genre = '|'.join(ti_show.genre_list or []) + return ti_show results = [] if ids: @@ -267,14 +267,14 @@ class TmdbIndexer(TVInfoBase): characters = [] for character in cast or []: - show = TVInfoShow() - show.id = character.get('id') - show.ids = TVInfoIDs(ids={TVINFO_TMDB: show.id}) - show.seriesname = clean_data(character.get('original_name')) - show.overview = clean_data(character.get('overview')) - show.firstaired = clean_data(character.get('first_air_date')) + ti_show = TVInfoShow() + ti_show.id = character.get('id') + ti_show.ids = TVInfoIDs(ids={TVINFO_TMDB: ti_show.id}) + ti_show.seriesname = clean_data(character.get('original_name')) + ti_show.overview = clean_data(character.get('overview')) + ti_show.firstaired = clean_data(character.get('first_air_date')) characters.append( - TVInfoCharacter(name=clean_data(character.get('character')), show=show) + TVInfoCharacter(name=clean_data(character.get('character')), show=ti_show) ) pi = person_obj.get('images') @@ -408,31 +408,32 @@ class TmdbIndexer(TVInfoBase): def _convert_show(self, show_dict, show_obj=None): # type: (Dict, TVInfoShow) -> TVInfoShow if None is show_obj: - tv_s = TVInfoShow() + ti_show = TVInfoShow() else: - tv_s = show_obj + ti_show = show_obj if show_dict: - tv_s.seriesname = clean_data(show_dict.get('name') or show_dict.get('original_name') - or show_dict.get('original_title')) + ti_show.seriesname = clean_data(show_dict.get('name') or show_dict.get('original_name') + or show_dict.get('original_title')) org_title = clean_data(show_dict.get('original_name') or show_dict.get('original_title')) - if org_title != tv_s.seriesname: - tv_s.aliases = [org_title] - tv_s.id = show_dict.get('id') - tv_s.seriesid = tv_s.id - tv_s.language = clean_data(show_dict.get('original_language')) - tv_s.overview = clean_data(show_dict.get('overview')) - tv_s.status = clean_data(show_dict.get('status', '')) - tv_s.show_type = clean_data((show_dict.get('type') and [show_dict['type']]) or []) - tv_s.firstaired = clean_data(show_dict.get('first_air_date')) - tv_s.vote_count = show_dict.get('vote_count') - tv_s.vote_average = show_dict.get('vote_average') - tv_s.popularity = show_dict.get('popularity') - tv_s.origin_countries = clean_data(show_dict.get('origin_country') or []) - tv_s.genre_list = [] + if org_title != ti_show.seriesname: + ti_show.aliases = [org_title] + ti_show.id = show_dict.get('id') + ti_show.seriesid = ti_show.id + ti_show.language = clean_data(show_dict.get('original_language')) + ti_show.overview = clean_data(show_dict.get('overview')) + ti_show.status = clean_data(show_dict.get('status', '')) + ti_show.show_type = clean_data((show_dict.get('type') and [show_dict['type']]) or []) + ti_show.firstaired = clean_data(show_dict.get('first_air_date')) + ti_show.popularity = show_dict.get('popularity') + ti_show.vote_count = show_dict.get('vote_count') + ti_show.vote_average = show_dict.get('vote_average') + ti_show.origin_countries = show_dict.get('origin_country') or [] + ti_show.genre_list = [] + ti_show.origin_countries = clean_data(show_dict.get('origin_country') or []) for g in show_dict.get('genre_ids') or []: if g in self.tv_genres: - tv_s.genre_list.append(self.tv_genres.get(g)) - tv_s.genre = '|'.join(tv_s.genre_list) + ti_show.genre_list.append(self.tv_genres.get(g)) + ti_show.genre = '|'.join(ti_show.genre_list) runtime = None for r in sorted(show_dict.get('episode_run_time') or [], reverse=True): if 40 < r < 50: @@ -443,18 +444,18 @@ class TmdbIndexer(TVInfoBase): break if not runtime and show_dict.get('episode_run_time'): runtime = max(show_dict.get('episode_run_time') or [0]) or None - tv_s.runtime = runtime + ti_show.runtime = runtime - tv_s.networks = [ + ti_show.networks = [ TVInfoNetwork(name=clean_data(n.get('name')), n_id=n.get('id'), country_code=clean_data(n.get('origin_country'))) for n in reversed(show_dict.get('networks') or []) ] if show_dict.get('networks'): - tv_s.network = clean_data(show_dict['networks'][-1]['name']) - tv_s.network_id = show_dict['networks'][-1].get('id') - tv_s.network_country_code = clean_data(show_dict['networks'][-1].get('origin_country')) + ti_show.network = clean_data(show_dict['networks'][-1]['name']) + ti_show.network_id = show_dict['networks'][-1].get('id') + ti_show.network_country_code = clean_data(show_dict['networks'][-1].get('origin_country')) image_url = show_dict.get('poster_path') and '%s%s%s' % \ (self.img_base_url, self.size_map[TVInfoImageType.poster][TVInfoImageSize.original], @@ -465,19 +466,19 @@ class TmdbIndexer(TVInfoBase): backdrop_url = show_dict.get('backdrop_path') and '%s%s%s' % \ (self.img_base_url, self.size_map[TVInfoImageType.fanart][TVInfoImageSize.original], show_dict.get('backdrop_path')) - tv_s.ids = TVInfoIDs(tvdb=show_dict.get('external_ids', {}).get('tvdb_id'), + ti_show.ids = TVInfoIDs(tvdb=show_dict.get('external_ids', {}).get('tvdb_id'), tmdb=show_dict['id'], rage=show_dict.get('external_ids', {}).get('tvrage_id'), imdb=show_dict.get('external_ids', {}).get('imdb_id') and try_int(show_dict.get('external_ids', {}).get('imdb_id', '').replace('tt', ''), None)) - tv_s.social_ids = TVInfoSocialIDs(twitter=show_dict.get('external_ids', {}).get('twitter_id'), + ti_show.social_ids = TVInfoSocialIDs(twitter=show_dict.get('external_ids', {}).get('twitter_id'), instagram=show_dict.get('external_ids', {}).get('instagram_id'), facebook=show_dict.get('external_ids', {}).get('facebook_id')) - tv_s.poster = image_url - tv_s.poster_thumb = thumb_image_url - tv_s.fanart = backdrop_url - return tv_s + ti_show.poster = image_url + ti_show.poster_thumb = thumb_image_url + ti_show.fanart = backdrop_url + return ti_show def _get_show_list(self, src_method, result_count, **kwargs): result = [] @@ -606,9 +607,9 @@ class TmdbIndexer(TVInfoBase): tmdb_lang = ('en-US', language)[language in self._tmdb_supported_lang_list] if any((banners, posters, seasons, seasonwides, fanart)): to_append.append('images') - if (actors or self.config['actors_enabled']) and not getattr(self.shows.get(sid), 'actors_loaded', False): + if (actors or self.config['actors_enabled']) and not getattr(self.ti_shows.get(sid), 'actors_loaded', False): to_append.append('aggregate_credits') - if get_ep_info and not getattr(self.shows.get(sid), 'ep_loaded', False): + if get_ep_info and not getattr(self.ti_shows.get(sid), 'ep_loaded', False): to_append.append('episode_groups') try: tmdb = tmdbsimple.TV(sid) @@ -624,7 +625,7 @@ class TmdbIndexer(TVInfoBase): self.show_not_found = True return False - show_obj = self.shows[sid] + show_obj = self.ti_shows[sid] self._convert_show(show_data, show_obj) @@ -656,7 +657,7 @@ class TmdbIndexer(TVInfoBase): ) season_cast_objs = {} - if (actors or self.config['actors_enabled']) and not getattr(self.shows.get(sid), 'actors_loaded', False): + if (actors or self.config['actors_enabled']) and not getattr(self.ti_shows.get(sid), 'actors_loaded', False): cast, show_obj.actors_loaded = CastList(), True if isinstance(show_data.get('aggregate_credits'), dict) and 'cast' in show_data['aggregate_credits'] and\ isinstance(show_data['aggregate_credits']['cast'], list): @@ -723,7 +724,7 @@ class TmdbIndexer(TVInfoBase): }, } for ch in cast[RoleTypes.ActorMain]] - if get_ep_info and not getattr(self.shows.get(sid), 'ep_loaded', False): + if get_ep_info and not getattr(self.ti_shows.get(sid), 'ep_loaded', False): show_obj.ep_loaded = True seasons = ['season/%d' % s['season_number'] for s in show_data.get('seasons') or []] # call limited to 20 seasons per call diff --git a/lib/api_trakt/indexerapiinterface.py b/lib/api_trakt/indexerapiinterface.py index 29238bb7..a73d62fd 100644 --- a/lib/api_trakt/indexerapiinterface.py +++ b/lib/api_trakt/indexerapiinterface.py @@ -292,24 +292,21 @@ class TraktIndexer(TVInfoBase): if show_credits: pc = [] for c in resp.get('cast') or []: - show = TVInfoShow() - show.id = c['show']['ids'].get('trakt') - show.seriesname = c['show']['title'] - show.ids = TVInfoIDs(ids={id_map[src]: _convert_imdb_id(id_map[src], sid) + ti_show = TVInfoShow() + ti_show.id = c['show']['ids'].get('trakt') + ti_show.seriesname = c['show']['title'] + ti_show.ids = TVInfoIDs(ids={id_map[src]: _convert_imdb_id(id_map[src], sid) for src, sid in iteritems(c['show']['ids']) if src in id_map}) - show.network = c['show']['network'] - show.firstaired = c['show']['first_aired'] - show.overview = c['show']['overview'] - show.status = c['show']['status'] - show.imdb_id = c['show']['ids'].get('imdb') - show.runtime = c['show']['runtime'] - show.genre_list = c['show']['genres'] + ti_show.network = c['show']['network'] + ti_show.firstaired = c['show']['first_aired'] + ti_show.overview = c['show']['overview'] + ti_show.status = c['show']['status'] + ti_show.imdb_id = c['show']['ids'].get('imdb') + ti_show.runtime = c['show']['runtime'] + ti_show.genre_list = c['show']['genres'] for ch in c.get('characters') or []: pc.append( - TVInfoCharacter( - name=ch, regular=c.get('series_regular'), - show=show - ) + TVInfoCharacter(name=ch, regular=c.get('series_regular'), ti_show=ti_show) ) result.characters = pc else: diff --git a/lib/api_tvdb/tvdb_api.py b/lib/api_tvdb/tvdb_api.py index 3edf1eb0..82a5d950 100644 --- a/lib/api_tvdb/tvdb_api.py +++ b/lib/api_tvdb/tvdb_api.py @@ -52,7 +52,7 @@ log = logging.getLogger('tvdb.api') log.addHandler(logging.NullHandler()) -# noinspection PyUnusedLocal +# noinspection HttpUrlsUsage,PyUnusedLocal def _record_hook(r, *args, **kwargs): r.hook_called = True if 301 == r.status_code and isinstance(r.headers.get('Location'), string_types) \ @@ -64,8 +64,8 @@ def _record_hook(r, *args, **kwargs): def retry(exception_to_check, tries=4, delay=3, backoff=2): """Retry calling the decorated function using an exponential backoff. - http://www.saltycrane.com/blog/2009/11/trying-out-retry-decorator-python/ - original from: http://wiki.python.org/moin/PythonDecoratorLibrary#Retry + www.saltycrane.com/blog/2009/11/trying-out-retry-decorator-python/ + original from: wiki.python.org/moin/PythonDecoratorLibrary#Retry :param exception_to_check: the exception to check. may be a tuple of exceptions to check @@ -222,7 +222,7 @@ class Tvdb(TVInfoBase): tvdb_api's own key (fine for small scripts), but you can use your own key if desired - this is recommended if you are embedding tvdb_api in a larger application) - See http://thetvdb.com/?tab=apiregister to get your own key + See thetvdb.com/?tab=apiregister to get your own key """ @@ -976,7 +976,7 @@ class Tvdb(TVInfoBase): pass self._set_show_data(sid, 'actors', a) self._set_show_data(sid, 'cast', cast) - self.shows[sid].actors_loaded = True + self.ti_shows[sid].actors_loaded = True def get_episode_data(self, epid): # Parse episode information @@ -1004,7 +1004,7 @@ class Tvdb(TVInfoBase): mapped_img_types = {'banner': 'series'} excluded_main_data = enabled_type in ['seasons_enabled', 'seasonwides_enabled'] loaded_name = '%s_loaded' % image_type - if (type_bool or self.config[enabled_type]) and not getattr(self.shows.get(sid), loaded_name, False): + if (type_bool or self.config[enabled_type]) and not getattr(self.ti_shows.get(sid), loaded_name, False): image_data = self._getetsrc(self.config['url_series_images'] % (sid, mapped_img_types.get(image_type, image_type)), language=language) if image_data and 0 < len(image_data.get('data', '') or ''): @@ -1017,7 +1017,7 @@ class Tvdb(TVInfoBase): self._set_show_data(sid, f'{image_type}_thumb', url_thumb) excluded_main_data = True # artwork found so prevent fallback self._parse_banners(sid, image_data['data']) - self.shows[sid].__dict__[loaded_name] = True + self.ti_shows[sid].__dict__[loaded_name] = True # fallback image thumbnail for none excluded_main_data if artwork is not found if not excluded_main_data and show_data['data'].get(image_type): @@ -1073,13 +1073,13 @@ class Tvdb(TVInfoBase): ('seasonwide', 'seasonwides_enabled', seasonwides)]: self._parse_images(sid, language, show_data, img_type, en_type, p_type) - if (actors or self.config['actors_enabled']) and not getattr(self.shows.get(sid), 'actors_loaded', False): + if (actors or self.config['actors_enabled']) and not getattr(self.ti_shows.get(sid), 'actors_loaded', False): actor_data = self._getetsrc(self.config['url_actors_info'] % sid, language=language) actor_data_alt = self._getetsrc(self.config['url_series_people'] % sid, language=language) if actor_data and 0 < len(actor_data.get('data', '') or '') or actor_data_alt and actor_data_alt['data']: self._parse_actors(sid, actor_data and actor_data.get('data', ''), actor_data_alt and actor_data_alt['data']) - if get_ep_info and not getattr(self.shows.get(sid), 'ep_loaded', False): + if get_ep_info and not getattr(self.ti_shows.get(sid), 'ep_loaded', False): # Parse episode data log.debug('Getting all episodes of %s' % sid) @@ -1200,7 +1200,7 @@ class Tvdb(TVInfoBase): ep_no = int(float(elem_epno)) if not cur_ep.get('network'): - cur_ep['network'] = self.shows[sid].network + cur_ep['network'] = self.ti_shows[sid].network for k, v in iteritems(cur_ep): k = k.lower() @@ -1236,7 +1236,7 @@ class Tvdb(TVInfoBase): self._set_item(sid, seas_no, ep_no, 'crew', crew) self._set_item(sid, seas_no, ep_no, 'cast', cast) - self.shows[sid].ep_loaded = True + self.ti_shows[sid].ep_loaded = True return True diff --git a/lib/api_tvdb/tvdb_exceptions.py b/lib/api_tvdb/tvdb_exceptions.py index db2ab4c8..70c6a8e7 100644 --- a/lib/api_tvdb/tvdb_exceptions.py +++ b/lib/api_tvdb/tvdb_exceptions.py @@ -11,7 +11,7 @@ __author__ = 'dbr/Ben' __version__ = '1.9' __all__ = ['TvdbException', 'TvdbError', 'TvdbUserabort', 'TvdbShownotfound', - 'TvdbSeasonnotfound', 'TvdbEpisodenotfound', 'TvdbAttributenotfound', 'TvdbTokenexpired', 'TvdbTokenFailre'] + 'TvdbSeasonnotfound', 'TvdbEpisodenotfound', 'TvdbAttributenotfound', 'TvdbTokenexpired', 'TvdbTokenFailure'] from lib.tvinfo_base.exceptions import * @@ -66,8 +66,7 @@ class TvdbTokenexpired(BaseTVinfoAuthenticationerror, TvdbError): pass -class TvdbTokenFailre(BaseTVinfoAuthenticationerror, TvdbError): +class TvdbTokenFailure(BaseTVinfoAuthenticationerror, TvdbError): """getting token failed """ pass - diff --git a/lib/api_tvmaze/tvmaze_api.py b/lib/api_tvmaze/tvmaze_api.py index 76cec287..4c927aeb 100644 --- a/lib/api_tvmaze/tvmaze_api.py +++ b/lib/api_tvmaze/tvmaze_api.py @@ -16,7 +16,7 @@ from requests.adapters import HTTPAdapter from tornado._locale_data import LOCALE_NAMES from urllib3.util.retry import Retry -from sg_helpers import clean_data, get_url, try_int +from sg_helpers import clean_data, enforce_type, get_url, try_int from lib.dateutil.parser import parser # noinspection PyProtectedMember from lib.dateutil.tz.tz import _datetime_to_timestamp @@ -317,7 +317,7 @@ class TvMaze(TVInfoBase): if not show_data: return False - ti_show = self.shows[sid] # type: TVInfoShow + ti_show = self.ti_shows[sid] # type: TVInfoShow show_obj = ti_show.__dict__ for k, v in iteritems(show_obj): if k not in ('cast', 'crew', 'images', 'aliases'): @@ -354,7 +354,7 @@ class TvMaze(TVInfoBase): if show_data.genres: ti_show.genre = '|'.join(show_data.genres).lower() - if (actors or self.config['actors_enabled']) and not getattr(self.shows.get(sid), 'actors_loaded', False): + if (actors or self.config['actors_enabled']) and not getattr(self.ti_shows.get(sid), 'actors_loaded', False): if show_data.cast: character_person_ids = {} for cur_ch in ti_show.cast[RoleTypes.ActorMain]: @@ -450,7 +450,7 @@ class TvMaze(TVInfoBase): elif show_data.web_channel: self._set_network(ti_show, show_data.web_channel, True) - if get_ep_info and not getattr(self.shows.get(sid), 'ep_loaded', False): + if get_ep_info and not getattr(self.ti_shows.get(sid), 'ep_loaded', False): log.debug('Getting all episodes of %s' % sid) if None is show_data: show_data = self._get_tvm_show(sid, get_ep_info) @@ -513,23 +513,23 @@ class TvMaze(TVInfoBase): def _convert_person(person_obj): # type: (tvmaze.Person) -> TVInfoPerson ch = [] - for c in person_obj.castcredits or []: - show = TVInfoShow() - show.seriesname = clean_data(c.show.name) - show.id = c.show.id - show.firstaired = clean_data(c.show.premiered) - show.ids = TVInfoIDs(ids={TVINFO_TVMAZE: show.id}) - show.overview = clean_data(c.show.summary) - show.status = clean_data(c.show.status) + for c in tvmaze_person_obj.castcredits or []: + ti_show = TVInfoShow() + ti_show.seriesname = clean_data(c.show.name) + ti_show.id = c.show.id + ti_show.firstaired = clean_data(c.show.premiered) + ti_show.ids = TVInfoIDs(ids={TVINFO_TVMAZE: ti_show.id}) + ti_show.overview = clean_data(c.show.summary) + ti_show.status = clean_data(c.show.status) net = c.show.network or c.show.web_channel if net: - show.network = clean_data(net.name) - show.network_id = net.maze_id - show.network_country = clean_data(net.country) - show.network_timezone = clean_data(net.timezone) - show.network_country_code = clean_data(net.code) - show.network_is_stream = None is not c.show.web_channel - ch.append(TVInfoCharacter(name=clean_data(c.character.name), show=show)) + ti_show.network = clean_data(net.name) + ti_show.network_id = net.maze_id + ti_show.network_country = clean_data(net.country) + ti_show.network_country_code = clean_data(net.code) + ti_show.network_timezone = clean_data(net.timezone) + ti_show.network_is_stream = None is not c.show.web_channel + ch.append(TVInfoCharacter(name=clean_data(c.character.name), ti_show=ti_show, episode_count=1)) try: birthdate = person_obj.birthday and tz_p.parse(person_obj.birthday).date() except (BaseException, Exception): diff --git a/lib/sg_helpers.py b/lib/sg_helpers.py index 6111a441..59b725a6 100644 --- a/lib/sg_helpers.py +++ b/lib/sg_helpers.py @@ -25,6 +25,7 @@ import unicodedata from exceptions_helper import ex, ConnectionSkipException from json_helper import json_loads from cachecontrol import CacheControl, caches +from lib.dateutil.parser import parser # from lib.tmdbsimple.configuration import Configuration # from lib.tmdbsimple.genres import Genres from cfscrape import CloudflareScraper @@ -41,6 +42,7 @@ from six import integer_types, iteritems, iterkeys, itervalues, moves, PY2, stri import zipfile # py7z hardwired removed, see comment below py7zr = None +tz_p = parser() # noinspection PyUnreachableCode if False: @@ -634,6 +636,21 @@ def try_int(s, s_default=0): return s_default +def try_date(s, s_default=None): + # type: (AnyStr, Any) -> Optional[AnyStr] + """ + Convert string to a standard UTC date string + :param s: + :param s_default: + :return: + """ + try: + parse = tz_p.parse(clean_data(s)) + return '%04d-%02d-%02d' % (parse.year, parse.month, parse.day) + except(BaseException, Exception): + return s_default + + def _maybe_request_url(e, def_url=''): return hasattr(e, 'request') and hasattr(e.request, 'url') and ' ' + e.request.url or def_url @@ -644,6 +661,7 @@ def clean_data(data): Issues corrected: - Replaces & with & + - Replace multiple spaces with one space - Trailing whitespace - Decode html entities :param data: data @@ -659,7 +677,7 @@ def clean_data(data): if isinstance(data, dict): return {k: clean_data(v) for k, v in iteritems(data)} if isinstance(data, string_types): - return unicodedata.normalize('NFKD', html_unescape(data).strip().replace('&', '&')) + return unicodedata.normalize('NFKD', re.sub(r' {2,}', ' ', html_unescape(data).strip().replace('&', '&'))) return data diff --git a/lib/tvinfo_base/base.py b/lib/tvinfo_base/base.py index 793f196e..b2cfe13e 100644 --- a/lib/tvinfo_base/base.py +++ b/lib/tvinfo_base/base.py @@ -70,7 +70,7 @@ tv_src_names = { log = logging.getLogger('TVInfo') log.addHandler(logging.NullHandler()) -TVInfoShowContainer = {} # type: Dict[str, ShowContainer] +TVInfoShowContainer = {} # type: Union[ShowContainer, Dict] class ShowContainer(dict): @@ -158,9 +158,16 @@ class TVInfoIDs(object): class TVInfoSocialIDs(object): - def __init__(self, twitter=None, instagram=None, facebook=None, wikipedia=None, ids=None, reddit=None, - youtube=None): - # type: (str_int, str_int, str_int, str_int, Dict[int, str_int], str_int, str) -> None + def __init__( + self, + twitter=None, # type: str_int + instagram=None, # type: str_int + facebook=None, # type: str_int + wikipedia=None, # type: str_int + ids=None, # type: Dict[int, str_int] + reddit=None, # type: str_int + youtube=None # type: AnyStr + ): ids = ids or {} self.twitter = twitter or ids.get(TVINFO_TWITTER) self.instagram = instagram or ids.get(TVINFO_INSTAGRAM) @@ -171,7 +178,7 @@ class TVInfoSocialIDs(object): def __getitem__(self, key): return {TVINFO_TWITTER: self.twitter, TVINFO_INSTAGRAM: self.instagram, TVINFO_FACEBOOK: self.facebook, - TVINFO_WIKIPEDIA: self.wikipedia, TVINFO_REDDIT: self.reddit, TVINFO_TWITTER: self.youtube}.get(key) + TVINFO_WIKIPEDIA: self.wikipedia, TVINFO_REDDIT: self.reddit, TVINFO_YOUTUBE: self.youtube}.get(key) def __iter__(self): for s, v in [(TVINFO_TWITTER, self.twitter), (TVINFO_INSTAGRAM, self.instagram), @@ -238,7 +245,7 @@ class TVInfoImage(object): lang=None, height=None, width=None, aspect_ratio=None): self.img_id = img_id # type: Optional[integer_types] self.image_type = image_type # type: integer_types - self.sizes = sizes # type: Dict[int, AnyStr] + self.sizes = sizes # type: Union[TVInfoImageSize, Dict] self.type_str = type_str # type: AnyStr self.main_image = main_image # type: bool self.rating = rating # type: Optional[Union[float, integer_types]] @@ -392,6 +399,8 @@ class TVInfoShow(dict): setattr(result, k, copy.deepcopy(v, memo)) for k, v in self.items(): result[k] = copy.deepcopy(v, memo) + if isinstance(k, integer_types): + setattr(result[k], 'show', result) return result def __bool__(self): @@ -484,9 +493,12 @@ class TVInfoSeason(dict): result = cls.__new__(cls) memo[id(self)] = result for k, v in self.__dict__.items(): + # noinspection PyArgumentList setattr(result, k, copy.deepcopy(v, memo)) for k, v in self.items(): result[k] = copy.deepcopy(v, memo) + if isinstance(k, integer_types): + setattr(result[k], 'season', result) return result def search(self, term=None, key=None): @@ -580,6 +592,7 @@ class TVInfoEpisode(dict): result = cls.__new__(cls) memo[id(self)] = result for k, v in self.__dict__.items(): + # noinspection PyArgumentList setattr(result, k, copy.deepcopy(v, memo)) for k, v in self.items(): result[k] = copy.deepcopy(v, memo) @@ -671,12 +684,12 @@ class PersonBase(dict): sortorder """ def __init__( - self, # type: + self, p_id=None, # type: integer_types name=None, # type: AnyStr image=None, # type: AnyStr images=None, # type: List[TVInfoImage] - gender=None, # type: int + gender=None, # type: integer_types bio=None, # type: AnyStr birthdate=None, # type: datetime.date deathdate=None, # type: datetime.date @@ -758,7 +771,7 @@ class TVInfoPerson(PersonBase): image=None, # type: Optional[AnyStr] images=None, # type: List[TVInfoImage] thumb_url=None, # type: AnyStr - gender=None, # type: int + gender=None, # type: integer_types bio=None, # type: AnyStr birthdate=None, # type: datetime.date deathdate=None, # type: datetime.date @@ -766,13 +779,13 @@ class TVInfoPerson(PersonBase): country_code=None, # type: AnyStr country_timezone=None, # type: AnyStr ids=None, # type: Dict - homepage=None, # type: AnyStr + homepage=None, # type: Optional[AnyStr] social_ids=None, # type: Dict birthplace=None, # type: AnyStr + deathplace=None, # type: AnyStr url=None, # type: AnyStr characters=None, # type: List[TVInfoCharacter] height=None, # type: Union[integer_types, float] - deathplace=None, # type: AnyStr nicknames=None, # type: Set[AnyStr] real_name=None, # type: AnyStr akas=None, # type: Set[AnyStr] @@ -801,7 +814,7 @@ class TVInfoPerson(PersonBase): class TVInfoCharacter(PersonBase): - def __init__(self, person=None, voice=None, plays_self=None, regular=None, show=None, start_year=None, + def __init__(self, person=None, voice=None, plays_self=None, regular=None, ti_show=None, start_year=None, end_year=None, **kwargs): # type: (List[TVInfoPerson], bool, bool, bool, TVInfoShow, int, int, Dict) -> None super(TVInfoCharacter, self).__init__(**kwargs) @@ -809,7 +822,7 @@ class TVInfoCharacter(PersonBase): self.voice = voice # type: Optional[bool] self.plays_self = plays_self # type: Optional[bool] self.regular = regular # type: Optional[bool] - self.show = show # type: Optional[TVInfoShow] + self.ti_show = ti_show # type: Optional[TVInfoShow] self.start_year = start_year # type: Optional[integer_types] self.end_year = end_year # type: Optional[integer_types] @@ -857,12 +870,21 @@ class RoleTypes(object): CrewShowrunner = 72 CrewOther = 100 - reverse = {1: 'Main', 2: 'Recurring', 3: 'Guest', 4: 'Special Guest', 50: 'Director', 51: 'Writer', 52: 'Producer', - 53: 'Executive Producer', 60: 'Creator', 61: 'Editor', 62: 'Camera', 63: 'Music', 64: 'Stylist', - 65: 'Makeup', 66: 'Photography', 67: 'Sound', 68: 'Designer', 69: 'Developer', 70: 'Animation', - 71: 'Visual Effects', 100: 'Other'} + reverse = {1: 'Main', 2: 'Recurring', 3: 'Guest', 4: 'Special Guest', 10: 'Host', 11: 'Host Guest', + 12: 'Presenter', 13: 'Presenter Guest', 14: 'Interviewer', 15: 'Interviewer Guest', + 16: 'Musical Guest', 50: 'Director', 51: 'Writer', 52: 'Producer', 53: 'Executive Producer', + 60: 'Creator', 61: 'Editor', 62: 'Camera', 63: 'Music', 64: 'Stylist', 65: 'Makeup', + 66: 'Photography', 67: 'Sound', 68: 'Designer', 69: 'Developer', 70: 'Animation', + 71: 'Visual Effects', 72: 'Showrunner', 100: 'Other'} crew_limit = 50 + # just a helper to generate the reverse data + # def __init__(self): + # import re + # {value: re.sub(r'([a-z])([A-Z])', r'\1 \2', name.replace('Actor', '').replace('Crew', '')) + # for name, value in iteritems(vars(RoleTypes)) if not name.startswith('_') + # and name not in ('reverse', 'crew_limit')} + crew_type_names = {c.lower(): v for v, c in iteritems(RoleTypes.reverse) if v >= RoleTypes.crew_limit} @@ -882,8 +904,8 @@ class TVInfoBase(object): global TVInfoShowContainer if self.__class__.__name__ not in TVInfoShowContainer: TVInfoShowContainer[self.__class__.__name__] = ShowContainer() - self.shows = TVInfoShowContainer[self.__class__.__name__] # type: ShowContainer[integer_types, TVInfoShow] - self.shows.cleanup_old() + self.ti_shows = TVInfoShowContainer[self.__class__.__name__] # type: ShowContainer[integer_types, TVInfoShow] + self.ti_shows.cleanup_old() self.lang = None # type: Optional[AnyStr] self.corrections = {} # type: Dict self.show_not_found = False # type: bool @@ -929,10 +951,10 @@ class TVInfoBase(object): :param actors: should load actors :param lang: requested language """ - if sid not in self.shows or None is self.shows[sid].id or \ - (load_episodes and not getattr(self.shows[sid], 'ep_loaded', False)): + if sid not in self.ti_shows or None is self.ti_shows[sid].id or \ + (load_episodes and not getattr(self.ti_shows[sid], 'ep_loaded', False)): return True - _show = self.shows[sid] # type: TVInfoShow + _show = self.ti_shows[sid] # type: TVInfoShow if _show.requested_language != lang: _show.ep_loaded = _show.poster_loaded = _show.banner_loaded = _show.actors_loaded = _show.fanart_loaded = \ _show.seasonwide_images_loaded = _show.season_images_loaded = False @@ -1088,8 +1110,9 @@ class TVInfoBase(object): actors=False, # type: bool old_call=False, # type: bool language=None, # type: AnyStr - **kwargs # type: Optional[Any] - ): # type: (...) -> Optional[TVInfoShow] + # **kwargs # type: dict + ): + # type: (...) -> Optional[TVInfoShow] """ get data for show id :param show_id: id of show @@ -1109,33 +1132,33 @@ class TVInfoBase(object): self.config.update({'banners_enabled': banners, 'posters_enabled': posters, 'seasons_enabled': seasons, 'seasonwides_enabled': seasonwides, 'fanart_enabled': fanart, 'actors_enabled': actors, 'language': language or 'en'}) - self.shows.lock.acquire() + self.ti_shows.lock.acquire() try: - if show_id not in self.shows: - self.shows[show_id] = TVInfoShow() # type: TVInfoShow - with self.shows[show_id].lock: - self.shows.lock.release() + if show_id not in self.ti_shows: + self.ti_shows[show_id] = TVInfoShow() # type: TVInfoShow + with self.ti_shows[show_id].lock: + self.ti_shows.lock.release() try: if self._must_load_data(show_id, load_episodes, banners, posters, seasons, seasonwides, fanart, actors, self.config['language']): - self.shows[show_id].requested_language = self.config['language'] + self.ti_shows[show_id].requested_language = self.config['language'] self._get_show_data(show_id, self.map_languages.get(self.config['language'], self.config['language']), load_episodes, banners, posters, seasons, seasonwides, fanart, actors) - if None is self.shows[show_id].id: - with self.shows.lock: - del self.shows[show_id] - return None if show_id not in self.shows else copy.deepcopy(self.shows[show_id]) + if None is self.ti_shows[show_id].id: + with self.ti_shows.lock: + del self.ti_shows[show_id] + return None if show_id not in self.ti_shows else copy.deepcopy(self.ti_shows[show_id]) finally: try: - if None is self.shows[show_id].id: - with self.shows.lock: - del self.shows[show_id] + if None is self.ti_shows[show_id].id: + with self.ti_shows.lock: + del self.ti_shows[show_id] except (BaseException, Exception): pass finally: try: - self.shows.lock.release() + self.ti_shows.lock.release() except RuntimeError: pass if not old_call and None is not self._old_config: @@ -1163,8 +1186,13 @@ class TVInfoBase(object): return names return name - def search_show(self, name=None, ids=None, **kwargs): - # type: (Union[AnyStr, List[AnyStr]], Dict[integer_types, integer_types], Optional[Any]) -> List[Dict] + def search_show( + self, + name=None, # type: Union[AnyStr, List[AnyStr]] + ids=None, # type: Dict[integer_types, integer_types] + # **kwargs # type: Optional[Any] + ): + # type: (...) -> List[Dict] """ search for series with name(s) or ids @@ -1206,41 +1234,41 @@ class TVInfoBase(object): calls __getitem__ on tvinfo[1], there is no way to check if tvinfo.__dict__ should have a key "1" before we auto-create it """ - # if sid not in self.shows: - # self.shows[sid] = TVInfoShow() - if seas not in self.shows[sid]: - self.shows[sid][seas] = TVInfoSeason(show=self.shows[sid]) - self.shows[sid][seas].number = seas - if ep not in self.shows[sid][seas]: - self.shows[sid][seas][ep] = TVInfoEpisode(season=self.shows[sid][seas], show=self.shows[sid]) + # if sid not in self.ti_shows: + # self.ti_shows[sid] = TVInfoShow() + if seas not in self.ti_shows[sid]: + self.ti_shows[sid][seas] = TVInfoSeason(show=self.ti_shows[sid]) + self.ti_shows[sid][seas].number = seas + if ep not in self.ti_shows[sid][seas]: + self.ti_shows[sid][seas][ep] = TVInfoEpisode(season=self.ti_shows[sid][seas], show=self.ti_shows[sid]) if attrib not in ('cast', 'crew'): - self.shows[sid][seas][ep][attrib] = value - self.shows[sid][seas][ep].__dict__[attrib] = value + self.ti_shows[sid][seas][ep][attrib] = value + self.ti_shows[sid][seas][ep].__dict__[attrib] = value def _set_show_data(self, sid, key, value, add=False): # type: (integer_types, Any, Any, bool) -> None - """Sets self.shows[sid] to a new Show instance, or sets the data + """Sets self.ti_shows[sid] to a new Show instance, or sets the data """ - # if sid not in self.shows: - # self.shows[sid] = TVInfoShow() + # if sid not in self.ti_shows: + # self.ti_shows[sid] = TVInfoShow() if key not in ('cast', 'crew'): - if add and isinstance(self.shows[sid].data, dict) and key in self.shows[sid].data: - self.shows[sid].data[key].update(value) + if add and isinstance(self.ti_shows[sid].data, dict) and key in self.ti_shows[sid].data: + self.ti_shows[sid].data[key].update(value) else: - self.shows[sid].data[key] = value + self.ti_shows[sid].data[key] = value if '_banners' == key: p_key = 'banners' else: p_key = key - if add and key in self.shows[sid].__dict__ and isinstance(self.shows[sid].__dict__[p_key], dict): - self.shows[sid].__dict__[p_key].update(self.shows[sid].data[key]) + if add and key in self.ti_shows[sid].__dict__ and isinstance(self.ti_shows[sid].__dict__[p_key], dict): + self.ti_shows[sid].__dict__[p_key].update(self.ti_shows[sid].data[key]) else: - self.shows[sid].__dict__[p_key] = self.shows[sid].data[key] + self.ti_shows[sid].__dict__[p_key] = self.ti_shows[sid].data[key] else: - if add and key in self.shows[sid].__dict__ and isinstance(self.shows[sid].__dict__[key], dict): - self.shows[sid].__dict__[key].update(value) + if add and key in self.ti_shows[sid].__dict__ and isinstance(self.ti_shows[sid].__dict__[key], dict): + self.ti_shows[sid].__dict__[key].update(value) else: - self.shows[sid].__dict__[key] = value + self.ti_shows[sid].__dict__[key] = value def get_updated_shows(self): # type: (...) -> Dict[integer_types, integer_types] @@ -1331,6 +1359,7 @@ class TVInfoBase(object): msg_success = 'Treating image as %s with extracted aspect ratio' # most posters are around 0.68 width/height ratio (eg. 680/1000) + # noinspection DuplicatedCode if 0.55 <= img_ratio <= 0.8: log.debug(msg_success % 'poster') return TVInfoImageType.poster @@ -1368,6 +1397,6 @@ class TVInfoBase(object): return self._supported_languages or [] def __str__(self): - return '' % (self.__class__.__name__, text_type(self.shows)) + return '' % (self.__class__.__name__, text_type(self.ti_shows)) __repr__ = __str__ diff --git a/sickgear/tv.py b/sickgear/tv.py index 04a6e64e..8d7d9d98 100644 --- a/sickgear/tv.py +++ b/sickgear/tv.py @@ -148,15 +148,15 @@ class TVidProdid(object): if isinstance(tvid_prodid, dict) and 1 == len(tvid_prodid): try: - for (tvid, prodid) in iteritems(tvid_prodid): - self.tvid, self.prodid = int(tvid), int(prodid) + for (cur_tvid, cur_prodid) in iteritems(tvid_prodid): + self.tvid, self.prodid = int(cur_tvid), int(cur_prodid) except ValueError: pass elif isinstance(tvid_prodid, string_types): if self.glue in tvid_prodid: try: - for (tvid, prodid) in [re.findall(r'(\d+)\s*%s\s*(\d+)' % self.glue, tvid_prodid)[0]]: - self.tvid, self.prodid = int(tvid), int(prodid) + for (cur_tvid, cur_prodid) in [re.findall(r'(\d+)\s*%s\s*(\d+)' % self.glue, tvid_prodid)[0]]: + self.tvid, self.prodid = int(cur_tvid), int(cur_prodid) except IndexError: pass else: @@ -413,7 +413,7 @@ class Person(Referential): fetched = self._data_fetched cur_data = self._remember_properties() self.load_from_db() - cur_data['ids'] = dict(chain.from_iterable(iteritems(d) for d in (self.ids, ids or {}))) + cur_data['ids'] = dict(chain.from_iterable(iteritems(_d) for _d in (self.ids, ids or {}))) self.update_properties(**cur_data) self._data_fetched = fetched elif not self.name: @@ -447,7 +447,7 @@ class Person(Referential): def _remember_properties(self): # type: (...) -> Dict - return {k: self.__dict__[k] for k in + return {_k: self.__dict__[_k] for _k in ['akas', 'biography', 'birthday', 'birthplace', 'deathday', 'deathplace', 'gender', 'height', 'homepage', 'ids', 'image_url', 'name', 'nicknames', 'real_name', 'thumb_url']} @@ -537,9 +537,9 @@ class Person(Referential): remove all images of person """ try: - for r in image_cache.ImageCache().person_both_paths(self): + for cur_remove in image_cache.ImageCache().person_both_paths(self): try: - remove_file_perm(r) + remove_file_perm(cur_remove) except (BaseException, Exception): pass except (BaseException, Exception): @@ -574,26 +574,26 @@ class Person(Referential): self.remove_img() self.image_url = None - for k, v in iteritems(kwargs): - if k in ('image_url', 'thumb_url'): + for cur_key, cur_value in iteritems(kwargs): + if cur_key in ('image_url', 'thumb_url'): continue - if k not in self.__dict__: - raise Exception('Person has no property [%s]' % k) - if None is not v: - if 'akas' == k: - v.update(self.akas) - elif 'nicknames' == k: - v.update(self.nicknames) - if v != self.__dict__[k]: - if 'biography' == k: - if len(v) > len(self.biography or ''): - self.biography = v + if cur_key not in self.__dict__: + raise Exception('Person has no property [%s]' % cur_key) + if None is not cur_value: + if 'akas' == cur_key: + cur_value.update(self.akas) + elif 'nicknames' == cur_key: + cur_value.update(self.nicknames) + if cur_value != self.__dict__[cur_key]: + if 'biography' == cur_key: + if len(cur_value) > len(self.biography or ''): + self.biography = cur_value self.dirty_main = True - elif 'gender' == k and v not in (PersonGenders.male, PersonGenders.female): + elif 'gender' == cur_key and cur_value not in (PersonGenders.male, PersonGenders.female): continue else: - self.__dict__[k] = v - if 'ids' == k: + self.__dict__[cur_key] = cur_value + if 'ids' == cur_key: self.dirty_ids = True else: self.dirty_main = True @@ -656,8 +656,8 @@ class Person(Referential): char_obj = self.character_obj or self._tmp_character_obj if person_obj.characters and char_obj and char_obj.show_obj \ and char_obj.show_obj.ids.get(TVINFO_IMDB, {}).get('id'): - p_char = [pc for pc in person_obj.characters - if pc.show.ids.imdb == char_obj.show_obj.ids.get(TVINFO_IMDB, {}).get('id')] + p_char = [_pc for _pc in person_obj.characters + if _pc.ti_show.ids.imdb == char_obj.show_obj.ids.get(TVINFO_IMDB, {}).get('id')] p_count = len(p_char) if 1 == p_count: if (p_char[0].start_year or p_char[0].end_year) and getattr(self, 'id', None): @@ -665,22 +665,23 @@ class Person(Referential): {self.id: {'start': p_char[0].start_year, 'end': p_char[0].end_year}}) elif 1 < p_count: start, end, found, p_p = None, None, False, None - for c_p in p_char: - if not start or start > (c_p.start_year or 3000): - start = c_p.start_year - if not end or end < (c_p.end_year or 0): - end = c_p.end_year - if c_p.name == char_obj.name: - start = c_p.start_year - end = c_p.end_year + for cur_p in p_char: + if not start or start > (cur_p.start_year or 3000): + start = cur_p.start_year + if not end or end < (cur_p.end_year or 0): + end = cur_p.end_year + if cur_p.name == char_obj.name: + start = cur_p.start_year + end = cur_p.end_year found = True break if not found: try: p_p = sorted([ - (fuzz.UWRatio(char_obj.name, p.name), - p.end_year and p.start_year and p.end_year - p.start_year, p) for p in p_char], - key=lambda a: (a[0], a[1]), reverse=True)[0][2] + (fuzz.UWRatio(char_obj.name, _pc.name), + _pc.end_year and _pc.start_year and _pc.end_year - _pc.start_year, _pc) + for _pc in p_char], + key=lambda _a: (_a[0], _a[1]), reverse=True)[0][2] except (BaseException, Exception): p_p = None if None is not p_p and (p_p.start_year or p_p.end_year): @@ -691,8 +692,8 @@ class Person(Referential): self.update_properties( gender=person_obj.gender, homepage=person_obj.homepage, ids=dict(chain.from_iterable( - iteritems(d) for d in (self.ids, {k: v for k, v in iteritems(person_obj.ids) - if v and TVINFO_SLUG != k} or {}))), + iteritems(_d) for _d in (self.ids, {_k: _v for _k, _v in iteritems(person_obj.ids) + if _v and TVINFO_SLUG != _k} or {}))), birthday=person_obj.birthdate, deathday=person_obj.deathdate, biography=person_obj.bio, birthplace=person_obj.birthplace, deathplace=person_obj.deathplace, height=person_obj.height, real_name=person_obj.real_name, nicknames=person_obj.nicknames, akas=person_obj.akas @@ -714,30 +715,30 @@ class Person(Referential): self.dirty_main = True self._data_failure = False self._data_fetched = True - tvsrc_result, found_persons, found_on_src, search_sources, found_ids, ids_to_check, tv_loop, imdb_confirmed, \ - source_confirmed = \ + tvsrc_result, found_persons, found_on_src, search_sources, \ + found_ids, ids_to_check, imdb_confirmed, source_confirmed = \ None, {}, set(), [TVINFO_TRAKT, TVINFO_TMDB, TVINFO_IMDB], \ - set([k for k, v in iteritems(self.ids) if v] + ['text']), {}, 0, False, {} + set([_k for _k, _v in iteritems(self.ids) if _v] + ['text']), {}, False, {} # confirmed_character = False max_search_src = len(search_sources) logger.debug('Getting extra data for: %s' % self.name) - for tv_loop in moves.xrange(0, max_search_src): - search_sources = [s for s in search_sources if s not in found_on_src] + for cur_tv_loop in moves.xrange(0, max_search_src): + search_sources = [_s for _s in search_sources if _s not in found_on_src] for cur_tv_info_src in search_sources: if stop_event and stop_event.is_set(): return rp, confirmed_on_src = None, False tvinfo_config = sickgear.TVInfoAPI(cur_tv_info_src).api_params.copy() t = sickgear.TVInfoAPI(cur_tv_info_src).setup(**tvinfo_config) - if 0 == tv_loop or cur_tv_info_src not in ids_to_check: + if 0 == cur_tv_loop or cur_tv_info_src not in ids_to_check: ids_to_check[cur_tv_info_src] = t.supported_person_id_searches + ['text'] found_persons[cur_tv_info_src] = set() - for tv_src in ids_to_check[cur_tv_info_src]: - if 'text' != tv_src and not self.ids.get(tv_src): + for cur_tv_src in ids_to_check[cur_tv_info_src]: + if 'text' != cur_tv_src and not self.ids.get(cur_tv_src): continue try: - if 'text' != tv_src: - kw = {'ids': {tv_src: self.ids[tv_src]}} + if 'text' != cur_tv_src: + kw = {'ids': {cur_tv_src: self.ids[cur_tv_src]}} else: kw = {'name': self.name} tvsrc_result = t.search_person(**kw) @@ -749,7 +750,7 @@ class Person(Referential): for cur_person in tvsrc_result: # type: TVInfoPerson if None is not rp: break - if not (imdb_confirmed and TVINFO_IMDB == tv_src) \ + if not (imdb_confirmed and TVINFO_IMDB == cur_tv_src) \ and cur_person.id in found_persons[cur_tv_info_src]: continue found_persons[cur_tv_info_src].add(cur_person.id) @@ -760,21 +761,22 @@ class Person(Referential): self._data_failure = True logger.warning('Error searching extra info for person: %s - %s' % (self.name, ex(e))) continue - if None is not pd and imdb_confirmed and TVINFO_IMDB == tv_src: + if None is not pd and imdb_confirmed and TVINFO_IMDB == cur_tv_src: rp = pd break # noinspection PyUnresolvedReferences if show_obj and None is not pd and pd.characters: clean_show_name = indexermapper.clean_show_name(show_obj.name.lower()) - for ch in pd.characters or []: # type: TVInfoCharacter - if clean_show_name == indexermapper.clean_show_name(ch.show.seriesname.lower()): + for cur_ch in pd.characters or []: # type: TVInfoCharacter + if clean_show_name == indexermapper.clean_show_name( + cur_ch.ti_show.seriesname.lower()): rp = pd confirmed_on_src = True # confirmed_character = True break - elif any(t_src == s_src and bool(t_id) and t_id == s_id['id'] - for t_src, t_id in iteritems(ch.show.ids) - for s_src, s_id in iteritems(show_obj.ids)): + elif any(_ti_src == _so_src and bool(_ti_ids) and _ti_ids == _so_ids['id'] + for _ti_src, _ti_ids in iteritems(cur_ch.ti_show.ids) + for _so_src, _so_ids in iteritems(show_obj.ids)): rp = pd confirmed_on_src = True # confirmed_character = True @@ -785,33 +787,33 @@ class Person(Referential): found_on_src.add(cur_tv_info_src) break - ids_to_check[cur_tv_info_src] = [i for i in ids_to_check[cur_tv_info_src] if i not in found_ids] + ids_to_check[cur_tv_info_src] = [_i for _i in ids_to_check[cur_tv_info_src] if _i not in found_ids] if None is not rp: if confirmed_on_src: - for i in (TVINFO_TRAKT, TVINFO_IMDB, TVINFO_TMDB, TVINFO_TVMAZE, TVINFO_TVDB): - if not rp.ids.get(i): + for cur_i in (TVINFO_TRAKT, TVINFO_IMDB, TVINFO_TMDB, TVINFO_TVMAZE, TVINFO_TVDB): + if not rp.ids.get(cur_i): continue # in case it's the current source use its id and lock if from being changed - if cur_tv_info_src == i and rp.ids.get(i): - source_confirmed[i] = True - if rp.ids.get(i) != self.ids.get(i): - self.ids[i] = rp.ids[i] + if cur_tv_info_src == cur_i and rp.ids.get(cur_i): + source_confirmed[cur_i] = True + if rp.ids.get(cur_i) != self.ids.get(cur_i): + self.ids[cur_i] = rp.ids[cur_i] self.dirty_ids = True - if not source_confirmed.get(i) and \ - (rp.ids.get(i) and not self.ids.get(i) or - (force_id and rp.ids.get(i) and rp.ids.get(i) != self.ids.get(i))): - self.ids[i] = rp.ids[i] - found_ids.add(i) + if not source_confirmed.get(cur_i) and \ + (rp.ids.get(cur_i) and not self.ids.get(cur_i) or + (force_id and rp.ids.get(cur_i) and rp.ids.get(cur_i) != self.ids.get(cur_i))): + self.ids[cur_i] = rp.ids[cur_i] + found_ids.add(cur_i) self.dirty_ids = True - for i in (TVINFO_INSTAGRAM, TVINFO_TWITTER, TVINFO_FACEBOOK, TVINFO_WIKIPEDIA): - if not rp.social_ids.get(i): + for cur_i in (TVINFO_INSTAGRAM, TVINFO_TWITTER, TVINFO_FACEBOOK, TVINFO_WIKIPEDIA): + if not rp.social_ids.get(cur_i): continue - if rp.social_ids.get(i) and not self.ids.get(i) or \ - (rp.social_ids.get(i) and rp.social_ids.get(i) != self.ids.get(i)): - self.ids[i] = rp.social_ids[i] - found_ids.add(i) + if rp.social_ids.get(cur_i) and not self.ids.get(cur_i) or \ + (rp.social_ids.get(cur_i) and rp.social_ids.get(cur_i) != self.ids.get(cur_i)): + self.ids[cur_i] = rp.social_ids[cur_i] + found_ids.add(cur_i) self.dirty_ids = True self.update_prop_from_tvinfo_person(rp) @@ -835,7 +837,7 @@ class Person(Referential): if not self._data_fetched: self.get_missing_data(show_obj=show_obj, character_obj=character_obj, stop_event=stop_event) self._data_fetched = False - if not any(d for d in (self.dirty_main, self.dirty_ids)): + if not any(_d for _d in (self.dirty_main, self.dirty_ids)): return my_db = db.DBConnection() if not self.id: @@ -868,7 +870,7 @@ class Person(Referential): (SELECT person_ids.person_id FROM person_ids WHERE person_ids.id = last_insert_rowid()) ); - """, [s, self.ids[s]]] for s in list(self.ids)[1:] + """, [_s, self.ids[_s]]] for _s in list(self.ids)[1:] ]) cl.extend([[ """ @@ -896,13 +898,13 @@ class Person(Referential): ';;;'.join(self.nicknames or []), ';;;'.join(self.akas or []), self.id]], ] if force or self.dirty_ids: - for s, v in iteritems(self.ids): - if v: - cl.extend([ - ['UPDATE person_ids SET src_id = ? WHERE person_id = ? AND src = ?', [v, self.id, s]], - ["INSERT INTO person_ids (src, src_id, person_id) SELECT %s, '%s', %s WHERE changes() == 0" - % (s, v, self.id)] - ]) + for cur_src, cur_ids in iteritems(self.ids): + cl.extend([ + ['UPDATE person_ids SET src_id = ? WHERE person_id = ? AND src = ?', + [cur_ids, self.id, cur_src]], + ["INSERT INTO person_ids (src, src_id, person_id) SELECT %s, '%s', %s WHERE changes() == 0" + % (cur_src, cur_ids, self.id)] + ]) if cl: r_id = my_db.mass_action(cl) if r_id and r_id[-1:][0]: @@ -930,7 +932,7 @@ class Person(Referential): def __eq__(self, other): return (self.id not in [None, 0] and other.id == self.id) \ - and any(self.ids[o] == v for o, v in iteritems(other.ids)) + and any(self.ids[_o] == ids for _o, ids in iteritems(other.ids)) def __str__(self): lived, id_str, id_list = '', '', [] @@ -938,8 +940,8 @@ class Person(Referential): lived += ' %s' % self.birthday if self.deathday: lived += ' - %s' % self.deathday - for i, d in iteritems(self.ids): - id_list.append('%s: %s' % (sickgear.TVInfoAPI(i).name, d)) + for _src, _ids in iteritems(self.ids): + id_list.append('%s: %s' % (sickgear.TVInfoAPI(_src).name, _ids)) if id_list: id_str = ' (%s)' % ', '.join(id_list) return '' % (self.name, lived, id_str) @@ -988,7 +990,7 @@ class Character(Referential): if not sid and self.id: self.load_from_db() self.update_properties(name=name, person=person, biography=bio, - ids=dict(chain.from_iterable(iteritems(d) for d in (self.ids, ids or {}))), + ids=dict(chain.from_iterable(iteritems(_d) for _d in (self.ids, ids or {}))), image_url=image_url, thumb_url=thumb_url) elif not self.name: self.load_from_db() @@ -1023,7 +1025,7 @@ class Character(Referential): LEFT JOIN character_person_map cpm ON characters.id = cpm.character_id WHERE name = ? AND cpm.person_id IN (%s) """ % ','.join(['?' * len(self.person)]), - [self.name] + [p.id for p in self.person]) + [self.name] + [_p.id for _p in self.person]) if sql_result: return sql_result[0]['c_id'] @@ -1059,41 +1061,42 @@ class Character(Referential): remove all images of person """ try: - for r in image_cache.ImageCache().character_both_path(self, show_obj=self.show_obj, tvid=tvid, proid=proid): + for cur_remove in image_cache.ImageCache().character_both_path( + self, show_obj=self.show_obj, tvid=tvid, proid=proid): try: - remove_file_perm(r) + remove_file_perm(cur_remove) except (BaseException, Exception): pass except (BaseException, Exception): pass if include_person: - for p in self.person or []: + for cur_person in self.person or []: try: - p.remove_all_img() + cur_person.remove_all_img() except (BaseException, Exception): pass def update_properties(self, **kwargs): - for k, v in iteritems(kwargs): - if k not in self.__dict__: - raise Exception('Character has no property [%s]' % k) - if None is not v and v != self.__dict__[k]: - if 'image_url' == k: + for cur_key, cur_value in iteritems(kwargs): + if cur_key not in self.__dict__: + raise Exception('Character has no property [%s]' % cur_key) + if None is not cur_value and cur_value != self.__dict__[cur_key]: + if 'image_url' == cur_key: self.dirty_main = True self.remove_img() if not kwargs.get('thumb_url'): self.remove_thumb() self.thumb_url = None - elif 'thumb_url' == k: + elif 'thumb_url' == cur_key: self.dirty_main = True self.remove_thumb() if not kwargs.get('image_url'): self.remove_img() self.image_url = None - self.__dict__[k] = v - if 'ids' == k: + self.__dict__[cur_key] = cur_value + if 'ids' == cur_key: self.dirty_ids = True - elif 'person' == k: + elif 'person' == cur_key: self.dirty_person = True else: self.dirty_main = True @@ -1101,7 +1104,8 @@ class Character(Referential): def combine_start_end_years(self, new_years): # type: (Dict[integer_types, Dict[AnyStr, int]]) -> None new_dict = dict(chain.from_iterable( - iteritems(d) for d in (self.persons_years, {k: v for k, v in iteritems(new_years) if v} or {}))) + iteritems(_d) for _d in (self.persons_years, + {_k: _v for _k, _v in iteritems(new_years) if _v} or {}))) if new_dict != self.persons_years: self.persons_years = new_dict self.dirty_years = True @@ -1148,8 +1152,8 @@ class Character(Referential): self.person, self.persons_years, self.thumb_url, self.updated) = \ (cur_row['bio'], cur_row['c_id'], c_ids, cur_row['image_url'], cur_row['name'], - [Person(sid=int(p), character_obj=self) - for p in (cur_row['person_ids'] and cur_row['person_ids'].split(';;;')) or []], + [Person(sid=int(_p), character_obj=self) + for _p in (cur_row['person_ids'] and cur_row['person_ids'].split(';;;')) or []], p_years, cur_row['thumb_url'], cur_row['c_updated']) self.dirty_main, self.dirty_ids, self.dirty_person = False, False, False @@ -1211,7 +1215,7 @@ class Character(Referential): (SELECT character_ids.character_id FROM character_ids WHERE character_ids.id = last_insert_rowid()) ); - """, [s, self.ids[s]]] for s in list(self.ids)[1:] + """, [_s, self.ids[_s]]] for _s in list(self.ids)[1:] ]) cl.extend([[ """ @@ -1260,7 +1264,7 @@ class Character(Referential): DELETE FROM character_person_map WHERE character_id = ? AND person_id NOT IN (%s) """ % ','.join(['?'] * len(self.person)), - [self.id] + [p.id for p in self.person]]) + [self.id] + [_p.id for _p in self.person]]) for cur_per in self.person: cl.extend([[ """ @@ -1275,9 +1279,9 @@ class Character(Referential): DELETE FROM character_person_years WHERE character_id = ? AND person_id NOT IN (%s) """ % ','.join(['?'] * len(self.person)), - [self.id] + [p.id for p in self.person]]) + [self.id] + [_p.id for _p in self.person]]) for cur_per in self.person: - if cur_per.id and any(1 for v in itervalues(self.persons_years.get(cur_per.id, {})) if v): + if cur_per.id and any(1 for _v in itervalues(self.persons_years.get(cur_per.id, {})) if _v): p_years = self.persons_years.get(cur_per.id, {}) cl.append([ """ @@ -1295,16 +1299,16 @@ class Character(Referential): def __eq__(self, other): return other.person == self.person and ((self.id not in [None, 0] and other.id == self.id) - or any(self.ids[o] == v for o, v in iteritems(other.ids)) + or any(self.ids[_o] == _v for _o, _v in iteritems(other.ids)) or (not other.ids and other.name == self.name)) def __str__(self): id_str, id_list = '', [] - for i, d in iteritems(self.ids): - id_list.append('%s: %s' % (sickgear.TVInfoAPI(i).name, d)) + for _src, _ids in iteritems(self.ids): + id_list.append('%s: %s' % (sickgear.TVInfoAPI(_src).name, _ids)) if id_list: id_str = ' (%s)' % ', '.join(id_list) - return '' % (self.name, ', '.join(p.name for p in self.person), id_str) + return '' % (self.name, ', '.join(_p.name for _p in self.person), id_str) def __repr__(self): return self.__str__() @@ -1359,8 +1363,9 @@ class TVShow(TVShowBase): eps = self.get_all_episodes() if eps: ed = datetime.date(1900, 1, 1) - return next(iter(sorted((ep for ep in eps if ep.airdate > ed and (not exclude_specials or ep.season != 0)), - key=lambda a: a.airdate, reverse=last)), None) + return next(iter(sorted( + (_ep for _ep in eps if _ep.airdate > ed and (not exclude_specials or _ep.season != 0)), + key=lambda a: a.airdate, reverse=last)), None) @property def first_aired_episode(self): @@ -1607,13 +1612,13 @@ class TVShow(TVShowBase): @ids.setter def ids(self, value): if isinstance(value, dict): - for k, v in iteritems(value): - if k not in indexermapper.indexer_list or \ - not isinstance(v, dict) or \ - not isinstance(v.get('id'), integer_types) or \ - not isinstance(v.get('status'), integer_types) or \ - v.get('status') not in indexermapper.MapStatus.allstatus or \ - not isinstance(v.get('date'), datetime.date): + for cur_key, cur_value in iteritems(value): + if cur_key not in indexermapper.indexer_list or \ + not isinstance(cur_value, dict) or \ + not isinstance(cur_value.get('id'), integer_types) or \ + not isinstance(cur_value.get('status'), integer_types) or \ + cur_value.get('status') not in indexermapper.MapStatus.allstatus or \ + not isinstance(cur_value.get('date'), datetime.date): return self.internal_ids = value @@ -1840,22 +1845,22 @@ class TVShow(TVShowBase): deathdate = try_int(cur_row['deathdate'], None) deathdate = deathdate and datetime.date.fromordinal(cur_row['deathdate']) p_years = {} - for p in (cur_row['p_years'] and cur_row['p_years'].split(';;;')) or []: - p_id, py = p.split(':') + for cur_p in (cur_row['p_years'] and cur_row['p_years'].split(';;;')) or []: + p_id, py = cur_p.split(':') start, end = py.split('-') p_years[int(p_id)] = {'start': try_int(start, None), 'end': try_int(end, None)} p_ids, c_ids = {}, {} - for i in (cur_row['p_ids'] and cur_row['p_ids'].split(';;;')) or []: - k, v = i.split(':') + for cur_i in (cur_row['p_ids'] and cur_row['p_ids'].split(';;;')) or []: + k, v = cur_i.split(':') k = try_int(k, None) if v: if k in (TVINFO_INSTAGRAM, TVINFO_TWITTER, TVINFO_FACEBOOK, TVINFO_WIKIPEDIA): p_ids[k] = v else: p_ids[k] = try_int(v, None) - for i in (cur_row['c_ids'] and cur_row['c_ids'].split(';;;')) or []: - k, v = i.split(':') + for cur_i in (cur_row['c_ids'] and cur_row['c_ids'].split(';;;')) or []: + k, v = cur_i.split(':') v = try_int(v, None) if v: c_ids[int(k)] = try_int(v, None) @@ -1876,9 +1881,9 @@ class TVShow(TVShowBase): old_list.remove(existing_character.id) except (BaseException, Exception): pass - existing_person = next((p for p in existing_character.person if (None is not p.id - and p.ids.get(self.tvid) == person.ids.get(self.tvid)) - or p.name == person.name), + existing_person = next((_p for _p in existing_character.person if (None is not _p.id + and _p.ids.get(self.tvid) == person.ids.get(self.tvid)) + or _p.name == person.name), None) # type: Optional[Person] existing_character.combine_start_end_years(p_years) if existing_person: @@ -1888,7 +1893,7 @@ class TVShow(TVShowBase): birthday=person.birthday, birthplace=person.birthplace, deathday=person.deathday, deathplace=cur_row['deathplace'], gender=person.gender, height=cur_row['height'], - ids=dict(chain.from_iterable(iteritems(d) for d in (existing_person.ids, person.ids or {}))), + ids=dict(chain.from_iterable(iteritems(_d) for _d in (existing_person.ids, person.ids or {}))), image_url=person.image_url, name=person.name, nicknames=set((cur_row['nicknames'] and cur_row['nicknames'].split(';;;')) or []), real_name=cur_row['realname'], thumb_url=person.thumb_url @@ -1912,9 +1917,9 @@ class TVShow(TVShowBase): used to tell if a change has occurred in a cast list after time/process """ - return set((c.name, c.image_url or '', c.thumb_url or '', - hash(*([', '.join(p.name for p in c.person or [] if p.name)]))) - for c in self.cast_list or [] if c.name) + return set((_c.name, _c.image_url or '', _c.thumb_url or '', + hash(*([', '.join(_p.name for _p in _c.person or [] if _p.name)]))) + for _c in self.cast_list or [] if _c.name) @staticmethod def orphaned_cast_sql(): @@ -2041,9 +2046,9 @@ class TVShow(TVShowBase): last_update_diff = update_date - last_update_indexer update_step_list = [[60, 1], [120, 3], [180, 7], [1281, 15], [update_days_limit, 30]] - for date_diff, interval in update_step_list: - if airdate_diff <= datetime.timedelta(days=date_diff) \ - and last_update_diff >= datetime.timedelta(days=interval): + for cur_date_diff, cur_iv in update_step_list: + if airdate_diff <= datetime.timedelta(days=cur_date_diff) \ + and last_update_diff >= datetime.timedelta(days=cur_iv): return True # update shows without an airdate for the last episode for update_days_limit days every 7 days @@ -2111,9 +2116,9 @@ class TVShow(TVShowBase): processed += [(cur_row['season'], cur_row['episode'])] else: logger.debug(f'{self.tvid_prodid}: Found related to {cur_row["season"]}x{cur_row["episode"]} episode(s)' - f'... {", ".join(["%sx%s" % (x.season, x.episode) for x in ep_obj.related_ep_obj])}') + f'... {", ".join(["%sx%s" % (_ep.season, _ep.episode) for _ep in ep_obj.related_ep_obj])}') processed += list(set([(cur_row['season'], cur_row['episode'])] + - [(x.season, x.episode) for x in ep_obj.related_ep_obj])) + [(_ep.season, _ep.episode) for _ep in ep_obj.related_ep_obj])) ep_obj.create_meta_files(force) def update_metadata(self): @@ -2349,17 +2354,18 @@ class TVShow(TVShowBase): WHERE indexer = ? AND showid = ? """, [self.tvid, self.prodid]) sql_l = [] - for season in show_obj: - scanned_eps[season] = {} - for episode in show_obj[season]: + for cur_season in show_obj: + scanned_eps[cur_season] = {} + for cur_episode in show_obj[cur_season]: # need some examples of wtf episode 0 means to decide if we want it or not - if 0 == episode: + if 0 == cur_episode: continue try: - ep_obj = self.get_episode(season, episode, ep_result=sql_result) # type: TVEpisode + ep_obj = self.get_episode(cur_season, cur_episode, ep_result=sql_result) # type: TVEpisode except exceptions_helper.EpisodeNotFoundException: logger.log('%s: %s object for %sx%s from [%s] is incomplete, skipping this episode' % - (self.tvid_prodid, sickgear.TVInfoAPI(self.tvid).name, season, episode, self._name)) + (self.tvid_prodid, sickgear.TVInfoAPI( + self.tvid).name, cur_season, cur_episode, self._name)) continue else: try: @@ -2371,8 +2377,8 @@ class TVShow(TVShowBase): with ep_obj.lock: logger.debug(f'{self.tvid_prodid}: Loading info from {sickgear.TVInfoAPI(self.tvid).name}' - f' for episode {season}x{episode} from [{self._name}]') - ep_obj.load_from_tvinfo(season, episode, tvapi=t, update=update, cached_show=show_obj, + f' for episode {cur_season}x{cur_episode} from [{self._name}]') + ep_obj.load_from_tvinfo(cur_season, cur_episode, tvapi=t, update=update, cached_show=show_obj, switch=switch, old_tvid=old_tvid, old_prodid=old_prodid, switch_list=sql_l) @@ -2380,7 +2386,7 @@ class TVShow(TVShowBase): if None is not result: sql_l.append(result) - scanned_eps[season][episode] = True + scanned_eps[cur_season][cur_episode] = True if 0 < len(sql_l): my_db = db.DBConnection() @@ -2711,7 +2717,7 @@ class TVShow(TVShowBase): if isinstance(sql_result[0], dict): self._imdb_info = sql_result[0] else: - self._imdb_info = dict(zip(sql_result[0].keys(), [(r, '')[None is r] for r in sql_result[0]])) + self._imdb_info = dict(zip(sql_result[0].keys(), [(_r, '')[None is _r] for _r in sql_result[0]])) if 'is_mini_series' in self._imdb_info: self._imdb_info['is_mini_series'] = bool(self._imdb_info['is_mini_series']) elif sickgear.USE_IMDB_INFO: @@ -2860,7 +2866,7 @@ class TVShow(TVShowBase): self.airs = ('%s %s' % (show_info['airs_dayofweek'], show_info['airs_time'])).strip() if None is not getattr(show_info, 'firstaired', None): - self.startyear = int(str(show_info["firstaired"]).split('-')[0]) + self.startyear = int(str(show_info["firstaired"] or '0000-00-00').split('-')[0]) self.status = self.dict_prevent_nonetype(show_info, 'status') self.overview = self.dict_prevent_nonetype(show_info, 'overview') @@ -2887,8 +2893,7 @@ class TVShow(TVShowBase): name=src_person.name, gender=src_person.gender, birthday=src_person.birthdate, deathday=src_person.deathdate, biography=src_person.bio, - ids=dict(chain.from_iterable(iteritems(d) for d in - (person_obj.ids, p_ids))), + ids=dict(chain.from_iterable(iteritems(_d) for _d in (person_obj.ids, p_ids))), deathplace=src_person.deathplace, akas=src_person.akas, nicknames=src_person.nicknames, real_name=src_person.real_name, height=src_person.height) @@ -2918,31 +2923,31 @@ class TVShow(TVShowBase): cast_list = self._load_cast_from_db() remove_char_ids = {c.id for c in cast_list or []} cast_ordered = WeakList() - for ct, c_l in iteritems(show_info_cast): # type: (integer_types, List[TVInfoCharacter]) - if ct not in (RoleTypes.ActorMain, RoleTypes.Host, RoleTypes.Interviewer, RoleTypes.Presenter): + for cur_cast_type, cur_cast_list in iteritems(show_info_cast): # type: (integer_types, List[TVInfoCharacter]) + if cur_cast_type not in (RoleTypes.ActorMain, RoleTypes.Host, RoleTypes.Interviewer, RoleTypes.Presenter): continue - for c in c_l: + for cur_cast in cur_cast_list: if stop_event and stop_event.is_set(): return - unique_name = 1 == len([cu for cu in c_l if (None is not c.id and cu.id == c.id) - or cu.name == c.name]) - mc = next((cl for cl in cast_list or [] - if (None is not c.id and cl.ids.get(self.tvid) == c.id) - or (unique_name and c.name and cl.name == c.name) - or any(cl.ids.get(src) == c.ids.get(src) for src in c.ids or {})), + unique_name = 1 == len([_c for _c in cur_cast_list if (None is not cur_cast.id and _c.id == cur_cast.id) + or _c.name == cur_cast.name]) + mc = next((_c for _c in cast_list or [] + if (None is not cur_cast.id and _c.ids.get(self.tvid) == cur_cast.id) + or (unique_name and cur_cast.name and _c.name == cur_cast.name) + or any(_c.ids.get(_src) == cur_cast.ids.get(_src) for _src in cur_cast.ids or {})), None) # type: Optional[Character] if not mc: unique_person = not any(1 for _cp in - Counter([_p.name for _cha in c_l for _p in _cha.person - if any(_p.name == _pp.name for _pp in c.person)]).values() + Counter([_p.name for _cha in cur_cast_list for _p in _cha.person + if any(_p.name == _pp.name for _pp in cur_cast.person)]).values() if 1 != _cp) if unique_person: - pc = [cl for cl in cast_list or [] if cl.person - and any(1 for p in cl.person if c.person - and ((None is not p.ids.get(self.tvid) and any(p.ids.get(self.tvid) == cp.id - for cp in c.person)) - or any(p.name == cp.name for cp in c.person)))] + pc = [_c for _c in cast_list or [] if _c.person + and any(1 for _p in _c.person if cur_cast.person + and ((None is not _p.ids.get(self.tvid) + and any(_p.ids.get(self.tvid) == _cp.id for _cp in cur_cast.person)) + or any(_p.name == _ccp.name for _ccp in cur_cast.person)))] if 1 == len(pc): mc = pc[0] if mc: @@ -2952,80 +2957,86 @@ class TVShow(TVShowBase): # can happen with duplicate characters on source logger.debug('%s - error character: %s (%s)' % (self.name, mc.id, mc.name)) - old_person_ids = {op.id for op in mc.person if None is not op.id} - for src_person in c.person: - if src_person.id: - person_ids = {self.tvid: src_person.id} + original_person_ids = {_op.id for _op in mc.person if None is not _op.id} + for cur_person in cur_cast.person: + if cur_person.id: + person_ids = {self.tvid: cur_person.id} else: person_ids = {} existing_person = next( - (cur_person for cur_person in mc.person - if (None is not src_person.id and cur_person.ids.get(self.tvid) == src_person.id) - or (cur_person.name and cur_person.name == src_person.name)), + (_p for _p in mc.person + if (None is not cur_person.id and _p.ids.get(self.tvid) == cur_person.id) + or (_p.name and _p.name == cur_person.name)), None) # type: Optional[Person] new_person = None if not existing_person: - new_person = Person(src_person.name, src_person.gender, src_person.birthdate, - src_person.deathdate, src_person.bio, akas=src_person.akas, - character_obj=mc, deathplace=src_person.deathplace, - height=src_person.height, ids=person_ids, image_url=src_person.image, - nicknames=src_person.nicknames, real_name=src_person.real_name, - show_obj=self, thumb_url=src_person.thumb_url) - if new_person and new_person.id and any(1 for pi in mc.person if pi.id == new_person.id): - existing_person = next((pi for pi in mc.person if pi.id == new_person.id), None) + new_person = Person(cur_person.name, cur_person.gender, cur_person.birthdate, + cur_person.deathdate, cur_person.bio, akas=cur_person.akas, + character_obj=mc, deathplace=cur_person.deathplace, + height=cur_person.height, ids=person_ids, image_url=cur_person.image, + nicknames=cur_person.nicknames, real_name=cur_person.real_name, + show_obj=self, thumb_url=cur_person.thumb_url) + if new_person and new_person.id and any(1 for _p in mc.person if _p.id == new_person.id): + existing_person = next((_pi for _pi in mc.person if _pi.id == new_person.id), None) if existing_person: try: - old_person_ids.remove(existing_person.id) + original_person_ids.remove(existing_person.id) except KeyError: logger.error(f'{self.name} -' f' Person error: {existing_person.name} ({existing_person.id})') pass if force: - existing_person.reset(src_person) - self._update_person_properties_helper(existing_person, src_person, person_ids) + existing_person.reset(cur_person) + self._update_person_properties_helper(existing_person, cur_person, person_ids) elif None is not new_person: mc.person.append(new_person) - if old_person_ids: - mc.person = [cp for cp in mc.person if cp.id not in old_person_ids] + if original_person_ids: + mc.person = [_cp for _cp in mc.person if _cp.id not in original_person_ids] mc.update_properties( - name=c.name, image_url=c.image, thumb_url=c.thumb_url, + name=cur_cast.name, image_url=cur_cast.image, thumb_url=cur_cast.thumb_url, ids=dict(chain.from_iterable( - iteritems(d) for d in (mc.ids, ({}, {self.tvid: c.id})[None is not c.id])))) + iteritems(_d) for _d in (mc.ids, ({}, {self.tvid: cur_cast.id})[None is not cur_cast.id])))) else: persons = [] - for s_pers in c.person: + for cur_person in cur_cast.person: existing_person = next((_p for _c in cast_list for _p in _c.person - if (s_pers.id and _p.ids.get(self.tvid) == s_pers.id) - or (not s_pers.id and s_pers.name == _p.name)), + if (cur_person.id and _p.ids.get(self.tvid) == cur_person.id) + or (not cur_person.id and cur_person.name == _p.name)), None) # type: Optional[Person] - if s_pers.id: - person_ids = {self.tvid: s_pers.id} + if cur_person.id: + person_ids = {self.tvid: cur_person.id} else: person_ids = {} if existing_person: if force: - existing_person.reset(s_pers) - self._update_person_properties_helper(existing_person, s_pers, person_ids) + existing_person.reset(cur_person) + self._update_person_properties_helper(existing_person, cur_person, person_ids) persons.append(existing_person) else: - tmp_char = Character(c.name, ids=({}, {self.tvid: c.id})[None is not c.id], - image_url=c.image, show_obj=self, thumb_url=c.thumb_url, tmp=True) + tmp_char = Character(cur_cast.name, + ids=({}, {self.tvid: cur_cast.id})[None is not cur_cast.id], + image_url=cur_cast.image, show_obj=self, + thumb_url=cur_cast.thumb_url, tmp=True) new_person = Person( - s_pers.name, s_pers.gender, s_pers.birthdate, s_pers.deathdate, s_pers.bio, - akas=s_pers.akas, deathplace=s_pers.deathplace, height=s_pers.height, - ids=({}, {self.tvid: s_pers.id})[None is not s_pers.id], - image_url=s_pers.image, nicknames=s_pers.nicknames, real_name=s_pers.real_name, - show_obj=self, thumb_url=s_pers.thumb_url, tmp_character_obj=tmp_char + cur_person.name, cur_person.gender, cur_person.birthdate, cur_person.deathdate, + cur_person.bio, + akas=cur_person.akas, deathplace=cur_person.deathplace, height=cur_person.height, + ids=({}, {self.tvid: cur_person.id})[None is not cur_person.id], + image_url=cur_person.image, nicknames=cur_person.nicknames, + real_name=cur_person.real_name, show_obj=self, + thumb_url=cur_person.thumb_url, tmp_character_obj=tmp_char ) if force: - new_person.reset(s_pers) - self._update_person_properties_helper(new_person, s_pers, person_ids) + new_person.reset(cur_person) + self._update_person_properties_helper(new_person, cur_person, person_ids) persons.append(new_person) - mc = Character(c.name, ids=({}, {self.tvid: c.id})[None is not c.id], image_url=c.image, - person=persons, show_obj=self, thumb_url=c.thumb_url) + mc = Character(cur_cast.name, + ids=({}, {self.tvid: cur_cast.id})[None is not cur_cast.id], + image_url=cur_cast.image, person=persons, + show_obj=self, thumb_url=cur_cast.thumb_url) cast_list.append(mc) cast_ordered.append(mc) @@ -3059,7 +3070,7 @@ class TVShow(TVShowBase): page_url = 'https://www.imdb.com/title/{0}/'.format(imdb_id) try: response = requests.head(page_url, allow_redirects=True) - if response.history and any(h for h in response.history if 301 == h.status_code): + if response.history and any(_h for _h in response.history if 301 == _h.status_code): return helpers.parse_imdb_id(response.url) except (BaseException, Exception): pass @@ -3138,17 +3149,17 @@ class TVShow(TVShowBase): en_cc = ['GB', 'US', 'CA', 'AU'] # akas if isinstance(imdb_akas.get('alternateTitles'), (list, tuple)): - akas_head = OrderedDict([(k, None) for k in en_cc]) + akas_head = OrderedDict([(_k, None) for _k in en_cc]) akas_tail = [] - for t in imdb_akas.get('alternateTitles'): - if isinstance(t, dict) and t.get('title') and t.get('region'): - cc = t.get('region').upper() - cc_aka = '%s::%s' % (cc, t.get('title')) - if cc in akas_head: - akas_head[cc] = cc_aka + for cur_aka in imdb_akas.get('alternateTitles'): + if isinstance(cur_aka, dict) and cur_aka.get('title') and cur_aka.get('region'): + cur_cc = cur_aka.get('region').upper() + cc_aka = '%s::%s' % (cur_cc, cur_aka.get('title')) + if cur_cc in akas_head: + akas_head[cur_cc] = cc_aka else: akas_tail += [cc_aka] - imdb_info['akas'] = '|'.join([aka for aka in itervalues(akas_head) if aka] + sorted(akas_tail)) + imdb_info['akas'] = '|'.join([_aka for _aka in itervalues(akas_head) if _aka] + sorted(akas_tail)) # tv if isinstance(imdb_tv.get('title'), string_types): @@ -3179,22 +3190,23 @@ class TVShow(TVShowBase): # certificate if isinstance(imdb_certificates.get('certificates'), dict): - certs_head = OrderedDict([(k, None) for k in en_cc]) + certs_head = OrderedDict([(_k, None) for _k in en_cc]) certs_tail = [] - for cc, values in iteritems(imdb_certificates.get('certificates')): - if cc and isinstance(values, (list, tuple)): - for cert in values: - if isinstance(cert, dict) and cert.get('certificate'): + for cur_cc, cur_values in iteritems(imdb_certificates.get('certificates')): + if cur_cc and isinstance(cur_values, (list, tuple)): + for cur_cert in cur_values: + if isinstance(cur_cert, dict) and cur_cert.get('certificate'): extra_info = '' - if isinstance(cert.get('attributes'), list): - extra_info = ' (%s)' % ', '.join(cert.get('attributes')) - cc = cc.upper() - cc_cert = '%s:%s%s' % (cc, cert.get('certificate'), extra_info) - if cc in certs_head: - certs_head[cc] = cc_cert + if isinstance(cur_cert.get('attributes'), list): + extra_info = ' (%s)' % ', '.join(cur_cert.get('attributes')) + cur_cc = cur_cc.upper() + cc_cert = '%s:%s%s' % (cur_cc, cur_cert.get('certificate'), extra_info) + if cur_cc in certs_head: + certs_head[cur_cc] = cc_cert else: certs_tail += [cc_cert] - imdb_info['certificates'] = '|'.join([cert for cert in itervalues(certs_head) if cert] + sorted(certs_tail)) + imdb_info['certificates'] = '|'.join( + [_cert for _cert in itervalues(certs_head) if _cert] + sorted(certs_tail)) if (not imdb_info['certificates'] and isinstance(imdb_tv.get('certificate'), dict) and isinstance(imdb_tv.get('certificate').get('certificate'), string_types)): imdb_info['certificates'] = f'US:{imdb_tv.get("certificate").get("certificate")}' @@ -3203,7 +3215,7 @@ class TVShow(TVShowBase): # Rename dict keys without spaces for DB upsert self.imdb_info = dict( - [(k.replace(' ', '_'), k(v) if hasattr(v, 'keys') else v) for k, v in iteritems(imdb_info)]) + [(_k.replace(' ', '_'), _k(_v) if hasattr(_v, 'keys') else _v) for _k, _v in iteritems(imdb_info)]) logger.debug('%s: Obtained info from IMDb -> %s' % (self.tvid_prodid, self._imdb_info)) logger.log('%s: Parsed latest IMDb show info for [%s]' % (self.tvid_prodid, self._name)) @@ -3289,19 +3301,20 @@ class TVShow(TVShowBase): if tvid_prodid in sickgear.switched_shows: sickgear.switched_shows.pop(tvid_prodid) elif tvid_prodid in itervalues(sickgear.switched_shows): - sickgear.switched_shows = {k: v for k, v in iteritems(sickgear.switched_shows) if tvid_prodid != v} + sickgear.switched_shows = {_k: _v for _k, _v in iteritems(sickgear.switched_shows) + if tvid_prodid != _v} except (BaseException, Exception): pass # clear the cache ic = image_cache.ImageCache() - for cache_obj in glob.glob(ic.fanart_path(self.tvid, self.prodid).replace('fanart.jpg', '*')) \ + for cur_cachefile in glob.glob(ic.fanart_path(self.tvid, self.prodid).replace('fanart.jpg', '*')) \ + glob.glob(ic.poster_thumb_path(self.tvid, self.prodid).replace('poster.jpg', '*')) \ + glob.glob(ic.poster_path(self.tvid, self.prodid).replace('poster.jpg', '*')): - cache_dir = os.path.isdir(cache_obj) - result = helpers.remove_file(cache_obj, tree=cache_dir, log_level=logger.WARNING) + cache_dir = os.path.isdir(cur_cachefile) + result = helpers.remove_file(cur_cachefile, tree=cache_dir, log_level=logger.WARNING) if result: - logger.log('%s cache %s %s' % (result, cache_dir and 'dir' or 'file', cache_obj)) + logger.log('%s cache %s %s' % (result, cache_dir and 'dir' or 'file', cur_cachefile)) if self.tvid_prodid in sickgear.FANART_RATINGS: del sickgear.FANART_RATINGS[self.tvid_prodid] @@ -3470,18 +3483,18 @@ class TVShow(TVShowBase): try: img_obj = image_cache.ImageCache() delete_list = [] - for character in self.cast_list: - for p in character.person: - person_img = img_obj.person_both_paths(p) - for i in person_img: - delete_list.append(i) - character_img = img_obj.character_both_path(character, self) - for i in character_img: - delete_list.append(i) + for cur_character in self.cast_list: + for cur_person in cur_character.person: + person_img = img_obj.person_both_paths(cur_person) + for cur_image in person_img: + delete_list.append(cur_image) + character_img = img_obj.character_both_path(cur_character, self) + for cur_image in character_img: + delete_list.append(cur_image) - for d in delete_list: + for cur_delete in delete_list: try: - remove_file_perm(d) + remove_file_perm(cur_delete) except (BaseException, Exception): pass except (BaseException, Exception): @@ -3528,8 +3541,8 @@ class TVShow(TVShowBase): [self.tvid, self.prodid, old_tvid, old_prodid]) del_mapping(old_tvid, old_prodid) try: - for c in self.cast_list: # type: Character - c.remove_all_img(tvid=old_tvid, proid=old_prodid) + for cur_cast in self.cast_list: # type: Character + cur_cast.remove_all_img(tvid=old_tvid, proid=old_prodid) except (BaseException, Exception): pass self._cast_list = None @@ -3716,10 +3729,10 @@ class TVShow(TVShowBase): initial_qualities, archive_qualities = Quality.split_quality(self._quality) all_qualities = list(set(initial_qualities + archive_qualities)) - initial = '= (%s)' % ','.join([Quality.qualityStrings[qual] for qual in initial_qualities]) + initial = '= (%s)' % ','.join([Quality.qualityStrings[cur_qual] for cur_qual in initial_qualities]) if 0 < len(archive_qualities): initial = '+ upgrade to %s + (%s)'\ - % (initial, ','.join([Quality.qualityStrings[qual] for qual in archive_qualities])) + % (initial, ','.join([Quality.qualityStrings[cur_qual] for cur_qual in archive_qualities])) logger.debug('Want initial %s and found %s' % (initial, Quality.qualityStrings[quality])) if quality not in all_qualities: @@ -4001,22 +4014,22 @@ class TVEpisode(TVEpisodeBase): os_hash=sickgear.SUBTITLES_OS_HASH) if sickgear.SUBTITLES_DIR: - for video in subs: - subs_new_path = os.path.join(os.path.dirname(video.path), sickgear.SUBTITLES_DIR) + for cur_video in subs: + subs_new_path = os.path.join(os.path.dirname(cur_video.path), sickgear.SUBTITLES_DIR) dir_exists = helpers.make_dir(subs_new_path) if not dir_exists: logger.error('Unable to create subtitles folder %s' % subs_new_path) else: helpers.chmod_as_parent(subs_new_path) - for subtitle in subs.get(video): - new_file_path = os.path.join(subs_new_path, os.path.basename(subtitle.path)) - helpers.move_file(subtitle.path, new_file_path) + for cur_subtitle in subs.get(cur_video): + new_file_path = os.path.join(subs_new_path, os.path.basename(cur_subtitle.path)) + helpers.move_file(cur_subtitle.path, new_file_path) helpers.chmod_as_parent(new_file_path) else: - for video in subs: - for subtitle in subs.get(video): - helpers.chmod_as_parent(subtitle.path) + for cur_video in subs: + for cur_subtitle in subs.get(cur_video): + helpers.chmod_as_parent(cur_subtitle.path) except (BaseException, Exception): logger.error('Error occurred when downloading subtitles: %s' % traceback.format_exc()) @@ -4032,7 +4045,7 @@ class TVEpisode(TVEpisodeBase): if newsubtitles: try: - subtitle_list = ", ".join([subliminal.language.Language(x).name for x in newsubtitles]) + subtitle_list = ", ".join([subliminal.language.Language(_x).name for _x in newsubtitles]) except (BaseException, Exception): logger.debug(f'Could not parse a language to use to fetch subtitles' f' for episode {self.season}x{self.episode}') @@ -4047,10 +4060,10 @@ class TVEpisode(TVEpisodeBase): f' for episode {self.season}x{self.episode}') if sickgear.SUBTITLES_HISTORY: - for video in subs: - for subtitle in subs.get(video): + for cur_video in subs: + for cur_subtitle in subs.get(cur_video): history.log_subtitle(self.show_obj.tvid, self.show_obj.prodid, - self.season, self.episode, self.status, subtitle) + self.season, self.episode, self.status, cur_subtitle) return subs @@ -4355,7 +4368,7 @@ class TVEpisode(TVEpisodeBase): firstaired = getattr(ep_info, 'firstaired', None) if None is firstaired or firstaired in '0000-00-00': firstaired = str(datetime.date.fromordinal(1)) - raw_airdate = [int(x) for x in firstaired.split('-')] + raw_airdate = [int(_x) for _x in firstaired.split('-')] old_airdate_future = self._airdate == datetime.date.fromordinal(1) or self._airdate >= datetime.date.today() try: @@ -4560,22 +4573,22 @@ class TVEpisode(TVEpisodeBase): # TODO: deprecated function getiterator needs to be replaced # for epDetails in showXML.getiterator('episodedetails'): - for epDetails in list(show_xml.iter('episodedetails')): - if None is epDetails.findtext('season') or int(epDetails.findtext('season')) != self._season or \ - None is epDetails.findtext('episode') or int( - epDetails.findtext('episode')) != self._episode: + for cur_detail in list(show_xml.iter('episodedetails')): + if None is cur_detail.findtext('season') or int(cur_detail.findtext('season')) != self._season or \ + None is cur_detail.findtext('episode') or int( + cur_detail.findtext('episode')) != self._episode: logger.debug(f'{self._show_obj.tvid_prodid}' f': NFO has an block for a different episode - wanted' f' {self._season}x{self._episode}' - f' but got {epDetails.findtext("season")}x{epDetails.findtext("episode")}') + f' but got {cur_detail.findtext("season")}x{cur_detail.findtext("episode")}') continue - if None is epDetails.findtext('title') or None is epDetails.findtext('aired'): + if None is cur_detail.findtext('title') or None is cur_detail.findtext('aired'): raise exceptions_helper.NoNFOException('Error in NFO format (missing episode title or airdate)') - self.name = epDetails.findtext('title') - self.episode = int(epDetails.findtext('episode')) - self.season = int(epDetails.findtext('season')) + self.name = cur_detail.findtext('title') + self.episode = int(cur_detail.findtext('episode')) + self.season = int(cur_detail.findtext('season')) sickgear.scene_numbering.xem_refresh(self._show_obj.tvid, self._show_obj.prodid) @@ -4588,12 +4601,12 @@ class TVEpisode(TVEpisodeBase): self._show_obj.tvid, self._show_obj.prodid, self._season, self._episode, show_obj=self._show_obj) - self.description = epDetails.findtext('plot') + self.description = cur_detail.findtext('plot') if None is self._description: self.description = '' - if epDetails.findtext('aired'): - raw_airdate = [int(x) for x in epDetails.findtext('aired').split("-")] + if cur_detail.findtext('aired'): + raw_airdate = [int(_x) for _x in cur_detail.findtext('aired').split("-")] self.airdate = datetime.date(raw_airdate[0], raw_airdate[1], raw_airdate[2]) else: self.airdate = datetime.date.fromordinal(1) @@ -4759,7 +4772,7 @@ class TVEpisode(TVEpisodeBase): self._season, self._episode, self._epid, self._tvid, self._name, self._description, - ','.join([sub for sub in self._subtitles]), self._subtitles_searchcount, self._subtitles_lastsearch, + ','.join([_sub for _sub in self._subtitles]), self._subtitles_searchcount, self._subtitles_lastsearch, self._airdate.toordinal(), self._hasnfo, self._hastbn, self._status, self._location, self._file_size, self._release_name, self._is_proper, self._show_obj.prodid, self._season, self._episode, self._absolute_number, @@ -4809,7 +4822,7 @@ class TVEpisode(TVEpisodeBase): release_name=self._release_name, runtime=self._runtime, status=self._status, - subtitles=','.join([sub for sub in self._subtitles]), + subtitles=','.join([_sub for _sub in self._subtitles]), subtitles_lastsearch=self._subtitles_lastsearch, subtitles_searchcount=self._subtitles_searchcount, timestamp=self._timestamp, @@ -4886,7 +4899,7 @@ class TVEpisode(TVEpisodeBase): single_name = True known_good_name = None - for cur_name in [self._name] + [x.name for x in self.related_ep_obj]: + for cur_name in [self._name] + [_x.name for _x in self.related_ep_obj]: match = re.match(multi_name_regex, cur_name) if not match: single_name = False @@ -4902,8 +4915,8 @@ class TVEpisode(TVEpisodeBase): good_name = known_good_name else: good_name = self._name - for ep_obj in self.related_ep_obj: - good_name += ' & ' + ep_obj.name + for cur_ep_obj in self.related_ep_obj: + good_name += ' & ' + cur_ep_obj.name return good_name or 'tba' @@ -5287,8 +5300,8 @@ class TVEpisode(TVEpisodeBase): if any_renamed: with self.lock: self.location = absolute_proper_path + file_ext - for ep_obj in self.related_ep_obj: - ep_obj.location = absolute_proper_path + file_ext + for cur_ep_obj in self.related_ep_obj: + cur_ep_obj.location = absolute_proper_path + file_ext # in case something changed with the metadata just do a quick check for cur_ep_obj in [self] + self.related_ep_obj: @@ -5297,8 +5310,8 @@ class TVEpisode(TVEpisodeBase): # save any changes to the database sql_l = [] with self.lock: - for ep_obj in [self] + self.related_ep_obj: - ep_sql = ep_obj.get_sql() + for cur_ep_obj in [self] + self.related_ep_obj: + ep_sql = cur_ep_obj.get_sql() if None is not ep_sql: sql_l.append(ep_sql) diff --git a/sickgear/webserve.py b/sickgear/webserve.py index 447c2a54..52d0d0df 100644 --- a/sickgear/webserve.py +++ b/sickgear/webserve.py @@ -4173,7 +4173,7 @@ class AddShows(Home): + ('', '&lid=%s' % sickgear.TVInfoAPI().config.get('langabbv_to_id', {}).get(lang, lang))[TVINFO_TVDB == tvid], int(show['id']), show['seriesname'], helpers.xhtml_escape(show['seriesname']), show['firstaired'], - (isinstance(show['firstaired'], string_types) + (isinstance(show['firstaired'], string_types) and show['firstaired'] and SGDatetime.sbfdate(_parse_date(show['firstaired'])) or ''), show.get('network', '') or '', # 11 (show.get('genres', '') or show.get('genre', '') or '').replace('|', ', '), # 12