Beispiel #1
0
def copy_file(old, new):
    """Copy 'old' file to 'new'.
    """
    p("Copying %s to %s" % (old, new))
    log().debug("Copying %r to %r" % (old, new))
    shutil.copyfile(old, new)
    shutil.copystat(old, new)
Beispiel #2
0
def tvnamer(paths):
    """Main tvnamer function, takes an array of paths, does stuff.
    """
    # Warn about move_files function
    if Config['move_files_enable']:
        import warnings
        warnings.warn("The move_files feature is still under development. "
            "Be very careful with it.\n"
            "It has not been heavily tested, and is not recommended for "
            "general use yet.")

    if Config['force_name'] is not None:
        import warnings
        warnings.warn("The --name argument is a temporary solution, and will"
            "be removed at some point in the future. Do no depend on it")

    p("#" * 20)
    p("# Starting tvnamer")

    episodes_found = []

    for cfile in findFiles(paths):
        parser = FileParser(cfile)
        try:
            episode = parser.parse()
        except InvalidFilename, e:
            warn("Invalid filename: %s" % e)
        else:
            if episode.seriesname is None:
                warn("Parsed filename did not contain series name, skipping: %s" % cfile)
            else:
                episodes_found.append(episode)
Beispiel #3
0
def rename_file(old, new):
    """Rename 'old' file to 'new'. Both files must be on the same partition.
    Preserves access and modification time.
    """
    p("Renaming %s to %s" % (old, new))
    log().debug("Renaming %r to %r" % (old, new))
    stat = os.stat(old)
    os.rename(old, new)
    os.utime(new, (stat.st_atime, stat.st_mtime))
Beispiel #4
0
def rename_file(old, new):
    p("rename %s to %s" % (old, new))
    stat = os.stat(old)
    os.rename(old, new)
    try:
        os.utime(new, (stat.st_atime, stat.st_mtime))
    except OSError, ex:
        if ex.errno == errno.EPERM:
            warn("WARNING: Could not preserve times for %s "
                 "(owner UID mismatch?)" % new)
        else:
            raise
Beispiel #5
0
def doMoveFile(cnamer, destDir):
    """Moves file to destDir"""
    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")

    p("New directory:", destDir)
    try:
        cnamer.newPath(destDir)
    except OSError, e:
        warn(unicode(e))
Beispiel #6
0
    def newPath(self, new_path = None, new_fullpath = None, force = False, always_copy = False, always_move = False, create_dirs = True, getPathPreview = False):
        """Moves the file to a new path.
        If it is on the same partition, it will be moved (unless always_copy is True)
        If it is on a different partition, it will be copied.
        If the target file already exists, it will raise OSError unless force is True.
        """
        old_fileinfo = self.filename
	p("self.filename: %s" % (self.filename))
	p("old_fileinfo: %s" % (old_fileinfo))

        if always_copy and always_move:
            raise ValueError("Both always_copy and always_move cannot be specified")

        if (new_path is None and new_fullpath is None) or (new_path is not None and new_fullpath is not None):
            raise ValueError("Specify only new_dir or new_fullpath")

        if new_path is not None:
            old_dir, old_filename = os.path.split(self.filename)

            # Join new filepath to old one (to handle realtive dirs)
            new_dir = os.path.abspath(os.path.join(old_dir, new_path))

            # Join new filename onto new filepath
            new_fullpath = os.path.join(new_dir, old_filename)

        else:
            old_dir, old_filename = os.path.split(self.filename)

            # Join new filepath to old one (to handle realtive dirs)
            new_fullpath = os.path.abspath(os.path.join(old_dir, new_fullpath))

            new_dir = os.path.dirname(new_fullpath)


        if len(Config['move_files_fullpath_replacements']) > 0:
            p("Before custom full path replacements: %s" % (new_fullpath))
            new_fullpath = applyCustomFullpathReplacements(new_fullpath)
            new_dir = os.path.dirname(new_fullpath)

        p("New path: %s" % new_fullpath)

        if getPathPreview:
            return new_fullpath

        if create_dirs:
            p("Creating directory %s" % new_dir)
            try:
                os.makedirs(new_dir)
            except OSError, e:
                if e.errno != 17:
                    raise
Beispiel #7
0
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), errormsg:
        if Config['always_rename'] and Config['skip_file_on_error'] is True:
            warn("Skipping file due to error: %s" % errormsg)
            return
        else:
            warn(errormsg)
Beispiel #8
0
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), errormsg:
        if Config['always_rename'] and Config['skip_file_on_error'] is True:
            warn("Skipping file due to error: %s" % errormsg)
            return
        else:
            warn(errormsg)
