dbr / tvdb_api

Simple to use TVDB (thetvdb.com) API in Python. The automatic TV episode namer "tvnamer" is now in a separate repository http://github.com/dbr/tvnamer

This URL has Read+Write access

tvdb_api / tvnamer.py
e01ec1b6 » dbr 2008-05-07 Added (semi-)automated TV e... 1 #!/usr/bin/env python
2 #encoding:utf-8
edc2372d » dbr 2008-06-22 Added Creative Commons GNU ... 3 #author:dbr/Ben
4 #project:tvdb_api
5 #repository:http://github.com/dbr/tvdb_api
70ed746b » dbr 2008-07-22 Made headers match tvdb_api... 6 #license:Creative Commons GNU GPL v2
7 # (http://creativecommons.org/licenses/GPL/2.0/)
e01ec1b6 » dbr 2008-05-07 Added (semi-)automated TV e... 8
b366cfe4 » dbr 2008-07-21 Made tvnamer and tvdb_api a... 9 """
10 tvnamer.py
11 Automatic TV episode namer.
12 Uses data from www.thetvdb.com via tvdb_api
13 """
14
e01ec1b6 » dbr 2008-05-07 Added (semi-)automated TV e... 15 __author__ = "dbr/Ben"
a6a1addf » dbr 2008-07-24 Bumped to v0.3 in preperati... 16 __version__ = "0.3"
e01ec1b6 » dbr 2008-05-07 Added (semi-)automated TV e... 17
b366cfe4 » dbr 2008-07-21 Made tvnamer and tvdb_api a... 18 import os, sys, re
e01ec1b6 » dbr 2008-05-07 Added (semi-)automated TV e... 19 from optparse import OptionParser
d1377c02 » dbr 2008-06-09 Added more dockstrings and ... 20
d8af8a37 » dbr 2008-07-23 Import new exceptions 21 from tvdb_api import (tvdb_error, tvdb_shownotfound, tvdb_seasonnotfound,
22 tvdb_episodenotfound, tvdb_episodenotfound, tvdb_attributenotfound, tvdb_userabort)
472a73d4 » dbr 2008-07-21 Use Tvdb, not tvdb 23 from tvdb_api import Tvdb
e01ec1b6 » dbr 2008-05-07 Added (semi-)automated TV e... 24
fe3a957f » dbr 2008-07-23 Cleaning up "abc=[]" lines ... 25 config = {}
e01ec1b6 » dbr 2008-05-07 Added (semi-)automated TV e... 26
d1377c02 » dbr 2008-06-09 Added more dockstrings and ... 27 # The format of the renamed files (with and without episode names)
e01ec1b6 » dbr 2008-05-07 Added (semi-)automated TV e... 28 config['with_ep_name'] = '%(showname)s - [%(seasno)02dx%(epno)02d] - %(epname)s.%(ext)s'
29 config['without_ep_name'] = '%(showname)s - [%(seasno)02dx%(epno)02d].%(ext)s'
30
d1377c02 » dbr 2008-06-09 Added more dockstrings and ... 31 config['valid_filename_chars'] = """0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!@£$%^&*()_+=-[]{}"'.,<>`~? """
45262d4f » dbr 2008-07-23 Cleaning up the new regex, ... 32 config['valid_filename_chars_regex'] = re.escape(config['valid_filename_chars'])
d1377c02 » dbr 2008-06-09 Added more dockstrings and ... 33
34 # Regex's to parse filenames with. Must have 3 groups, showname, season number
35 # and episode number. Use (?: optional) non-capturing groups if you need others.
e01ec1b6 » dbr 2008-05-07 Added (semi-)automated TV e... 36 config['name_parse'] = [
1041e82c » Doris 2008-07-22 Added support for more file... 37 # foo_[s01]_[e01]
45262d4f » dbr 2008-07-23 Cleaning up the new regex, ... 38 re.compile('''^([%s]+?)[ \._\-]\[[Ss]([0-9]+?)\]_\[[Ee]([0-9]+?)\]?[^\\/]*$'''% (config['valid_filename_chars_regex'])),
1041e82c » Doris 2008-07-22 Added support for more file... 39 # foo.1x09*
45262d4f » dbr 2008-07-23 Cleaning up the new regex, ... 40 re.compile('''^([%s]+?)[ \._\-]\[?([0-9]+)x([0-9]+)[^\\/]*$''' % (config['valid_filename_chars_regex'])),
1041e82c » Doris 2008-07-22 Added support for more file... 41 # foo.s01.e01, foo.s01_e01
8c6f4e35 » dbr 2008-08-12 Allow "show name s01 e02.av... 42 re.compile('''^([%s]+?)[ \._\-][Ss]([0-9]+)[\.\- ]?[Ee]([0-9]+)[^\\/]*$''' % (config['valid_filename_chars_regex'])),
30d96e16 » dbr 2008-07-23 Fixed parsing of "123 2008 ... 43 # foo.103*
44 re.compile('''^([%s]+)[ \._\-]([0-9]{1})([0-9]{2})[\._ -][^\\/]*$''' % (config['valid_filename_chars_regex'])),
45 # foo.0103*
46 re.compile('''^([%s]+)[ \._\-]([0-9]{2})([0-9]{2,3})[\._ -][^\\/]*$''' % (config['valid_filename_chars_regex'])),
e01ec1b6 » dbr 2008-05-07 Added (semi-)automated TV e... 47 ]
48
49
50 def findFiles(args):
d1377c02 » dbr 2008-06-09 Added more dockstrings and ... 51 """
52 Takes a list of files/folders, grabs files inside them. Does not recurse
53 more than one level (if a folder is supplied, it will list files within)
54 """
fe3a957f » dbr 2008-07-23 Cleaning up "abc=[]" lines ... 55 allfiles = []
b366cfe4 » dbr 2008-07-21 Made tvnamer and tvdb_api a... 56 for cfile in args:
57 if os.path.isdir(cfile):
58 for sf in os.listdir(cfile):
59 newpath = os.path.join(cfile, sf)
e01ec1b6 » dbr 2008-05-07 Added (semi-)automated TV e... 60 if os.path.isfile(newpath):
61 allfiles.append(newpath)
62 #end if isfile
63 #end for sf
b366cfe4 » dbr 2008-07-21 Made tvnamer and tvdb_api a... 64 elif os.path.isfile(cfile):
65 allfiles.append(cfile)
e01ec1b6 » dbr 2008-05-07 Added (semi-)automated TV e... 66 #end if isdir
b366cfe4 » dbr 2008-07-21 Made tvnamer and tvdb_api a... 67 #end for cfile
e01ec1b6 » dbr 2008-05-07 Added (semi-)automated TV e... 68 return allfiles
69 #end findFiles
70
b366cfe4 » dbr 2008-07-21 Made tvnamer and tvdb_api a... 71 def processNames(names, verbose=False):
d1377c02 » dbr 2008-06-09 Added more dockstrings and ... 72 """
73 Takes list of names, runs them though the config['name_parse'] regexs
74 """
fe3a957f » dbr 2008-07-23 Cleaning up "abc=[]" lines ... 75 allEps = []
e01ec1b6 » dbr 2008-05-07 Added (semi-)automated TV e... 76 for f in names:
b366cfe4 » dbr 2008-07-21 Made tvnamer and tvdb_api a... 77 filepath, filename = os.path.split( f )
78 filename, ext = os.path.splitext( filename )
2c312811 » dbr 2008-07-24 Commented break statement i... 79
4c9c9fee » dbr 2008-07-24 Moved extension-dot strippi... 80 # Remove leading . from extension
81 ext = ext.replace(".", "", 1)
2c312811 » dbr 2008-07-24 Commented break statement i... 82
e01ec1b6 » dbr 2008-05-07 Added (semi-)automated TV e... 83 for r in config['name_parse']:
84 match = r.match(filename)
85 if match:
b366cfe4 » dbr 2008-07-21 Made tvnamer and tvdb_api a... 86 showname, seasno, epno = match.groups()
2c312811 » dbr 2008-07-24 Commented break statement i... 87
1041e82c » Doris 2008-07-22 Added support for more file... 88 #remove ._- characters from name (- removed only if next to end of line)
2c312811 » dbr 2008-07-24 Commented break statement i... 89 showname = re.sub("[\._]|\-(?=$)", " ", showname).strip()
90
b366cfe4 » dbr 2008-07-21 Made tvnamer and tvdb_api a... 91 seasno, epno = int(seasno), int(epno)
acf8d117 » dbr 2008-06-22 Added verbose argument to p... 92
93 if verbose:
94 print "*"*20
95 print "File:", filename
96 print "Pattern:", r.pattern
97 print "Showname:", showname
98 print "Seas:", seasno
99 print "Ep:", epno
100 print "*"*20
101
77c548eb » dbr 2008-05-15 Moved cfile['showname'] (pa... 102 allEps.append({ 'file_showname':showname,
103 'seasno':seasno,
104 'epno':epno,
105 'filepath':filepath,
106 'filename':filename,
107 'ext':ext
e01ec1b6 » dbr 2008-05-07 Added (semi-)automated TV e... 108 })
2c312811 » dbr 2008-07-24 Commented break statement i... 109 break # Matched - to the next file!
e01ec1b6 » dbr 2008-05-07 Added (semi-)automated TV e... 110 else:
eb2536e7 » dbr 2008-07-23 Fixed a few sytnax problems... 111 print "Invalid name: %s" % (f)
e01ec1b6 » dbr 2008-05-07 Added (semi-)automated TV e... 112 #end for r
113 #end for f
114
115 return allEps
116 #end processNames
117
118 def formatName(cfile):
d1377c02 » dbr 2008-06-09 Added more dockstrings and ... 119 """
120 Takes a file dict and renames files using the configured format
121 """
e01ec1b6 » dbr 2008-05-07 Added (semi-)automated TV e... 122 if cfile['epname']:
123 n = config['with_ep_name'] % (cfile)
124 else:
125 n = config['without_ep_name'] % (cfile)
126 #end if epname
127 return n
128 #end formatName
129
130 def cleanName(name):
d1377c02 » dbr 2008-06-09 Added more dockstrings and ... 131 """
132 Cleans the supplied filename for renaming-to
133 """
b366cfe4 » dbr 2008-07-21 Made tvnamer and tvdb_api a... 134 name = name.encode('ascii', 'ignore') # convert unicode to ASCII
2b13c73f » dbr 2008-05-15 Deal with unicode corrected... 135
e01ec1b6 » dbr 2008-05-07 Added (semi-)automated TV e... 136 return ''.join( [c for c in name if c in config['valid_filename_chars']] )
d1377c02 » dbr 2008-06-09 Added more dockstrings and ... 137 #end cleanName
e01ec1b6 » dbr 2008-05-07 Added (semi-)automated TV e... 138
b366cfe4 » dbr 2008-07-21 Made tvnamer and tvdb_api a... 139 def renameFile(oldfile, newfile, force=False):
d1377c02 » dbr 2008-06-09 Added more dockstrings and ... 140 """
141 Renames files, does not overwrite files unless forced
142 """
b366cfe4 » dbr 2008-07-21 Made tvnamer and tvdb_api a... 143 new_exists = os.access(newfile, os.F_OK)
e01ec1b6 » dbr 2008-05-07 Added (semi-)automated TV e... 144 if new_exists:
145 sys.stderr.write("New filename already exists.. ")
146 if force:
147 sys.stderr.write("overwriting\n")
b366cfe4 » dbr 2008-07-21 Made tvnamer and tvdb_api a... 148 os.rename(oldfile, newfile)
e01ec1b6 » dbr 2008-05-07 Added (semi-)automated TV e... 149 else:
150 sys.stderr.write("skipping\n")
151 return False
152 #end if force
153 else:
b366cfe4 » dbr 2008-07-21 Made tvnamer and tvdb_api a... 154 os.rename(oldfile, newfile)
e01ec1b6 » dbr 2008-05-07 Added (semi-)automated TV e... 155 return True
156 #end if new_exists
157
158
159 def main():
9581e2c8 » dbr 2008-05-09 Improved --help output, vai... 160 parser = OptionParser(usage="%prog [options] <file or directories>")
e01ec1b6 » dbr 2008-05-07 Added (semi-)automated TV e... 161
b366cfe4 » dbr 2008-07-21 Made tvnamer and tvdb_api a... 162 parser.add_option( "-d", "--debug", action="store_true", default=False, dest="debug",
9581e2c8 » dbr 2008-05-09 Improved --help output, vai... 163 help="show debugging info")
b366cfe4 » dbr 2008-07-21 Made tvnamer and tvdb_api a... 164 parser.add_option( "-b", "--batch", action="store_false", dest="interactive",
165 help="selects first search result, requires no human intervention once launched", default=False)
166 parser.add_option( "-i", "--interactive", action="store_true", dest="interactive", default=True,
9581e2c8 » dbr 2008-05-09 Improved --help output, vai... 167 help="interactivly select correct show from search results [default]")
b366cfe4 » dbr 2008-07-21 Made tvnamer and tvdb_api a... 168 parser.add_option( "-a", "--always", action="store_true", default=False, dest="always",
9581e2c8 » dbr 2008-05-09 Improved --help output, vai... 169 help="always renames files (but still lets user select correct show). Can be changed during runtime with the 'a' prompt-option")
b366cfe4 » dbr 2008-07-21 Made tvnamer and tvdb_api a... 170 parser.add_option( "-f", "--force", action="store_true", default=False, dest="force",
9581e2c8 » dbr 2008-05-09 Improved --help output, vai... 171 help="forces file to be renamed, even if it will overwrite an existing file")
b366cfe4 » dbr 2008-07-21 Made tvnamer and tvdb_api a... 172 parser.add_option( "-t", "--tests", action="store_true", default=False, dest="dotests",
a5b8a318 » dbr 2008-05-15 Added unittest flag 173 help="Run unittests (mostly useful for development)")
e01ec1b6 » dbr 2008-05-07 Added (semi-)automated TV e... 174
b366cfe4 » dbr 2008-07-21 Made tvnamer and tvdb_api a... 175 opts, args = parser.parse_args()
a5b8a318 » dbr 2008-05-15 Added unittest flag 176
b0d7364e » dbr 2008-05-15 Implimented -t (unittest) f... 177 if opts.dotests:
353dff7b » dbr 2008-07-23 Renamed name parser unittes... 178 suite = unittest.TestLoader().loadTestsFromTestCase(test_name_parser)
b0d7364e » dbr 2008-05-15 Implimented -t (unittest) f... 179 unittest.TextTestRunner(verbosity=2).run(suite)
180 sys.exit(0)
181 #end if dotests
182
e01ec1b6 » dbr 2008-05-07 Added (semi-)automated TV e... 183 if len(args) == 0:
184 parser.error("No filenames or directories supplied")
185 #end if len(args)
186
187 allFiles = findFiles(args)
411e6052 » dbr 2008-07-24 If the debug flag is used, ... 188 validFiles = processNames(allFiles, verbose = opts.debug)
e01ec1b6 » dbr 2008-05-07 Added (semi-)automated TV e... 189
190 if len(validFiles) == 0:
db9c02a0 » dbr 2008-05-07 No valid files found error ... 191 sys.stderr.write("No valid files found\n")
1883717e » dbr 2008-07-24 tvnamer.py now exits with e... 192 sys.exit(2)
e01ec1b6 » dbr 2008-05-07 Added (semi-)automated TV e... 193
9581e2c8 » dbr 2008-05-09 Improved --help output, vai... 194 print "#"*20
195 print "# Starting tvnamer"
196 print "# Processing %d files" % ( len(validFiles) )
197
472a73d4 » dbr 2008-07-21 Use Tvdb, not tvdb 198 t = Tvdb(debug = opts.debug, interactive = opts.interactive)
9581e2c8 » dbr 2008-05-09 Improved --help output, vai... 199
200 print "# ..got tvdb mirrors"
201 print "# Starting to process files"
df6389fc » dbr 2008-06-09 Improved console GUI (made ... 202 print "#"*20
9581e2c8 » dbr 2008-05-09 Improved --help output, vai... 203
e01ec1b6 » dbr 2008-05-07 Added (semi-)automated TV e... 204 for cfile in validFiles:
4f8a41a6 » dbr 2008-06-24 Improved user-input handlin... 205 print "# Processing %(file_showname)s (season: %(seasno)d, episode %(epno)d)" % (cfile)
77c548eb » dbr 2008-05-15 Moved cfile['showname'] (pa... 206 try:
4f8a41a6 » dbr 2008-06-24 Improved user-input handlin... 207 # Ask for episode name from tvdb_api
a1a532ea » dbr 2008-08-03 Now retrive all episode dat... 208 epname = t[ cfile['file_showname'] ][ cfile['seasno'] ][ cfile['epno'] ]['episodename']
5261f621 » dbr 2008-07-23 Using the new exceptions to... 209 except tvdb_shownotfound:
210 # No such show found.
211 # Use the show-name from the files name, and None as the ep name
212 sys.stderr.write("! Warning: Show %s not found (in %s)\n" % (
213 cfile['file_showname'],
214 cfile['filepath'] )
215 )
216
217 cfile['showname'] = cfile['file_showname']
e01ec1b6 » dbr 2008-05-07 Added (semi-)automated TV e... 218 cfile['epname'] = None
5261f621 » dbr 2008-07-23 Using the new exceptions to... 219 except (tvdb_seasonnotfound, tvdb_episodenotfound, tvdb_attributenotfound):
220 # The season, episode or name wasn't found, but the show was.
221 # Use the corrected show-name, but no episode name.
b366cfe4 » dbr 2008-07-21 Made tvnamer and tvdb_api a... 222 sys.stderr.write("! Warning: Episode name not found for %s (in %s)\n" % (
223 cfile['file_showname'],
224 cfile['filepath'] )
225 )
5261f621 » dbr 2008-07-23 Using the new exceptions to... 226
227 cfile['showname'] = t[ cfile['file_showname'] ]['showname']
228 cfile['epname'] = None
74e11400 » dbr 2008-08-07 Handle the tvdb_error (gene... 229 except tvdb_error, errormsg:
230 # Error communicating with thetvdb.com
231 sys.stderr.write(
232 "! Warning: Error contacting www.thetvdb.com:\n%s\n" % (errormsg)
233 )
234
235 cfile['showname'] = t[ cfile['file_showname'] ]['showname']
236 cfile['epname'] = None
237 except tvdb_userabort, errormsg:
5261f621 » dbr 2008-07-23 Using the new exceptions to... 238 # User aborted selection (q or ^c)
239 print "\n", errormsg
eb2536e7 » dbr 2008-07-23 Fixed a few sytnax problems... 240 sys.exit(1)
77c548eb » dbr 2008-05-15 Moved cfile['showname'] (pa... 241 else:
5261f621 » dbr 2008-07-23 Using the new exceptions to... 242 cfile['epname'] = epname
243 cfile['showname'] = t[ cfile['file_showname'] ]['showname'] # get the corrected showname
77c548eb » dbr 2008-05-15 Moved cfile['showname'] (pa... 244
9581e2c8 » dbr 2008-05-09 Improved --help output, vai... 245 # Format new filename, strip unwanted characters
3f3eeabb » dbr 2008-06-24 Cleaned up formatName( cfil... 246 newname = formatName(cfile)
e01ec1b6 » dbr 2008-05-07 Added (semi-)automated TV e... 247 newname = cleanName(newname)
9581e2c8 » dbr 2008-05-09 Improved --help output, vai... 248
249 # Append new filename (with extension) to path
250 oldfile = os.path.join(
251 cfile['filepath'],
38bfb31a » Doris 2008-07-23 Fixed bug with script not k... 252 cfile['filename'] + "." + cfile['ext']
9581e2c8 » dbr 2008-05-09 Improved --help output, vai... 253 )
254 # Join path to new file name
255 newfile = os.path.join(
256 cfile['filepath'],
257 newname
258 )
259
260 # Show new/old filename
261 print "#"*20
38bfb31a » Doris 2008-07-23 Fixed bug with script not k... 262 print "Old name: %s" % ( cfile['filename'] + "." + cfile['ext'] )
e01ec1b6 » dbr 2008-05-07 Added (semi-)automated TV e... 263 print "New name: %s" % ( newname )
264
9581e2c8 » dbr 2008-05-09 Improved --help output, vai... 265 # Either always rename, or prompt user
29fdfbb9 » dbr 2008-06-09 Fixed "always rename" optio... 266 if opts.always or (not opts.interactive):
b366cfe4 » dbr 2008-07-21 Made tvnamer and tvdb_api a... 267 rename_result = renameFile(oldfile, newfile, force=opts.force)
e01ec1b6 » dbr 2008-05-07 Added (semi-)automated TV e... 268 if rename_result:
269 print "..auto-renaming"
270 else:
271 print "..not renamed"
4f8a41a6 » dbr 2008-06-24 Improved user-input handlin... 272 #end if rename_result
273
e01ec1b6 » dbr 2008-05-07 Added (semi-)automated TV e... 274 continue # next filename!
275 #end if always
276
e731b73a » dbr 2008-07-23 Handle incorrect input into... 277 ans = None
278 while ans not in ['y', 'n', 'a', 'q', '']:
279 print "Rename?"
280 print "([y]/n/a/q)",
281 try:
282 ans = raw_input().strip()
283 except KeyboardInterrupt, errormsg:
eb2536e7 » dbr 2008-07-23 Fixed a few sytnax problems... 284 print "\n", errormsg
285 sys.exit(1)
e731b73a » dbr 2008-07-23 Handle incorrect input into... 286 #end try
287 #end while
4f8a41a6 » dbr 2008-06-24 Improved user-input handlin... 288
289 if len(ans) == 0:
290 print "Renaming (default)"
b366cfe4 » dbr 2008-07-21 Made tvnamer and tvdb_api a... 291 rename_result = renameFile(oldfile, newfile, force=opts.force)
4f8a41a6 » dbr 2008-06-24 Improved user-input handlin... 292 elif ans[0] == "a":
fe3a957f » dbr 2008-07-23 Cleaning up "abc=[]" lines ... 293 opts.always = True
b366cfe4 » dbr 2008-07-21 Made tvnamer and tvdb_api a... 294 rename_result = renameFile(oldfile, newfile, force=opts.force)
e01ec1b6 » dbr 2008-05-07 Added (semi-)automated TV e... 295 elif ans[0] == "q":
296 print "Aborting"
1883717e » dbr 2008-07-24 tvnamer.py now exits with e... 297 sys.exit(1)
e01ec1b6 » dbr 2008-05-07 Added (semi-)automated TV e... 298 elif ans[0] == "y":
b366cfe4 » dbr 2008-07-21 Made tvnamer and tvdb_api a... 299 rename_result = renameFile(oldfile, newfile, force=opts.force)
e01ec1b6 » dbr 2008-05-07 Added (semi-)automated TV e... 300 elif ans[0] == "n":
301 print "Skipping"
302 continue
d1377c02 » dbr 2008-06-09 Added more dockstrings and ... 303 else:
4f8a41a6 » dbr 2008-06-24 Improved user-input handlin... 304 print "Invalid input, skipping"
e01ec1b6 » dbr 2008-05-07 Added (semi-)automated TV e... 305 #end if ans
306 if rename_result:
307 print "..renamed"
308 else:
309 print "..not renamed"
310 #end if rename_result
311 #end for cfile
3f3eeabb » dbr 2008-06-24 Cleaned up formatName( cfil... 312 print "# Done"
e01ec1b6 » dbr 2008-05-07 Added (semi-)automated TV e... 313 #end main
314
5708b2b9 » dbr 2008-05-15 Numerous fixes to filename ... 315 import unittest
353dff7b » dbr 2008-07-23 Renamed name parser unittes... 316 class test_name_parser(unittest.TestCase):
b5fea24f » dbr 2008-06-22 Hugely improved unittests, ... 317 def setUp(self):
eb2536e7 » dbr 2008-07-23 Fixed a few sytnax problems... 318 """
319 Define name formats to test.
320 %(showname)s becomes the showname,
321 %(seasno)s becomes the season number,
322 %(epno)s becomes the episode number.
323
324 The verbose setting currently shows which
325 regex matches each filename, and the values
326 it found in each of the three groups.
327 """
2e51dd9a » dbr 2008-07-23 Commented what the self.ver... 328 # Shows verbose regex matching information
b5fea24f » dbr 2008-06-22 Hugely improved unittests, ... 329 self.verbose = False
330
1041e82c » Doris 2008-07-22 Added support for more file... 331 #scene naming standards: http://tvunderground.org.ru/forum/index.php?showtopic=8488
b5fea24f » dbr 2008-06-22 Hugely improved unittests, ... 332 self.name_formats = [
7fe0c000 » dbr 2008-07-23 Added more name formats to ... 333 '%(showname)s.s%(seasno)de%(epno)d.dsr.nf.avi', #showname.s01e02.dsr.nf.avi
334 '%(showname)s.S%(seasno)dE%(epno)d.PROPER.dsr.nf.avi', #showname.S01E02.PROPER.dsr.nf.avi
335 '%(showname)s.s%(seasno)d.e%(epno)d.avi', #showname.s01.e02.avi
336 '%(showname)s-s%(seasno)de%(epno)d.avi', #showname-s01e02.avi
337 '%(showname)s-s%(seasno)de%(epno)d.the.wrong.ep.name.avi', #showname-s01e02.the.wrong.ep.name.avi
338 '%(showname)s - [%(seasno)dx%(epno)d].avi', #showname - [01x02].avi
339 '%(showname)s - [%(seasno)dx0%(epno)d].avi', #showname - [01x002].avi
340 '%(showname)s-[%(seasno)dx%(epno)d].avi', #showname-[01x02].avi
341 '%(showname)s [%(seasno)dx%(epno)d].avi', #showname [01x02].avi
342 '%(showname)s [%(seasno)dx%(epno)d] the wrong ep name.avi', #showname [01x02] epname.avi
343 '%(showname)s [%(seasno)dx%(epno)d] - the wrong ep name.avi', #showname [01x02] - the wrong ep name.avi
344 '%(showname)s - [%(seasno)dx%(epno)d] - the wrong ep name.avi', #showname - [01x02] - the wrong ep name.avi
345 '%(showname)s.%(seasno)dx%(epno)d.The_Wrong_ep_name.avi', #showname.01x02.epname.avi
346 '%(showname)s.%(seasno)d%(epno)02d.The Wrong_ep.names.avi', #showname.102.epname.avi
347 '%(showname)s_s%(seasno)de%(epno)d_The_Wrong_ep_na-me.avi', #showname_s1e02_epname.avi
348 '%(showname)s - s%(seasno)de%(epno)d - dsr.nf.avi' #showname - s01e02 - dsr.nf.avi
349 '%(showname)s - s%(seasno)de%(epno)d - the wrong ep name.avi' #showname - s01e02 - the wrong ep name.avi
350 '%(showname)s - s%(seasno)de%(epno)d - the wrong ep name.avi' #showname - s01e02 - the_wrong_ep_name!.avi
5708b2b9 » dbr 2008-05-15 Numerous fixes to filename ... 351 ]
b5fea24f » dbr 2008-06-22 Hugely improved unittests, ... 352
7fe0c000 » dbr 2008-07-23 Added more name formats to ... 353 def test_name_parser_basic(self):
354 """
355 Tests most basic filename (simple showname, season 1 ep 21)
356 """
357 name_data = {'showname':'show name'}
b5fea24f » dbr 2008-06-22 Hugely improved unittests, ... 358
7fe0c000 » dbr 2008-07-23 Added more name formats to ... 359 self._run_test(name_data)
b5fea24f » dbr 2008-06-22 Hugely improved unittests, ... 360 #end test_name_parser
361
362 def test_name_parser_showdashname(self):
7fe0c000 » dbr 2008-07-23 Added more name formats to ... 363 """
364 Tests with dash in showname
365 """
366 name_data = {'showname':'S-how name'}
b5fea24f » dbr 2008-06-22 Hugely improved unittests, ... 367
7fe0c000 » dbr 2008-07-23 Added more name formats to ... 368 self._run_test(name_data)
b5fea24f » dbr 2008-06-22 Hugely improved unittests, ... 369 #end test_name_parser_showdashname
370
371 def test_name_parser_shownumeric(self):
30d96e16 » dbr 2008-07-23 Fixed parsing of "123 2008 ... 372 """
373 Tests with numeric show name
374 """
7fe0c000 » dbr 2008-07-23 Added more name formats to ... 375 name_data = {'showname':'123'}
b5fea24f » dbr 2008-06-22 Hugely improved unittests, ... 376
7fe0c000 » dbr 2008-07-23 Added more name formats to ... 377 self._run_test(name_data)
b5fea24f » dbr 2008-06-22 Hugely improved unittests, ... 378 #end test_name_parser_shownumeric
7fe0c000 » dbr 2008-07-23 Added more name formats to ... 379
30d96e16 » dbr 2008-07-23 Fixed parsing of "123 2008 ... 380 def test_name_parser_shownumericspaces(self):
381 """
382 Tests with numeric show name, with spaces
383 """
384 name_data = {'showname':'123 2008'}
385
386 self._run_test(name_data)
387 #end test_name_parser_shownumeric
388
7fe0c000 » dbr 2008-07-23 Added more name formats to ... 389 def test_name_parser_exclaim(self):
390 name_data = {'showname':'Show name!'}
391
392 self._run_test(name_data)
393 #end test_name_parser_exclaim
394
395 def test_name_parser_num_seq(self):
396 name_data = {'showname' : 'Show name'}
397 self._run_test(name_data)
398 #end test_name_parser_num_seq
399
400 def _run_test(self, name_data):
401 """
402 Runs the tests and checks if the parsed values have
403 the correct showname/season number/episode number.
1d643ad5 » dbr 2008-07-23 Made the regex-tests only r... 404 Runs from season 0 ep 0 to season 10, ep 10.
7fe0c000 » dbr 2008-07-23 Added more name formats to ... 405 """
1d643ad5 » dbr 2008-07-23 Made the regex-tests only r... 406 for seas in xrange(1, 11):
407 for ep in xrange(1, 11):
7fe0c000 » dbr 2008-07-23 Added more name formats to ... 408 name_data['seasno'] = seas
409 name_data['epno'] = ep
410
411 names = [x % name_data for x in self.name_formats]
412
413 proced = processNames(names, self.verbose)
414 self.assertEquals(len(names), len(proced))
415
416 for c in proced:
417 try:
418 self.assertEquals( c['epno'], name_data['epno'])
419 self.assertEquals( c['seasno'], name_data['seasno'] )
420 self.assertEquals( c['file_showname'], name_data['showname'] )
421 except AssertionError, errormsg:
422 # Show output of regex match in traceback (instead of "0 != 10")
423 new_errormsg = str(c) + "\n" + str(errormsg)
424 raise AssertionError, new_errormsg
425 #end for c in proced
426 #end for ep
427 #end for seas
428 #end run_test
353dff7b » dbr 2008-07-23 Renamed name parser unittes... 429 #end test_name_parser
5708b2b9 » dbr 2008-05-15 Numerous fixes to filename ... 430
e01ec1b6 » dbr 2008-05-07 Added (semi-)automated TV e... 431 if __name__ == "__main__":
432 main()