def doMoveFile(cnamer, destDir=None, destFilepath=None, getPathPreview=False): """Moves file to destDir, or to destFilepath """ if (destDir is None and destFilepath is None) or (destDir is not None and destFilepath is not None): raise ValueError("Specify only destDir or destFilepath") if not Config['move_files_enable']: raise ValueError( "move_files feature is disabled but doMoveFile was called") if Config['move_files_destination'] is None: raise ValueError( "Config value for move_files_destination cannot be None if move_files_enabled is True" ) try: return cnamer.newPath(new_path=destDir, new_fullpath=destFilepath, always_move=Config['always_move'], leave_symlink=Config['leave_symlink'], getPathPreview=getPathPreview, force=Config['overwrite_destination_on_move']) except OSError as e: if Config['skip_behaviour'] == 'exit': warn("Exiting due to error: %s" % e) raise SkipBehaviourAbort() warn("Skipping file due to error: %s" % e)
def doMoveFile(cnamer, destDir = None, destFilepath = None, getPathPreview = False): """Moves file to destDir, or to destFilepath """ if (destDir is None and destFilepath is None) or (destDir is not None and destFilepath is not None): raise ValueError("Specify only destDir or destFilepath") if not Config['move_files_enable']: raise ValueError("move_files feature is disabled but doMoveFile was called") if Config['move_files_destination'] is None: raise ValueError("Config value for move_files_destination cannot be None if move_files_enabled is True") try: return cnamer.newPath( new_path = destDir, new_fullpath = destFilepath, always_move = Config['always_move'], leave_symlink = Config['leave_symlink'], getPathPreview = getPathPreview, force = Config['overwrite_destination_on_move']) except OSError as e: if Config['skip_behaviour'] == 'exit': warn("Exiting due to error: %s" % e) raise SkipBehaviourAbort() warn("Skipping file due to error: %s" % e)
def tvnamer(paths): """Main tvnamer function, takes an array of paths, does stuff. """ p("#" * 20) p("# Starting tvnamer") episodes_found = [] for cfile in findFiles(paths): parser = FileParser(cfile) try: episode = parser.parse() except InvalidFilename as e: warn("Invalid filename: %s" % e) else: if episode.seriesname is None and Config['force_name'] is None and Config['series_id'] is None: warn("Parsed filename did not contain series name (and --name or --series-id not specified), skipping: %s" % cfile) else: episodes_found.append(episode) if len(episodes_found) == 0: raise NoValidFilesFoundError() p("# Found %d episode" % len(episodes_found) + ("s" * (len(episodes_found) > 1))) # Sort episodes by series name, season and episode number episodes_found.sort(key = lambda x: x.sortable_info()) # episode sort order if Config['order'] == 'dvd': dvdorder = True else: dvdorder = False if not PY2 and os.getenv("TRAVIS", "false") == "true": # Disable caching on Travis-CI because in Python 3 it errors with: # # Can't pickle <class 'http.cookiejar.DefaultCookiePolicy'>: it's not the same object as http.cookiejar.DefaultCookiePolicy cache = False else: cache = True tvdb_instance = Tvdb( interactive = not Config['select_first'], search_all_languages = Config['search_all_languages'], language = Config['language'], dvdorder = dvdorder, cache=cache, apikey=TVNAMER_API_KEY, ) for episode in episodes_found: processFile(tvdb_instance, episode) p('') p("#" * 20) p("# Done")
def doRenameFile(cnamer, newName): """Renames the file. cnamer should be Renamer instance, newName should be string containing new filename. """ try: cnamer.newPath(new_fullpath = newName, force = Config['overwrite_destination_on_rename'], leave_symlink = Config['leave_symlink']) except OSError as e: warn(e)
def tvnamer(paths): """Main tvnamer function, takes an array of paths, does stuff. """ p("#" * 20) p("# Starting tvnamer") episodes_found = [] for cfile in findFiles(paths): parser = FileParser(cfile) try: episode = parser.parse() except InvalidFilename as e: warn("Invalid filename: %s" % e) else: if episode.seriesname is None and Config['force_name'] is None and Config['series_id'] is None: warn("Parsed filename did not contain series name (and --name or --series-id not specified), skipping: %s" % cfile) else: episodes_found.append(episode) if len(episodes_found) == 0: raise NoValidFilesFoundError() p("# Found %d episode" % len(episodes_found) + ("s" * (len(episodes_found) > 1))) # Sort episodes by series name, season and episode number episodes_found.sort(key = lambda x: x.sortable_info()) # episode sort order if Config['order'] == 'dvd': dvdorder = True else: dvdorder = False if not PY2 and os.getenv("TRAVIS", "false") == "true": # Disable caching on Travis-CI because in Python 3 it errors with: # # Can't pickle <class 'http.cookiejar.DefaultCookiePolicy'>: it's not the same object as http.cookiejar.DefaultCookiePolicy cache = False else: cache = True tvdb_instance = Tvdb( interactive = not Config['select_first'], search_all_languages = Config['search_all_languages'], language = Config['language'], dvdorder = dvdorder, cache=cache, ) for episode in episodes_found: processFile(tvdb_instance, episode) p('') p("#" * 20) p("# Done")
def doRenameFile(cnamer, newName): """Renames the file. cnamer should be Renamer instance, newName should be string containing new filename. """ try: cnamer.newPath(new_fullpath=newName, force=Config['overwrite_destination_on_rename'], leave_symlink=Config['leave_symlink']) except OSError as e: warn(e)
def doRenameFile(cnamer, newName): """Renames the file. cnamer should be Renamer instance, newName should be string containing new filename. """ try: cnamer.newPath(new_fullpath = newName, force = Config['overwrite_destination_on_rename'], leave_symlink = Config['leave_symlink']) except OSError as e: if Config['skip_behaviour'] == 'exit': warn("Exiting due to error: %s" % e) raise SkipBehaviourAbort() warn("Skipping file due to error: %s" % e)
def findFiles(paths): """Takes an array of paths, returns all files found """ valid_files = [] for cfile in paths: cur = FileFinder(cfile, with_extension=Config['valid_extensions'], filename_blacklist=Config["filename_blacklist"], recursive=Config['recursive']) try: valid_files.extend(cur.findFiles()) except InvalidPath: warn("Invalid path: %s" % cfile) if len(valid_files) == 0: raise NoValidFilesFoundError() # Remove duplicate files (all paths from FileFinder are absolute) valid_files = list(set(valid_files)) return valid_files
def findFiles(paths): """Takes an array of paths, returns all files found """ valid_files = [] for cfile in paths: cur = FileFinder( cfile, with_extension = Config['valid_extensions'], filename_blacklist = Config["filename_blacklist"], recursive = Config['recursive']) try: valid_files.extend(cur.findFiles()) except InvalidPath: warn("Invalid path: %s" % cfile) if len(valid_files) == 0: raise NoValidFilesFoundError() # Remove duplicate files (all paths from FileFinder are absolute) valid_files = list(set(valid_files)) return valid_files
def processFile(tvdb_instance, episode): """Gets episode name, prompts user for input """ p("#" * 20) p("# Processing file: %s" % episode.fullfilename) if len(Config['input_filename_replacements']) > 0: replaced = applyCustomInputReplacements(episode.fullfilename) p("# With custom replacements: %s" % (replaced)) # Use force_name option. Done after input_filename_replacements so # it can be used to skip the replacements easily if Config['force_name'] is not None: episode.seriesname = Config['force_name'] p("# Detected series: %s (%s)" % (episode.seriesname, episode.number_string())) try: episode.populateFromTvdb(tvdb_instance, force_name=Config['force_name'], series_id=Config['series_id']) except (DataRetrievalError, ShowNotFound) as errormsg: if Config['always_rename'] and Config['skip_file_on_error'] is True: if Config['skip_behaviour'] == 'exit': warn("Exiting due to error: %s" % errormsg) raise SkipBehaviourAbort() warn("Skipping file due to error: %s" % errormsg) return else: warn(errormsg) except (SeasonNotFound, EpisodeNotFound, EpisodeNameNotFound) as errormsg: # Show was found, so use corrected series name if Config['always_rename'] and Config['skip_file_on_error']: if Config['skip_behaviour'] == 'exit': warn("Exiting due to error: %s" % errormsg) raise SkipBehaviourAbort() warn("Skipping file due to error: %s" % errormsg) return warn(errormsg) cnamer = Renamer(episode.fullpath) shouldRename = False if Config["move_files_only"]: newName = episode.fullfilename shouldRename = True else: newName = episode.generateFilename() if newName == episode.fullfilename: p("#" * 20) p("Existing filename is correct: %s" % episode.fullfilename) p("#" * 20) shouldRename = True else: p("#" * 20) p("Old filename: %s" % episode.fullfilename) if len(Config['output_filename_replacements']) > 0: # Show filename without replacements p("Before custom output replacements: %s" % (episode.generateFilename(preview_orig_filename=False))) p("New filename: %s" % newName) if Config['always_rename']: doRenameFile(cnamer, newName) if Config['move_files_enable']: if Config['move_files_destination_is_filepath']: doMoveFile(cnamer=cnamer, destFilepath=getMoveDestination(episode)) else: doMoveFile(cnamer=cnamer, destDir=getMoveDestination(episode)) return elif Config['dry_run']: p("%s will be renamed to %s" % (episode.fullfilename, newName)) if Config['move_files_enable']: p("%s will be moved to %s" % (newName, getMoveDestination(episode))) return ans = confirm("Rename?", options=['y', 'n', 'a', 'q'], default='y') if ans == "a": p("Always renaming") Config['always_rename'] = True shouldRename = True elif ans == "q": p("Quitting") raise UserAbort("User exited with q") elif ans == "y": p("Renaming") shouldRename = True elif ans == "n": p("Skipping") else: p("Invalid input, skipping") if shouldRename: doRenameFile(cnamer, newName) if shouldRename and Config['move_files_enable']: newPath = getMoveDestination(episode) if Config['dry_run']: p("%s will be moved to %s" % (newName, getMoveDestination(episode))) return if Config['move_files_destination_is_filepath']: doMoveFile(cnamer=cnamer, destFilepath=newPath, getPathPreview=True) else: doMoveFile(cnamer=cnamer, destDir=newPath, getPathPreview=True) if not Config['batch'] and Config['move_files_confirmation']: ans = confirm("Move file?", options=['y', 'n', 'q'], default='y') else: ans = 'y' if ans == 'y': p("Moving file") doMoveFile(cnamer, newPath) elif ans == 'q': p("Quitting") raise UserAbort("user exited with q")
def processFile(tvdb_instance, episode): """Gets episode name, prompts user for input """ p("#" * 20) p("# Processing file: %s" % episode.fullfilename) if len(Config['input_filename_replacements']) > 0: replaced = applyCustomInputReplacements(episode.fullfilename) p("# With custom replacements: %s" % (replaced)) # Use force_name option. Done after input_filename_replacements so # it can be used to skip the replacements easily if Config['force_name'] is not None: episode.seriesname = Config['force_name'] p("# Detected series: %s (%s)" % (episode.seriesname, episode.number_string())) try: episode.populateFromTvdb(tvdb_instance, force_name=Config['force_name'], series_id=Config['series_id']) except (DataRetrievalError, ShowNotFound) as errormsg: if Config['always_rename'] and Config['skip_file_on_error'] is True: if Config['skip_behaviour'] == 'exit': warn("Exiting due to error: %s" % errormsg) raise SkipBehaviourAbort() warn("Skipping file due to error: %s" % errormsg) return else: warn(errormsg) except (SeasonNotFound, EpisodeNotFound, EpisodeNameNotFound) as errormsg: # Show was found, so use corrected series name if Config['always_rename'] and Config['skip_file_on_error']: if Config['skip_behaviour'] == 'exit': warn("Exiting due to error: %s" % errormsg) raise SkipBehaviourAbort() warn("Skipping file due to error: %s" % errormsg) return warn(errormsg) cnamer = Renamer(episode.fullpath) shouldRename = False if Config["move_files_only"]: newName = episode.fullfilename shouldRename = True else: newName = episode.generateFilename() if newName == episode.fullfilename: p("#" * 20) p("Existing filename is correct: %s" % episode.fullfilename) p("#" * 20) shouldRename = True else: p("#" * 20) p("Old filename: %s" % episode.fullfilename) if len(Config['output_filename_replacements']) > 0: # Show filename without replacements p("Before custom output replacements: %s" % (episode.generateFilename(preview_orig_filename = False))) p("New filename: %s" % newName) if Config['always_rename']: doRenameFile(cnamer, newName) if Config['move_files_enable']: if Config['move_files_destination_is_filepath']: doMoveFile(cnamer = cnamer, destFilepath = getMoveDestination(episode)) else: doMoveFile(cnamer = cnamer, destDir = getMoveDestination(episode)) return elif Config['dry_run']: p("%s will be renamed to %s" % (episode.fullfilename, newName)) if Config['move_files_enable']: p("%s will be moved to %s" % (newName, getMoveDestination(episode))) return ans = confirm("Rename?", options = ['y', 'n', 'a', 'q'], default = 'y') if ans == "a": p("Always renaming") Config['always_rename'] = True shouldRename = True elif ans == "q": p("Quitting") raise UserAbort("User exited with q") elif ans == "y": p("Renaming") shouldRename = True elif ans == "n": p("Skipping") else: p("Invalid input, skipping") if shouldRename: doRenameFile(cnamer, newName) if shouldRename and Config['move_files_enable']: newPath = getMoveDestination(episode) if Config['dry_run']: p("%s will be moved to %s" % (newName, getMoveDestination(episode))) return if Config['move_files_destination_is_filepath']: doMoveFile(cnamer = cnamer, destFilepath = newPath, getPathPreview = True) else: doMoveFile(cnamer = cnamer, destDir = newPath, getPathPreview = True) if not Config['batch'] and Config['move_files_confirmation']: ans = confirm("Move file?", options = ['y', 'n', 'q'], default = 'y') else: ans = 'y' if ans == 'y': p("Moving file") doMoveFile(cnamer, newPath) elif ans == 'q': p("Quitting") raise UserAbort("user exited with q")