Beispiel #9
0
    def newName(self, newName, force = False):
        """Renames a file, keeping the path the same.
        """
        filepath, filename = os.path.split(self.filename)
        filename, _ = os.path.splitext(filename)
	global oldfileinfo
	oldfileinfo = self.filename
	p("self.filename: %s" % (self.filename))

        newpath = os.path.join(filepath, newName)

        if os.path.isfile(newpath):
            # If the destination exists, raise exception unless force is True
            if not force:
                raise OSError("File %s already exists, not forcefully renaming %s" % (
                    newpath, self.filename))

        os.rename(self.filename, newpath)
        self.filename = newpath
Beispiel #10
0
def delete_file(fpath):
    """On OS X: Trashes a path using the Finder, via OS X's Scripting Bridge.
    On other platforms: unlinks file.
    """

    try:
        from AppKit import NSURL
        from ScriptingBridge import SBApplication
    except ImportError:
        p("Deleting %s" % fpath)
        log().debug("Deleting %r" % fpath)
        os.unlink(fpath)
    else:
        p("Trashing %s" % fpath)
        log().debug("Trashing %r" % fpath)
        targetfile = NSURL.fileURLWithPath_(fpath)
        finder = SBApplication.applicationWithBundleIdentifier_("com.apple.Finder")
        items = finder.items().objectAtLocation_(targetfile)
        items.delete()
Beispiel #11
0
def main():
    """Parses command line arguments, displays errors from tvnamer in terminal
    """
    opter = cliarg_parser.getCommandlineParser(defaults)

    opts, args = opter.parse_args()

    args = [x.decode("utf-8") for x in args]

    if opts.verbose:
        logging.basicConfig(
            level=logging.DEBUG,
            format="%(asctime)s - %(name)s - %(levelname)s - %(message)s")
    else:
        logging.basicConfig()

    # If a config is specified, load it, update the defaults using the loaded
    # values, then reparse the options with the updated defaults.
    default_configuration = os.path.expanduser("~/.tvnamer.json")

    if opts.loadconfig is not None:
        # Command line overrides loading ~/.tvnamer.json
        configToLoad = opts.loadconfig
    elif os.path.isfile(default_configuration):
        # No --config arg, so load default config if it exists
        configToLoad = default_configuration
    else:
        # No arg, nothing at default config location, don't load anything
        configToLoad = None

    if configToLoad is not None:
        p("Loading config: %s" % (configToLoad))
        try:
            loadedConfig = json.load(open(configToLoad))
        except ValueError, e:
            p("Error loading config: %s" % e)
            opter.exit(1)
        else:
            # Config loaded, update optparser's defaults and reparse
            defaults.update(loadedConfig)
            opter = cliarg_parser.getCommandlineParser(defaults)
            opts, args = opter.parse_args()
Beispiel #12
0
def main():
    """Parses command line arguments, displays errors from tvnamer in terminal
    """
    opter = cliarg_parser.getCommandlineParser(defaults)

    opts, args = opter.parse_args()

    args = [x.decode("utf-8") for x in args]

    if opts.verbose:
        logging.basicConfig(
            level = logging.DEBUG,
            format = "%(asctime)s - %(name)s - %(levelname)s - %(message)s")
    else:
        logging.basicConfig()

    # If a config is specified, load it, update the defaults using the loaded
    # values, then reparse the options with the updated defaults.
    default_configuration = os.path.expanduser("~/.tvnamer.json")

    if opts.loadconfig is not None:
        # Command line overrides loading ~/.tvnamer.json
        configToLoad = opts.loadconfig
    elif os.path.isfile(default_configuration):
        # No --config arg, so load default config if it exists
        configToLoad = default_configuration
    else:
        # No arg, nothing at default config location, don't load anything
        configToLoad = None

    if configToLoad is not None:
        p("Loading config: %s" % (configToLoad))
        try:
            loadedConfig = json.load(open(configToLoad))
        except ValueError, e:
            p("Error loading config: %s" % e)
            opter.exit(1)
        else:
            # Config loaded, update optparser's defaults and reparse
            defaults.update(loadedConfig)
            opter = cliarg_parser.getCommandlineParser(defaults)
            opts, args = opter.parse_args()
Beispiel #13
0
    def newName(self, newName, force = False):
        """Renames a file, keeping the path the same.
        """
        filepath, filename = os.path.split(self.filename)
        filename, _ = os.path.splitext(filename)

        newpath = os.path.join(filepath, newName)

        if os.path.isfile(newpath):
            # If the destination exists, raise exception unless force is True
            if not force:
                raise OSError("File %s already exists, not forcefully renaming %s" % (
                    newpath, self.filename))

        if Config['link_files_enable']:
            p("Creating hard link")
            os.link(self.filename, newpath)
        else:
            os.rename(self.filename, newpath)
        self.filename = newpath
