public
Description: Simple to use TVDB (thetvdb.com) API in Python, and automatic TV episode namer
Homepage: http://dbr.lighthouseapp.com/projects/13342-tvdb_api/tickets
Clone URL: git://github.com/dbr/tvdb_api.git
tvdb_api / tvdb_ui.py
100644 126 lines (102 sloc) 4.442 kb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
#!/usr/bin/env python
#encoding:utf-8
#author:dbr/Ben
#project:tvdb_api
#repository:http://github.com/dbr/tvdb_api
#license:Creative Commons GNU GPL v2
# (http://creativecommons.org/licenses/GPL/2.0/)
 
"""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 "selectSeries", 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': u'Lost', 'sid': u'73739'},
{'name': u'Lost Universe', 'sid': u'73181'}]
 
The "selectSeries" 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 selectSeries(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)
<class 'tvdb_api.Show'>
"""
 
__author__ = "dbr/Ben"
__version__ = "1.2.2"
 
from tvdb_exceptions import tvdb_userabort
 
class BaseUI:
    """Default non-interactive UI, which auto-selects first results
"""
    def __init__(self, config, log):
        self.config = config
        self.log = log
 
    def selectSeries(self, allSeries):
        return allSeries[0]
 
 
class ConsoleUI(BaseUI):
    """Interactively allows the user to select a show from a console based UI
"""
 
    def _displaySeries(self, allSeries):
        """Helper function, lists series with corresponding ID
"""
        print "TVDB Search Results:"
        for i, cshow in enumerate(allSeries[:6]):
            i_show = i + 1 # Start at more human readable number 1 (not 0)
            self.log.debug('Showing allSeries[%s], series %s)' % (i_show, allSeries[i]['seriesname']))
            print "%s -> %s [%s] # http://thetvdb.com/?tab=series&id=%s" % (
                i_show,
                cshow['seriesname'].encode("UTF-8", "ignore"),
                cshow['language'].encode("UTF-8", "ignore"),
                cshow['id'].encode("UTF-8", "ignore")
            )
 
    def selectSeries(self, allSeries):
        self._displaySeries(allSeries)
 
        if len(allSeries) == 1:
            # Single result, return it!
            print "Automatically selecting only result"
            return allSeries[0]
 
        if self.config['select_first'] is True:
            print "Automatically returning first search result"
            return allSeries[0]
 
        while True: # return breaks this loop
            try:
                print "Enter choice (first number, ? for help):"
                ans = raw_input()
            except KeyboardInterrupt:
                raise tvdb_userabort("User aborted (^c keyboard interupt)")
            except EOFError:
                raise tvdb_userabort("User aborted (EOF received)")
 
            self.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 ans == "q":
                    self.log.debug('Got quit command (q)')
                    raise tvdb_userabort("User aborted ('q' quit command)")
                elif ans == "?":
                    print "## Help"
                    print "# Enter the number that corresponds to the correct show."
                    print "# ? - this help"
                    print "# q - abort tvnamer"
                else:
                    self.log.debug('Unknown keypress %s' % (ans))
            else:
                self.log.debug('Trying to return ID: %d' % (selected_id))
                try:
                    return allSeries[ selected_id ]
                except IndexError:
                    self.log.debug('Invalid show number entered!')
                    print "Invalid number (%s) selected!"
                    self._displaySeries(allSeries)
            #end try
        #end while not valid_input