#!/usr/bin/env python2 # encoding:utf-8 # author:dbr/Ben # project:tvdb_api # repository:http://github.com/dbr/tvdb_api # license:unlicense (http://unlicense.org/) """Contains included user interfaces for Tvdb show selection. A UI is a callback. A class, it's __init__ function takes two arguments: - config, which is the Tvdb config dict, setup in tvdb_api.py - log, which is Tvdb's logger instance (which uses the logging module). You can call log.info() log.warning() etc It must have a method "select_series", this is passed a list of dicts, each dict contains the the keys "name" (human readable show name), and "sid" (the shows ID as on thetvdb.com). For example: [{'name': 'Lost', 'sid': '73739'}, {'name': 'Lost Universe', 'sid': '73181'}] The "select_series" method must return the appropriate dict, or it can raise tvdb_userabort (if the selection is aborted), tvdb_shownotfound (if the show cannot be found). A simple example callback, which returns a random series: # >>> import random # >>> from tvdb_ui import BaseUI # >>> class RandomUI(BaseUI): # ... def select_series(self, allSeries): # ... import random # ... return random.choice(allSeries) Then to use it.. # >>> from tvdb_api import Tvdb # >>> t = Tvdb(custom_ui = RandomUI) # >>> random_matching_series = t['Lost'] # >>> type(random_matching_series) # """ __author__ = "dbr/Ben" __version__ = "1.9" import logging import warnings from .tvdb_exceptions import TvdbUserabort from six import moves def log(): return logging.getLogger(__name__) class BaseUI(object): """Default non-interactive UI, which auto-selects first results """ def __init__(self, config, log=None): self.config = config if None is not log: warnings.warn("the UI's log parameter is deprecated, instead use\n" "use import logging; logging.getLogger('ui').info('blah')\n" "The self.log attribute will be removed in the next version") self.log = logging.getLogger(__name__) def select_series(self, all_series): return all_series[0] class ConsoleUI(BaseUI): """Interactively allows the user to select a show from a console based UI """ @staticmethod def _displaySeries(all_series, limit=6): """Helper function, lists series with corresponding ID """ if None is not limit: toshow = all_series[:limit] else: toshow = all_series print('TVDB Search Results:') for i, cshow in enumerate(toshow): i_show = i + 1 # Start at more human readable number 1 (not 0) log().debug('Showing allSeries[%s], series %s)' % (i_show, all_series[i]['seriesname'])) if 0 == i: extra = " (default)" else: extra = "" print ('%s -> %s [%s] # http://thetvdb.com/?tab=series&id=%s&lid=%s%s' % ( i_show, cshow['seriesname'].encode('UTF-8', 'ignore'), cshow['language'].encode('UTF-8', 'ignore'), str(cshow['id']), cshow['lid'], extra )) def select_series(self, all_series): self._displaySeries(all_series) if 1 == len(all_series): # Single result, return it! print('Automatically selecting only result') return all_series[0] if self.config['select_first'] is True: print('Automatically returning first search result') return all_series[0] while True: # return breaks this loop try: print('Enter choice (first number, return for default, \'all\', ? for help):') ans = moves.input() except KeyboardInterrupt: raise TvdbUserabort("User aborted (^c keyboard interupt)") except EOFError: raise TvdbUserabort("User aborted (EOF received)") log().debug('Got choice of: %s' % ans) try: selected_id = int(ans) - 1 # The human entered 1 as first result, not zero except ValueError: # Input was not number if 0 == len(ans.strip()): # Default option log().debug('Default option, returning first series') return all_series[0] if "q" == ans: log().debug('Got quit command (q)') raise TvdbUserabort("User aborted ('q' quit command)") elif "?" == ans: print('## Help') print('# Enter the number that corresponds to the correct show.') print('# a - display all results') print('# all - display all results') print('# ? - this help') print('# q - abort tvnamer') print('# Press return with no input to select first result') elif ans.lower() in ["a", "all"]: self._displaySeries(all_series, limit=None) else: log().debug('Unknown keypress %s' % ans) else: log().debug('Trying to return ID: %d' % selected_id) try: return all_series[selected_id] except IndexError: log().debug('Invalid show number entered!') print('Invalid number (%s) selected!') self._displaySeries(all_series)