Beispiel #14
0
 def linkPath(self, new_path = None, new_fullpath = None, force = False, always_copy = False, always_move = False, create_dirs = True, getPathPreview = False):
     # Implement getPathPreview, just to respect the API
     if getPathPreview:
         return self.newPath(new_path, new_fullpath, force, always_copy, always_move, create_dirs, getPathPreview)
     
     # Grab the pathPreview from newPath to determine where we need to link to
     new_fullpath = self.newPath(new_path, new_fullpath, force, always_copy, always_move, create_dirs, True)
     new_dir = os.path.dirname(new_fullpath)
     # And then restore our faked filename, if one exists
     if self.srcFilename is not None:
         self.filename = self.srcFilename
         self.srcFilename = None
     
     if create_dirs:
         p("Creating directory %s" % new_dir)
         try:
             os.makedirs(new_dir)
         except OSError, e:
             if e.errno != 17:
                 raise
Beispiel #15
0
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, e:
            warn("Invalid filename: %s" % e)
        else:
            if episode.seriesname is None and Config['force_name'] is None:
                warn("Parsed filename did not contain series name (and --name not specified), skipping: %s" % cfile)
            else:
                episodes_found.append(episode)
Beispiel #16
0
    def rename(self, new_fullpath, force=False, always_copy=False, always_move=False, leave_symlink=False, create_dirs=True):
        """Moves the file to a new path.

        If it is on the same partition, it will be moved (unless always_copy is True)
        If it is on a different partition, it will be copied, and the original
        only deleted if always_move is True.
        If the target file already exists, it will raise OSError unless force is True.
        If it was moved, a symlink will be left behind with the original name
        pointing to the file's new destination if leave_symlink is True.
        """

        new_dir = os.path.dirname(new_fullpath)

        if create_dirs:
            p("Creating directory %s" % new_dir)
            try:
                os.makedirs(new_dir)
            except OSError, e:
                if e.errno != 17:
                    raise
Beispiel #17
0
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, 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)
Beispiel #18
0
    def newPath(self,
                new_path=None,
                new_fullpath=None,
                force=False,
                always_copy=False,
                always_move=False,
                leave_symlink=False,
                create_dirs=True,
                getPathPreview=False):
        """Moves the file to a new path.

        If it is on the same partition, it will be moved (unless always_copy is True)
        If it is on a different partition, it will be copied, and the original
        only deleted if always_move is True.
        If the target file already exists, it will raise OSError unless force is True.
        If it was moved, a symlink will be left behind with the original name
        pointing to the file's new destination if leave_symlink is True.
        """

        if always_copy and always_move:
            raise ValueError(
                "Both always_copy and always_move cannot be specified")

        if (new_path is None
                and new_fullpath is None) or (new_path is not None
                                              and new_fullpath is not None):
            raise ValueError("Specify only new_dir or new_fullpath")

        old_dir, old_filename = os.path.split(self.filename)
        if new_path is not None:
            # Join new filepath to old one (to handle realtive dirs)
            new_dir = os.path.abspath(os.path.join(old_dir, new_path))

            # Join new filename onto new filepath
            new_fullpath = os.path.join(new_dir, old_filename)

        else:
            # Join new filepath to old one (to handle realtive dirs)
            new_fullpath = os.path.abspath(os.path.join(old_dir, new_fullpath))

            new_dir = os.path.dirname(new_fullpath)

        if len(Config['move_files_fullpath_replacements']) > 0:
            p("Before custom full path replacements: %s" % (new_fullpath))
            new_fullpath = applyCustomFullpathReplacements(new_fullpath)
            new_dir = os.path.dirname(new_fullpath)

        p("New path: %s" % new_fullpath)

        if getPathPreview:
            return new_fullpath

        if create_dirs:
            try:
                os.makedirs(new_dir)
            except OSError, e:
                if e.errno != 17:
                    raise
            else:
                p("Created directory %s" % new_dir)
Beispiel #19
0
def confirm(question, options, default="y"):
    """Takes a question (string), list of options and a default value (used
    when user simply hits enter).
    Asks until valid option is entered.
    """
    # Highlight default option with [ ]
    options_str = []
    for x in options:
        if x == default:
            x = "[%s]" % x
        if x != '':
            options_str.append(x)
    options_str = "/".join(options_str)

    while True:
        p(question)
        p("(%s) " % (options_str), end="")
        try:
            ans = raw_input().strip()
        except KeyboardInterrupt, errormsg:
            p("\n", errormsg)
            raise UserAbort(errormsg)

        if ans in options:
            return ans
        elif ans == '':
            return default
