dbr / tvdb_api
- Source
- Commits
- Network (4)
- Issues (3)
- Downloads (14)
- Wiki (1)
- Graphs
-
Tree:
8c6f4e3
tvdb_api / tvnamer.py
| e01ec1b6 » | dbr | 2008-05-07 | 1 | #!/usr/bin/env python | |
| 2 | #encoding:utf-8 | ||||
| edc2372d » | dbr | 2008-06-22 | 3 | #author:dbr/Ben | |
| 4 | #project:tvdb_api | ||||
| 5 | #repository:http://github.com/dbr/tvdb_api | ||||
| 70ed746b » | dbr | 2008-07-22 | 6 | #license:Creative Commons GNU GPL v2 | |
| 7 | # (http://creativecommons.org/licenses/GPL/2.0/) | ||||
| e01ec1b6 » | dbr | 2008-05-07 | 8 | ||
| b366cfe4 » | dbr | 2008-07-21 | 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 | 15 | __author__ = "dbr/Ben" | |
| a6a1addf » | dbr | 2008-07-24 | 16 | __version__ = "0.3" | |
| e01ec1b6 » | dbr | 2008-05-07 | 17 | ||
| b366cfe4 » | dbr | 2008-07-21 | 18 | import os, sys, re | |
| e01ec1b6 » | dbr | 2008-05-07 | 19 | from optparse import OptionParser | |
| d1377c02 » | dbr | 2008-06-09 | 20 | ||
| d8af8a37 » | dbr | 2008-07-23 | 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 | 23 | from tvdb_api import Tvdb | |
| e01ec1b6 » | dbr | 2008-05-07 | 24 | ||
| fe3a957f » | dbr | 2008-07-23 | 25 | config = {} | |
| e01ec1b6 » | dbr | 2008-05-07 | 26 | ||
| d1377c02 » | dbr | 2008-06-09 | 27 | # The format of the renamed files (with and without episode names) | |
| e01ec1b6 » | dbr | 2008-05-07 | 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 | 31 | config['valid_filename_chars'] = """0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!@£$%^&*()_+=-[]{}"'.,<>`~? """ | |
| 45262d4f » | dbr | 2008-07-23 | 32 | config['valid_filename_chars_regex'] = re.escape(config['valid_filename_chars']) | |
| d1377c02 » | dbr | 2008-06-09 | 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 | 36 | config['name_parse'] = [ | |
| 1041e82c » | Doris | 2008-07-22 | 37 | # foo_[s01]_[e01] | |
| 45262d4f » | dbr | 2008-07-23 | 38 | re.compile('''^([%s]+?)[ \._\-]\[[Ss]([0-9]+?)\]_\[[Ee]([0-9]+?)\]?[^\\/]*$'''% (config['valid_filename_chars_regex'])), | |
| 1041e82c » | Doris | 2008-07-22 | 39 | # foo.1x09* | |
| 45262d4f » | dbr | 2008-07-23 | 40 | re.compile('''^([%s]+?)[ \._\-]\[?([0-9]+)x([0-9]+)[^\\/]*$''' % (config['valid_filename_chars_regex'])), | |
| 1041e82c » | Doris | 2008-07-22 | 41 | # foo.s01.e01, foo.s01_e01 | |
| 8c6f4e35 » | dbr | 2008-08-12 | 42 | re.compile('''^([%s]+?)[ \._\-][Ss]([0-9]+)[\.\- ]?[Ee]([0-9]+)[^\\/]*$''' % (config['valid_filename_chars_regex'])), | |
| 30d96e16 » | dbr | 2008-07-23 | 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 | 47 | ] | |
| 48 | |||||
| 49 | |||||
| 50 | def findFiles(args): | ||||
| d1377c02 » | dbr | 2008-06-09 | 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 | 55 | allfiles = [] | |
| b366cfe4 » | dbr | 2008-07-21 | 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 | 60 | if os.path.isfile(newpath): | |
| 61 | allfiles.append(newpath) | ||||
| 62 | #end if isfile | ||||
| 63 | #end for sf | ||||
| b366cfe4 » | dbr | 2008-07-21 | 64 | elif os.path.isfile(cfile): | |
| 65 | allfiles.append(cfile) | ||||
| e01ec1b6 » | dbr | 2008-05-07 | 66 | #end if isdir | |
| b366cfe4 » | dbr | 2008-07-21 | 67 | #end for cfile | |
| e01ec1b6 » | dbr | 2008-05-07 | 68 | return allfiles | |
| 69 | #end findFiles | ||||
| 70 | |||||
| b366cfe4 » | dbr | 2008-07-21 | 71 | def processNames(names, verbose=False): | |
| d1377c02 » | dbr | 2008-06-09 | 72 | """ | |
| 73 | Takes list of names, runs them though the config['name_parse'] regexs | ||||
| 74 | """ | ||||
| fe3a957f » | dbr | 2008-07-23 | 75 | allEps = [] | |
| e01ec1b6 » | dbr | 2008-05-07 | 76 | for f in names: | |
| b366cfe4 » | dbr | 2008-07-21 | 77 | filepath, filename = os.path.split( f ) | |
| 78 | filename, ext = os.path.splitext( filename ) | ||||
| 2c312811 » | dbr | 2008-07-24 | 79 | ||
| 4c9c9fee » | dbr | 2008-07-24 | 80 | # Remove leading . from extension | |
| 81 | ext = ext.replace(".", "", 1) | ||||
| 2c312811 » | dbr | 2008-07-24 | 82 | ||
| e01ec1b6 » | dbr | 2008-05-07 | 83 | for r in config['name_parse']: | |
| 84 | match = r.match(filename) | ||||
| 85 | if match: | ||||
| b366cfe4 » | dbr | 2008-07-21 | 86 | showname, seasno, epno = match.groups() | |
| 2c312811 » | dbr | 2008-07-24 | 87 | ||
| 1041e82c » | Doris | 2008-07-22 | 88 | #remove ._- characters from name (- removed only if next to end of line) | |
| 2c312811 » | dbr | 2008-07-24 | 89 | showname = re.sub("[\._]|\-(?=$)", " ", showname).strip() | |
| 90 | |||||
| b366cfe4 » | dbr | 2008-07-21 | 91 | seasno, epno = int(seasno), int(epno) | |
| acf8d117 » | dbr | 2008-06-22 | 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 | 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 | 108 | }) | |
| 2c312811 » | dbr | 2008-07-24 | 109 | break # Matched - to the next file! | |
| e01ec1b6 » | dbr | 2008-05-07 | 110 | else: | |
| eb2536e7 » | dbr | 2008-07-23 | 111 | print "Invalid name: %s" % (f) | |
| e01ec1b6 » | dbr | 2008-05-07 | 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 | 119 | """ | |
| 120 | Takes a file dict and renames files using the configured format | ||||
| 121 | """ | ||||
| e01ec1b6 » | dbr | 2008-05-07 | 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 | 131 | """ | |
| 132 | Cleans the supplied filename for renaming-to | ||||
| 133 | """ | ||||
| b366cfe4 » | dbr | 2008-07-21 | 134 | name = name.encode('ascii', 'ignore') # convert unicode to ASCII | |
| 2b13c73f » | dbr | 2008-05-15 | 135 | ||
| e01ec1b6 » | dbr | 2008-05-07 | 136 | return ''.join( [c for c in name if c in config['valid_filename_chars']] ) | |
| d1377c02 » | dbr | 2008-06-09 | 137 | #end cleanName | |
| e01ec1b6 » | dbr | 2008-05-07 | 138 | ||
| b366cfe4 » | dbr | 2008-07-21 | 139 | def renameFile(oldfile, newfile, force=False): | |
| d1377c02 » | dbr | 2008-06-09 | 140 | """ | |
| 141 | Renames files, does not overwrite files unless forced | ||||
| 142 | """ | ||||
| b366cfe4 » | dbr | 2008-07-21 | 143 | new_exists = os.access(newfile, os.F_OK) | |
| e01ec1b6 » | dbr | 2008-05-07 | 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 | 148 | os.rename(oldfile, newfile) | |
| e01ec1b6 » | dbr | 2008-05-07 | 149 | else: | |
| 150 | sys.stderr.write("skipping\n") | ||||
| 151 | return False | ||||
| 152 | #end if force | ||||
| 153 | else: | ||||
| b366cfe4 » | dbr | 2008-07-21 | 154 | os.rename(oldfile, newfile) | |
| e01ec1b6 » | dbr | 2008-05-07 | 155 | return True | |
| 156 | #end if new_exists | ||||
| 157 | |||||
| 158 | |||||
| 159 | def main(): | ||||
| 9581e2c8 » | dbr | 2008-05-09 | 160 | parser = OptionParser(usage="%prog [options] <file or directories>") | |
| e01ec1b6 » | dbr | 2008-05-07 | 161 | ||
| b366cfe4 » | dbr | 2008-07-21 | 162 | parser.add_option( "-d", "--debug", action="store_true", default=False, dest="debug", | |
| 9581e2c8 » | dbr | 2008-05-09 | 163 | help="show debugging info") | |
| b366cfe4 » | dbr | 2008-07-21 | 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 | 167 | help="interactivly select correct show from search results [default]") | |
| b366cfe4 » | dbr | 2008-07-21 | 168 | parser.add_option( "-a", "--always", action="store_true", default=False, dest="always", | |
| 9581e2c8 » | dbr | 2008-05-09 | 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 | 170 | parser.add_option( "-f", "--force", action="store_true", default=False, dest="force", | |
| 9581e2c8 » | dbr | 2008-05-09 | 171 | help="forces file to be renamed, even if it will overwrite an existing file") | |
| b366cfe4 » | dbr | 2008-07-21 | 172 | parser.add_option( "-t", "--tests", action="store_true", default=False, dest="dotests", | |
| a5b8a318 » | dbr | 2008-05-15 | 173 | help="Run unittests (mostly useful for development)") | |
| e01ec1b6 » | dbr | 2008-05-07 | 174 | ||
| b366cfe4 » | dbr | 2008-07-21 | 175 | opts, args = parser.parse_args() | |
| a5b8a318 » | dbr | 2008-05-15 | 176 | ||
| b0d7364e » | dbr | 2008-05-15 | 177 | if opts.dotests: | |
| 353dff7b » | dbr | 2008-07-23 | 178 | suite = unittest.TestLoader().loadTestsFromTestCase(test_name_parser) | |
| b0d7364e » | dbr | 2008-05-15 | 179 | unittest.TextTestRunner(verbosity=2).run(suite) | |
| 180 | sys.exit(0) | ||||
| 181 | #end if dotests | ||||
| 182 | |||||
| e01ec1b6 » | dbr | 2008-05-07 | 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 | 188 | validFiles = processNames(allFiles, verbose = opts.debug) | |
| e01ec1b6 » | dbr | 2008-05-07 | 189 | ||
| 190 | if len(validFiles) == 0: | ||||
| db9c02a0 » | dbr | 2008-05-07 | 191 | sys.stderr.write("No valid files found\n") | |
| 1883717e » | dbr | 2008-07-24 | 192 | sys.exit(2) | |
| e01ec1b6 » | dbr | 2008-05-07 | 193 | ||
| 9581e2c8 » | dbr | 2008-05-09 | 194 | print "#"*20 | |
| 195 | print "# Starting tvnamer" | ||||
| 196 | print "# Processing %d files" % ( len(validFiles) ) | ||||
| 197 | |||||
| 472a73d4 » | dbr | 2008-07-21 | 198 | t = Tvdb(debug = opts.debug, interactive = opts.interactive) | |
| 9581e2c8 » | dbr | 2008-05-09 | 199 | ||
| 200 | print "# ..got tvdb mirrors" | ||||
| 201 | print "# Starting to process files" | ||||
| df6389fc » | dbr | 2008-06-09 | 202 | print "#"*20 | |
| 9581e2c8 » | dbr | 2008-05-09 | 203 | ||
| e01ec1b6 » | dbr | 2008-05-07 | 204 | for cfile in validFiles: | |
| 4f8a41a6 » | dbr | 2008-06-24 | 205 | print "# Processing %(file_showname)s (season: %(seasno)d, episode %(epno)d)" % (cfile) | |
| 77c548eb » | dbr | 2008-05-15 | 206 | try: | |
| 4f8a41a6 » | dbr | 2008-06-24 | 207 | # Ask for episode name from tvdb_api | |
| a1a532ea » | dbr | 2008-08-03 | 208 | epname = t[ cfile['file_showname'] ][ cfile['seasno'] ][ cfile['epno'] ]['episodename'] | |
| 5261f621 » | dbr | 2008-07-23 | 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 | 218 | cfile['epname'] = None | |
| 5261f621 » | dbr | 2008-07-23 | 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 | 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 | 226 | ||
| 227 | cfile['showname'] = t[ cfile['file_showname'] ]['showname'] | ||||
| 228 | cfile['epname'] = None | ||||
| 74e11400 » | dbr | 2008-08-07 | 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 | 238 | # User aborted selection (q or ^c) | |
| 239 | print "\n", errormsg | ||||
| eb2536e7 » | dbr | 2008-07-23 | 240 | sys.exit(1) | |
| 77c548eb » | dbr | 2008-05-15 | 241 | else: | |
| 5261f621 » | dbr | 2008-07-23 | 242 | cfile['epname'] = epname | |
| 243 | cfile['showname'] = t[ cfile['file_showname'] ]['showname'] # get the corrected showname | ||||
| 77c548eb » | dbr | 2008-05-15 | 244 | ||
| 9581e2c8 » | dbr | 2008-05-09 | 245 | # Format new filename, strip unwanted characters | |
| 3f3eeabb » | dbr | 2008-06-24 | 246 | newname = formatName(cfile) | |
| e01ec1b6 » | dbr | 2008-05-07 | 247 | newname = cleanName(newname) | |
| 9581e2c8 » | dbr | 2008-05-09 | 248 | ||
| 249 | # Append new filename (with extension) to path | ||||
| 250 | oldfile = os.path.join( | ||||
| 251 | cfile['filepath'], | ||||
| 38bfb31a » | Doris | 2008-07-23 | 252 | cfile['filename'] + "." + cfile['ext'] | |
| 9581e2c8 » | dbr | 2008-05-09 | 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 | 262 | print "Old name: %s" % ( cfile['filename'] + "." + cfile['ext'] ) | |
| e01ec1b6 » | dbr | 2008-05-07 | 263 | print "New name: %s" % ( newname ) | |
| 264 | |||||
| 9581e2c8 » | dbr | 2008-05-09 | 265 | # Either always rename, or prompt user | |
| 29fdfbb9 » | dbr | 2008-06-09 | 266 | if opts.always or (not opts.interactive): | |
| b366cfe4 » | dbr | 2008-07-21 | 267 | rename_result = renameFile(oldfile, newfile, force=opts.force) | |
| e01ec1b6 » | dbr | 2008-05-07 | 268 | if rename_result: | |
| 269 | print "..auto-renaming" | ||||
| 270 | else: | ||||
| 271 | print "..not renamed" | ||||
| 4f8a41a6 » | dbr | 2008-06-24 | 272 | #end if rename_result | |
| 273 | |||||
| e01ec1b6 » | dbr | 2008-05-07 | 274 | continue # next filename! | |
| 275 | #end if always | ||||
| 276 | |||||
| e731b73a » | dbr | 2008-07-23 | 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 | 284 | print "\n", errormsg | |
| 285 | sys.exit(1) | ||||
| e731b73a » | dbr | 2008-07-23 | 286 | #end try | |
| 287 | #end while | ||||
| 4f8a41a6 » | dbr | 2008-06-24 | 288 | ||
| 289 | if len(ans) == 0: | ||||
| 290 | print "Renaming (default)" | ||||
| b366cfe4 » | dbr | 2008-07-21 | 291 | rename_result = renameFile(oldfile, newfile, force=opts.force) | |
| 4f8a41a6 » | dbr | 2008-06-24 | 292 | elif ans[0] == "a": | |
| fe3a957f » | dbr | 2008-07-23 | 293 | opts.always = True | |
| b366cfe4 » | dbr | 2008-07-21 | 294 | rename_result = renameFile(oldfile, newfile, force=opts.force) | |
| e01ec1b6 » | dbr | 2008-05-07 | 295 | elif ans[0] == "q": | |
| 296 | print "Aborting" | ||||
| 1883717e » | dbr | 2008-07-24 | 297 | sys.exit(1) | |
| e01ec1b6 » | dbr | 2008-05-07 | 298 | elif ans[0] == "y": | |
| b366cfe4 » | dbr | 2008-07-21 | 299 | rename_result = renameFile(oldfile, newfile, force=opts.force) | |
| e01ec1b6 » | dbr | 2008-05-07 | 300 | elif ans[0] == "n": | |
| 301 | print "Skipping" | ||||
| 302 | continue | ||||
| d1377c02 » | dbr | 2008-06-09 | 303 | else: | |
| 4f8a41a6 » | dbr | 2008-06-24 | 304 | print "Invalid input, skipping" | |
| e01ec1b6 » | dbr | 2008-05-07 | 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 | 312 | print "# Done" | |
| e01ec1b6 » | dbr | 2008-05-07 | 313 | #end main | |
| 314 | |||||
| 5708b2b9 » | dbr | 2008-05-15 | 315 | import unittest | |
| 353dff7b » | dbr | 2008-07-23 | 316 | class test_name_parser(unittest.TestCase): | |
| b5fea24f » | dbr | 2008-06-22 | 317 | def setUp(self): | |
| eb2536e7 » | dbr | 2008-07-23 | 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 | 328 | # Shows verbose regex matching information | |
| b5fea24f » | dbr | 2008-06-22 | 329 | self.verbose = False | |
| 330 | |||||
| 1041e82c » | Doris | 2008-07-22 | 331 | #scene naming standards: http://tvunderground.org.ru/forum/index.php?showtopic=8488 | |
| b5fea24f » | dbr | 2008-06-22 | 332 | self.name_formats = [ | |
| 7fe0c000 » | dbr | 2008-07-23 | 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 | 351 | ] | |
| b5fea24f » | dbr | 2008-06-22 | 352 | ||
| 7fe0c000 » | dbr | 2008-07-23 | 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 | 358 | ||
| 7fe0c000 » | dbr | 2008-07-23 | 359 | self._run_test(name_data) | |
| b5fea24f » | dbr | 2008-06-22 | 360 | #end test_name_parser | |
| 361 | |||||
| 362 | def test_name_parser_showdashname(self): | ||||
| 7fe0c000 » | dbr | 2008-07-23 | 363 | """ | |
| 364 | Tests with dash in showname | ||||
| 365 | """ | ||||
| 366 | name_data = {'showname':'S-how name'} | ||||
| b5fea24f » | dbr | 2008-06-22 | 367 | ||
| 7fe0c000 » | dbr | 2008-07-23 | 368 | self._run_test(name_data) | |
| b5fea24f » | dbr | 2008-06-22 | 369 | #end test_name_parser_showdashname | |
| 370 | |||||
| 371 | def test_name_parser_shownumeric(self): | ||||
| 30d96e16 » | dbr | 2008-07-23 | 372 | """ | |
| 373 | Tests with numeric show name | ||||
| 374 | """ | ||||
| 7fe0c000 » | dbr | 2008-07-23 | 375 | name_data = {'showname':'123'} | |
| b5fea24f » | dbr | 2008-06-22 | 376 | ||
| 7fe0c000 » | dbr | 2008-07-23 | 377 | self._run_test(name_data) | |
| b5fea24f » | dbr | 2008-06-22 | 378 | #end test_name_parser_shownumeric | |
| 7fe0c000 » | dbr | 2008-07-23 | 379 | ||
| 30d96e16 » | dbr | 2008-07-23 | 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 | 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 | 404 | Runs from season 0 ep 0 to season 10, ep 10. | |
| 7fe0c000 » | dbr | 2008-07-23 | 405 | """ | |
| 1d643ad5 » | dbr | 2008-07-23 | 406 | for seas in xrange(1, 11): | |
| 407 | for ep in xrange(1, 11): | ||||
| 7fe0c000 » | dbr | 2008-07-23 | 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 | 429 | #end test_name_parser | |
| 5708b2b9 » | dbr | 2008-05-15 | 430 | ||
| e01ec1b6 » | dbr | 2008-05-07 | 431 | if __name__ == "__main__": | |
| 432 | main() | ||||
