From 5490e48c0617bc91a6334f0742ace60f2e384fa8 Mon Sep 17 00:00:00 2001 From: Steve Erlenborn <1751095+SteveErl@users.noreply.github.com> Date: Tue, 29 Nov 2022 21:17:40 -0600 Subject: [PATCH] Handle null Country TvMaze field A recording of a broadcast of the first episode in season 16 of "Criminal Minds" on CBS lead to a metadata lookup failure. The general syntax for this metadata lookup was: tvmaze.py -N "Criminal Minds" "2022-11-24 11:00:00" Investigation revealed that for recent years this show is normally only available on a streaming service called Paramount+. https://api.tvmaze.com/shows/81 ... "webChannel":{"id":107,"name":"Paramount+", "country":null,"officialSite": "https://www.paramountplus.com/"} ... The null value for Country caused the Timezone retrieval code in tvmaze.py to fail. The code has been updated to handle a null Country field. While regression testing, another crash appeared. tvmaze.py -N "The Masked Singer" "2022-11-24 19:00:00" This show has distinct versions in many countries and timezones. country='United States', timezone='America/New_York' country='United Kingdom', timezone='Europe/London' country='Australia', timezone='Australia/Sydney' country='Belgium', timezone='Europe/Brussels' country=None, show_tz =None (Japanese version) country='Finland', timezone='Europe/Helsinki' country='Germany', timezone='Europe/Busingen' country='Israel', timezone='Asia/Jerusalem' country='Mexico', timezone='America/Monterrey' The null Country field for the Japanese version is handled fine, but passing 'Asia/Jerusalem' to astimezone() caused it to throw an exception. UnboundLocalError: local variable 'ttmfmt' referenced before assignment This appears to be a bug in python3. To prevent it from crashing our script, UnboundLocalError has been added to the exception catcher. Some of the debug print messages have also been updated to improve their format. Refs: #654 --- .../scripts/metadata/Television/tvmaze.py | 27 ++++++++++++------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/mythtv/programs/scripts/metadata/Television/tvmaze.py b/mythtv/programs/scripts/metadata/Television/tvmaze.py index 9f0a04877bb..50553b3ab94 100755 --- a/mythtv/programs/scripts/metadata/Television/tvmaze.py +++ b/mythtv/programs/scripts/metadata/Television/tvmaze.py @@ -227,10 +227,19 @@ def buildNumbers(args, opts): if show_network is None: show_network = show_info.streaming_service show_country = show_network.get('country') - show_tz = show_country.get('timezone') + # Some webChannels don't specify country or timezone + if show_country: + show_tz = show_country.get('timezone') + else: + show_tz = None dtInTgtZone = dtInLocalZone.astimezone(posixtzinfo(show_tz)) + # For at least one timezone, the following exception may be thrown. + # UnboundLocalError: local variable 'ttmfmt' referenced before assignment + # Example: tvmaze.py --debug -N "The Masked Singer" "2022-11-24 19:00:00" - except (ValueError, AttributeError) as e: + except (ValueError, AttributeError, UnboundLocalError) as e: + if opts.debug: + print('show_tz =%s, except = %s' % (show_tz, e)) dtInTgtZone = None if dtInTgtZone: @@ -253,18 +262,16 @@ def buildNumbers(args, opts): if epInTgtZone == dtInTgtZone: if opts.debug: - print('Recording matches inetref %d, season %d, episode %d at %s' \ - % (inetref, ep.season, ep.number, epInTgtZone)) + print('Recording matches \'%s\' at %s' % (ep, epInTgtZone)) time_match_list.append(i) minTimeDelta = timedelta(minutes=0) - # Consider it a match if the recording starts late, # but within the duration of the show. elif epInTgtZone < dtInTgtZone < epInTgtZone+durationDelta: # Recording start time is within the range of this episode if opts.debug: - print('Recording in range of inetref %d, season %d, episode %d (%s ... %s)' \ - % (inetref, ep.season, ep.number, epInTgtZone, epInTgtZone+durationDelta)) + print('Recording in range of \'%s\' (%s ... %s)' \ + % (ep, epInTgtZone, epInTgtZone+durationDelta)) time_match_list.append(i) minTimeDelta = timedelta(minutes=0) # Consider it a match if the recording is a little bit early. This helps cases @@ -274,11 +281,13 @@ def buildNumbers(args, opts): # Recording started earlier than this episode, so see if it's the closest match if epInTgtZone - dtInTgtZone == minTimeDelta: if opts.debug: - print('adding episode to closest list', epInTgtZone - dtInTgtZone, '\n') + print('Adding episode \'%s\' to closest list. Offset = %s' \ + % (ep, epInTgtZone - dtInTgtZone)) early_match_list.append(i) elif epInTgtZone - dtInTgtZone < minTimeDelta: if opts.debug: - print('this episode is new closest', epInTgtZone - dtInTgtZone, '\n') + print('Episode \'%s\' is new closest. Offset = %s' \ + % (ep, epInTgtZone - dtInTgtZone)) minTimeDelta = epInTgtZone - dtInTgtZone early_match_list = [i]