Beispiel #20
0
def confirm(question, options, default = "y"):
    """Takes a question (string), list of options and a default value (used
    when user simply hits enter).
    Asks until valid option is entered.
    """
    # Highlight default option with [ ]
    options_str = []
    for x in options:
        if x == default:
            x = "[%s]" % x
        if x != '':
            options_str.append(x)
    options_str = "/".join(options_str)

    while True:
        p(question)
        p("(%s) " % (options_str), end="")
        try:
            ans = raw_input().strip()
        except KeyboardInterrupt, errormsg:
            p("\n", errormsg)
            raise UserAbort(errormsg)

        if ans in options:
            return ans
        elif ans == '':
            return default
Beispiel #21
0
    def newName(self, newName, force = False, leave_symlink = False):
        """Renames a file, keeping the path the same.
        """
        filepath, filename = os.path.split(self.filename)
        filename, _ = os.path.splitext(filename)

        newpath = os.path.join(filepath, newName)

        if os.path.isfile(newpath):
            # If the destination exists, raise exception unless force is True
            if not force:
                raise OSError("File %s already exists, not forcefully renaming %s" % (
                    newpath, self.filename))

        os.rename(self.filename, newpath)

        # Leave a symlink behind if configured to do so
        if leave_symlink:
            p("symlink %s to %s" % (self.filename, newpath))
            os.symlink(newpath, self.filename)

        self.filename = newpath
Beispiel #22
0
def tvnamer(paths):
    """Main tvnamer function, takes an array of paths, does stuff.
    """
    # Warn about move_files function
    if Config['move_files_enable']:
        import warnings
        warnings.warn(
            "The move_files feature is still under development. "
            "Be very careful with it.\n"
            "It has not been heavily tested, and is not recommended for "
            "general use yet.")

    if Config['force_name'] is not None:
        import warnings
        warnings.warn(
            "The --name argument is a temporary solution, and will"
            "be removed at some point in the future. Do no depend on it")

    p("#" * 20)
    p("# Starting tvnamer")

    episodes_found = []

    for cfile in findFiles(paths):
        parser = FileParser(cfile)
        try:
            episode = parser.parse()
        except InvalidFilename, e:
            warn("Invalid filename: %s" % e)
        else:
            if episode.seriesname is None:
                warn(
                    "Parsed filename did not contain series name, skipping: %s"
                    % cfile)
            else:
                episodes_found.append(episode)
Beispiel #23
0
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))

    p("# Detected series: %s (%s)" % (episode.seriesname, episode.number_string()))

    try:
        correctedSeriesName, epName = getEpisodeName(tvdb_instance, episode)
    except (DataRetrievalError, ShowNotFound), errormsg:
        if Config['always_rename'] and Config['skip_file_on_error'] is True:
            warn("Skipping file due to error: %s" % errormsg)
            return
        else:
            warn(errormsg)
Beispiel #24
0
def processFile(comicvine_instance, issue):
    """Gets issue name, prompts user for input
    """
    p("#" * 20)
    p("# Processing file: %s" % issue.fullfilename)

    if len(Config['input_filename_replacements']) > 0:
        replaced = applyCustomInputReplacements(issue.fullfilename)
        p("# With custom replacements: %s" % (replaced))

    p("# Detected series: %s (issue: %s)" %
      (issue.seriesname, ", ".join([str(x) for x in issue.issuenumbers])))

    try:
        correctedSeriesName, issName = getIssueName(comicvine_instance, issue)
    except (DataRetrievalError, SeriesNotFound), errormsg:
        if Config['always_rename'] and Config['skip_file_on_error'] is True:
            warn("Skipping file due to error: %s" % errormsg)
            return
        else:
            warn(errormsg)
Beispiel #25
0
def processFile(comicvine_instance, issue):
    """Gets issue name, prompts user for input
    """
    p("#" * 20)
    p("# Processing file: %s" % issue.fullfilename)

    if len(Config['input_filename_replacements']) > 0:
        replaced = applyCustomInputReplacements(issue.fullfilename)
        p("# With custom replacements: %s" % (replaced))

    p("# Detected volume: %s (issue: %s)" % (
        issue.volumename,
        ", ".join([str(x) for x in issue.issuenumbers])))

    try:
        correctedvolumeName, issName = getIssueName(comicvine_instance, issue)
    except (DataRetrievalError, volumeNotFound), errormsg:
        if Config['always_rename'] and Config['skip_file_on_error'] is True:
            warn("Skipping file due to error: %s" % errormsg)
            return
        else:
            warn(errormsg)
Beispiel #26
0
    def newPath(self,
                new_path,
                force=False,
                always_copy=False,
                always_move=False,
                create_dirs=True,
                getPathPreview=False):
        """Moves the file to a new path.

        If it is on the same partition, it will be moved (unless always_copy is True)
        If it is on a different partition, it will be copied.
        If the target file already exists, it will raise OSError unless force is True.
        """

        if always_copy and always_move:
            raise ValueError(
                "Both always_copy and always_move cannot be specified")

        old_dir, old_filename = os.path.split(self.filename)

        # Join new filepath to old one (to handle realtive dirs)
        new_dir = os.path.abspath(os.path.join(old_dir, new_path))

        # Join new filename onto new filepath
        new_fullpath = os.path.join(new_dir, old_filename)

        if len(Config['move_files_fullpath_replacements']) > 0:
            p("Before custom full path replacements: %s" % (new_fullpath))
            new_fullpath = applyCustomFullpathReplacements(new_fullpath)
            new_dir = os.path.dirname(new_fullpath)

        p("New path: %s" % new_fullpath)

        if getPathPreview:
            return new_fullpath

        if create_dirs:
            p("Creating %s" % new_dir)
            try:
                os.makedirs(new_dir)
            except OSError, e:
                if e.errno != 17:
                    raise
Beispiel #27
0
    def newPath(self, new_path, force = False, always_copy = False, always_move = False, create_dirs = True, getPathPreview = False):
        """Moves the file to a new path.

        If it is on the same partition, it will be moved (unless always_copy is True)
        If it is on a different partition, it will be copied.
        If the target file already exists, it will raise OSError unless force is True.
        """

        if always_copy and always_move:
            raise ValueError("Both always_copy and always_move cannot be specified")

        if Config["link_files_enable"] and always_copy:
            warn("WARNING: having link_files_enable and always_copy both True can lead to 3 copies of a file: the original, a hard link and a copy")

        old_dir, old_filename = os.path.split(self.filename)

        # Join new filepath to old one (to handle realtive dirs)
        new_dir = os.path.abspath(os.path.join(old_dir, new_path))

        # Join new filename onto new filepath
        new_fullpath = os.path.join(new_dir, old_filename)

        if len(Config['move_files_fullpath_replacements']) > 0:
            p("Before custom full path replacements: %s" % (new_fullpath))
            new_fullpath = applyCustomFullpathReplacements(new_fullpath)
            new_dir = os.path.dirname(new_fullpath)

        p("New path: %s" % new_fullpath)

        if getPathPreview:
            return new_fullpath

        if create_dirs:
            p("Creating %s" % new_dir)
            try:
                os.makedirs(new_dir)
            except OSError, e:
                if e.errno != 17:
                    raise
Beispiel #28
0
    def getNewFullPath(self):
        """ Generates final fullPath, with all replacements, formatting etc.
            It's ready to pass it to Renamer.rename().
        """

        epdata = self.getepdata()
        newName = self.getFormatString() % epdata

        if len(Config['output_filename_replacements']) > 0:
            p("Before custom output replacements: '%s'" % newName)
            newName = applyCustomOutputReplacements(newName)
            p("After custom output replacements:  '%s'" % newName)

        if self.eptype == 'dated':
            newPath = Config['move_files_destination_date'] % epdata
        else:
            newPath = Config['move_files_destination'] % epdata
        if Config['move_files_destination_is_filepath']:
            newPath, newName = os.path.split(newPath)

        # make newName lowercase if specified in config
        if Config['lowercase_filename']:
            newName = newName.lower()

        # make sure the filename is valid
        newName = makeValidFilename(newName)

        # Join new filepath to old one (to handle realtive dirs)
        oldPath = os.path.dirname(self.fullpath)
        newFullPath = os.path.abspath(os.path.join(oldPath, newPath, newName))

        # apply full-path replacements
        if len(Config['move_files_fullpath_replacements']) > 0:
            p("Before custom full path replacements: '%s'" % (newFullPath))
            newFullPath = applyCustomFullpathReplacements(newFullPath)

        return newFullPath
Beispiel #29
0
def symlink_file(target, name):
    p("symlink %s to %s" % (name, target))
    os.symlink(target, name)
Beispiel #30
0
def comicnamer(paths):
    """Main comicnamer function, takes an array of paths, does stuff.
    """
    # Warn about move_files function
    if Config['move_files_enable']:
        import warnings
        warnings.warn(
            "The move_files feature is still under development. "
            "Be very careful with it.\n"
            "It has not been heavily tested, and is not recommended for "
            "general use yet.")

    p("#" * 20)
    p("# Starting comicnamer")

    issues_found = []

    for cfile in findFiles(paths):
        cfile = cfile.decode("utf-8")
        parser = FileParser(cfile)
        try:
            issue = parser.parse()
        except InvalidFilename:
            warn("Invalid filename %s" % cfile)
        else:
            issues_found.append(issue)

    if len(issues_found) == 0:
        raise NoValidFilesFoundError()

    p("# Found %d issue" % len(issues_found) + ("s" * (len(issues_found) > 1)))

    # Sort issues by series name and issue number
    issues_found.sort(key=lambda x: (x.seriesname, x.issuenumbers))

    comicvine_instance = Comicvine(interactive=not Config['select_first'])

    for issue in issues_found:
        processFile(comicvine_instance, issue)
        p('')

    p("#" * 20)
    p("# Done")
Beispiel #31
0
def tvnamer(paths):
    """Main tvnamer function, takes an array of paths, does stuff.
    """
    # Warn about move_files function
    if Config['move_files_enable']:
        import warnings
        warnings.warn("The move_files feature is still under development. "
            "Be very careful with it.\n"
            "It has not been heavily tested, and is not recommended for "
            "general use yet.")

    p("#" * 20)
    p("# Starting tvnamer")

    episodes_found = []

    for cfile in findFiles(paths):
        parser = FileParser(cfile)
        try:
            episode = parser.parse()
        except InvalidFilename:
            warn("Invalid filename %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())

    tvdb_instance = Tvdb(
        interactive=not Config['select_first'],
        search_all_languages = Config['search_all_languages'],
        language = Config['language'])

    for episode in episodes_found:
        processFile(tvdb_instance, episode)
        p('')

    p("#" * 20)
    p("# Done")
Beispiel #32
0
class Renamer(object):
    """Deals with renaming of files
    """
    def __init__(self, filename):
        self.filename = os.path.abspath(filename)

    def newPath(self,
                new_path=None,
                new_fullpath=None,
                force=False,
                always_copy=False,
                always_move=False,
                leave_symlink=False,
                create_dirs=True,
                getPathPreview=False):
        """Moves the file to a new path.

        If it is on the same partition, it will be moved (unless always_copy is True)
        If it is on a different partition, it will be copied, and the original
        only deleted if always_move is True.
        If the target file already exists, it will raise OSError unless force is True.
        If it was moved, a symlink will be left behind with the original name
        pointing to the file's new destination if leave_symlink is True.
        """

        if always_copy and always_move:
            raise ValueError(
                "Both always_copy and always_move cannot be specified")

        if (new_path is None
                and new_fullpath is None) or (new_path is not None
                                              and new_fullpath is not None):
            raise ValueError("Specify only new_dir or new_fullpath")

        old_dir, old_filename = os.path.split(self.filename)
        if new_path is not None:
            # Join new filepath to old one (to handle realtive dirs)
            new_dir = os.path.abspath(os.path.join(old_dir, new_path))

            # Join new filename onto new filepath
            new_fullpath = os.path.join(new_dir, old_filename)

        else:
            # Join new filepath to old one (to handle realtive dirs)
            new_fullpath = os.path.abspath(os.path.join(old_dir, new_fullpath))

            new_dir = os.path.dirname(new_fullpath)

        if len(Config['move_files_fullpath_replacements']) > 0:
            p("Before custom full path replacements: %s" % (new_fullpath))
            new_fullpath = applyCustomFullpathReplacements(new_fullpath)
            new_dir = os.path.dirname(new_fullpath)

        p("New path: %s" % new_fullpath)

        if getPathPreview:
            return new_fullpath

        if create_dirs:
            try:
                os.makedirs(new_dir)
            except OSError, e:
                if e.errno != 17:
                    raise
            else:
                p("Created directory %s" % new_dir)

        if os.path.isfile(new_fullpath):
            # If the destination exists, raise exception unless force is True
            if not force:
                raise OSError(
                    "File %s already exists, not forcefully moving %s" %
                    (new_fullpath, self.filename))

        if same_partition(self.filename, new_dir):
            if always_copy:
                # Same partition, but forced to copy
                copy_file(self.filename, new_fullpath)
            else:
                # Same partition, just rename the file to move it
                rename_file(self.filename, new_fullpath)

                # Leave a symlink behind if configured to do so
                if leave_symlink:
                    symlink_file(new_fullpath, self.filename)
        else:
            # File is on different partition (different disc), copy it
            copy_file(self.filename, new_fullpath)
            if always_move:
                # Forced to move file, we just trash old file
                p("Deleting %s" % (self.filename))
                delete_file(self.filename)

                # Leave a symlink behind if configured to do so
                if leave_symlink:
                    symlink_file(new_fullpath, self.filename)

        self.filename = new_fullpath
Beispiel #33
0
    except (SeasonNotFound, EpisodeNotFound, EpisodeNameNotFound), errormsg:
        # Show was found, so use corrected series name
        if Config['always_rename'] and Config['skip_file_on_error'] is True:
            warn("Skipping file due to error: %s" % errormsg)
            return

        warn(errormsg)
        episode.seriesname = correctedSeriesName
    else:
        episode.seriesname = correctedSeriesName
        episode.episodename = epName

    cnamer = Renamer(episode.fullpath)
    newName = episode.generateFilename()

    p("#" * 20)
    p("Old filename: %s" % episode.fullfilename)

    if len(Config['output_filename_replacements']):
        p("Before custom output replacements: %s" % (newName))
        # Only apply to filename, not extension
        newName, newExt = os.path.splitext(newName)
        newName = applyCustomOutputReplacements(newName)
        newName = newName + newExt

    p("New filename: %s" % newName)

    if Config['always_rename']:
        doRenameFile(cnamer, newName)
        if Config['move_files_enable']:
            doMoveFile(cnamer = cnamer, destDir = getDestinationFolder(episode))
Beispiel #34
0
def symlink_file(target, name):
    """Create symbolic link named 'name' pointing to 'target'.
    """
    p("Creating symlink %s to %s" % (name, target))
    log().debug("Creating symlink %r to %r" % (name, target))
    os.symlink(target, name)
Beispiel #35
0
def warn(text):
    """Displays message to sys.stdout
    """
    p(text, file=sys.stderr)
Beispiel #36
0
def copy_file(old, new):
    p("copy %s to %s" % (old, new))
    shutil.copyfile(old, new)
    shutil.copystat(old, new)
Beispiel #37
0
        # For atomic move, restore self.filename to it's real value here
        if self.srcFilename is not None:
            self.filename = self.srcFilename
            self.srcFilename = None
        
        if os.path.isfile(new_fullpath):
            # If the destination exists, raise exception unless force is True
            if not force:
                raise OSError("File %s already exists, not forcefully moving %s" % (
                    new_fullpath, self.filename))

        if same_partition(self.filename, new_dir):
            if always_copy:
                # Same partition, but forced to copy
                p("copy %s to %s" % (self.filename, new_fullpath))
                shutil.copyfile(self.filename, new_fullpath)
            else:
                # Same partition, just rename the file to move it
                p("move %s to %s" % (self.filename, new_fullpath))
                os.rename(self.filename, new_fullpath)
        else:
            # File is on different partition (different disc), copy it
            p("copy %s to %s" % (self.filename, new_fullpath))
            shutil.copyfile(self.filename, new_fullpath)
            if always_move:
                # Forced to move file, we just trash old file
                p("Deleting %s" % (self.filename))
                delete_file(self.filename)

        # Finally, if we were asked to make a link back and there's nothing left behind, create the link
Beispiel #38
0
        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)
Beispiel #39
0
def copy_file(old, new):
    p("copy %s to %s" % (old, new))
    shutil.copyfile(old, new)
    shutil.copystat(old, new)
Beispiel #40
0
            return
        else:
            warn(errormsg)
    except (SeasonNotFound, EpisodeNotFound, EpisodeNameNotFound), errormsg:
        # Show was found, so use corrected series name
        if Config['always_rename'] and Config['skip_file_on_error']:
            warn("Skipping file due to error: %s" % errormsg)
            return

        warn(errormsg)

    cnamer = Renamer(episode.fullpath)
    newName = episode.generateFilename()

    if newName == episode.fullfilename:
        p("#" * 20)
        p("Skipping: existing filename is correct: %s" % episode.fullfilename)
        p("#" * 20)
    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)
Beispiel #41
0
def comicnamer(paths):
    """Main comicnamer function, takes an array of paths, does stuff.
    """
    # Warn about move_files function
    if Config['move_files_enable']:
        import warnings
        warnings.warn("The move_files feature is still under development. "
            "Be very careful with it.\n"
            "It has not been heavily tested, and is not recommended for "
            "general use yet.")

    p("#" * 20)
    p("# Starting comicnamer")

    issues_found = []

    for cfile in findFiles(paths):
        cfile = cfile.decode("utf-8")
        parser = FileParser(cfile)
        try:
            issue = parser.parse()
        except InvalidFilename:
            warn("Invalid filename %s" % cfile)
        else:
            issues_found.append(issue)

    if len(issues_found) == 0:
        raise NoValidFilesFoundError()

    p("# Found %d issue" % len(issues_found) + ("s" * (len(issues_found) > 1)))

    # Sort issues by volume name and issue number
    issues_found.sort(key = lambda x: (x.volumename, x.issuenumbers))

    comicvine_instance = Comicvine(
        interactive=not Config['select_first'])

    for issue in issues_found:
        processFile(comicvine_instance, issue)
        p('')

    p("#" * 20)
    p("# Done")
Beispiel #42
0
def warn(text):
    """Displays message to sys.stdout
    """
    p(text, file = sys.stderr)
Beispiel #43
0
def symlink_file(target, name):
    p("symlink %s to %s" % (name, target))
    os.symlink(target, name)
Beispiel #44
0
        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)
Beispiel #45
0
class Renamer(object):
    """Deals with renaming of files
    """
    def __init__(self, filename):
        self.filename = os.path.abspath(filename)

    def newName(self, newName, force=False):
        """Renames a file, keeping the path the same.
        """
        filepath, filename = os.path.split(self.filename)
        filename, _ = os.path.splitext(filename)

        newpath = os.path.join(filepath, newName)

        if os.path.isfile(newpath):
            # If the destination exists, raise exception unless force is True
            if not force:
                raise OSError(
                    "File %s already exists, not forcefully renaming %s" %
                    (newpath, self.filename))

        os.rename(self.filename, newpath)
        self.filename = newpath

    def newPath(self,
                new_path,
                force=False,
                always_copy=False,
                always_move=False,
                create_dirs=True,
                getPathPreview=False):
        """Moves the file to a new path.

        If it is on the same partition, it will be moved (unless always_copy is True)
        If it is on a different partition, it will be copied.
        If the target file already exists, it will raise OSError unless force is True.
        """

        if always_copy and always_move:
            raise ValueError(
                "Both always_copy and always_move cannot be specified")

        old_dir, old_filename = os.path.split(self.filename)

        # Join new filepath to old one (to handle realtive dirs)
        new_dir = os.path.abspath(os.path.join(old_dir, new_path))

        # Join new filename onto new filepath
        new_fullpath = os.path.join(new_dir, old_filename)

        if len(Config['move_files_fullpath_replacements']) > 0:
            p("Before custom full path replacements: %s" % (new_fullpath))
            new_fullpath = applyCustomFullpathReplacements(new_fullpath)
            new_dir = os.path.dirname(new_fullpath)

        p("New path: %s" % new_fullpath)

        if getPathPreview:
            return new_fullpath

        if create_dirs:
            p("Creating %s" % new_dir)
            try:
                os.makedirs(new_dir)
            except OSError, e:
                if e.errno != 17:
                    raise

        if os.path.isfile(new_fullpath):
            # If the destination exists, raise exception unless force is True
            if not force:
                raise OSError(
                    "File %s already exists, not forcefully moving %s" %
                    (new_fullpath, self.filename))

        if same_partition(self.filename, new_dir):
            if always_copy:
                # Same partition, but forced to copy
                p("copy %s to %s" % (self.filename, new_fullpath))
                shutil.copyfile(self.filename, new_fullpath)
            else:
                # Same partition, just rename the file to move it
                p("move %s to %s" % (self.filename, new_fullpath))
                os.rename(self.filename, new_fullpath)
        else:
            # File is on different partition (different disc), copy it
            p("copy %s to %s" % (self.filename, new_fullpath))
            shutil.copyfile(self.filename, new_fullpath)
            if always_move:
                # Forced to move file, we just trash old file
                p("Deleting %s" % (self.filename))
                delete_file(self.filename)

        self.filename = new_fullpath
Beispiel #46
0
            return
        else:
            warn(errormsg)
    except (SeasonNotFound, EpisodeNotFound, EpisodeNameNotFound), errormsg:
        # Show was found, so use corrected series name
        if Config['always_rename'] and Config['skip_file_on_error']:
            warn("Skipping file due to error: %s" % errormsg)
            return

        warn(errormsg)

    cnamer = Renamer(episode.fullpath)
    newName = episode.generateFilename()

    if newName == episode.fullfilename:
        p("#" * 20)
        p("Skipping: existing filename is correct: %s" % episode.fullfilename)
        p("#" * 20)
    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']:
Beispiel #47
0
    except (IssueNotFound, IssueNameNotFound), errormsg:
        # Series was found, so use corrected series name
        if Config['always_rename'] and Config['skip_file_on_error'] is True:
            warn("Skipping file due to error: %s" % errormsg)
            return

        warn(errormsg)
        issue.seriesname = correctedSeriesName
    else:
        issue.seriesname = correctedSeriesName
        issue.issuename = issName

    cnamer = Renamer(issue.fullpath)
    newName = issue.generateFilename()

    p("#" * 20)
    p("Old filename: %s" % issue.fullfilename)

    if len(Config['output_filename_replacements']):
        p("Before custom output replacements: %s" % (newName))
        # Only apply to filename, not extension
        newName, newExt = os.path.splitext(newName)
        newName = applyCustomOutputReplacements(newName)
        newName = newName + newExt

    p("New filename: %s" % newName)

    if Config['always_rename']:
        doRenameFile(cnamer, newName)
        if Config['move_files_enable']:
            doMoveFile(cnamer=cnamer, destDir=getDestinationFolder(issue))