def safe_delete_folder(path):
        """
        Deletes a folder and all of its contents recursively, even
        if it has read-only items.

        .. note::
            Problems deleting any items will be reported as warnings in the
            log output but otherwise ignored and skipped; meaning the function
            will continue deleting as much as it can.

        :param path: File system path to location to the folder to be deleted
        """
        def _on_rm_error(func, path, exc_info):
            """
            Error function called whenever shutil.rmtree fails to remove
            a file system item. Exceptions raised by this function will not
            be caught.

            :param func: The function which raised the exception; it will be:
                         os.path.islink(), os.listdir(),
                         os.remove() or os.rmdir().
            :param path: The path name passed to function.
            :param exc_info: The exception information return
                             by sys.exc_info().
            """
            if func == os.unlink or func == os.remove or func == os.rmdir:
                try:
                    attr = get_permissions(path)
                    if not (attr & stat.S_IWRITE):
                        os.chmod(path, stat.S_IWRITE | attr)
                        try:
                            func(path)
                        except Exception as e:
                            log.warning("Couldn't delete %s: %s. Skipping" %
                                        (path, e))
                    else:
                        log.warning("Couldn't delete %s: Skipping" % path)
                except Exception as e:
                    log.warning("Could not delete %s: %s. Skipping" %
                                (path, e))
            else:
                log.warning("Couldn't delete %s. Skipping." % path)

        if os.path.exists(path):
            try:
                # On Windows, Python's shutil can't delete read-only files,
                # so if we were trying to delete one, remove the flag.
                # Inspired by http://stackoverflow.com/a/4829285/1074536
                shutil.rmtree(path, onerror=_on_rm_error)
            except Exception as e:
                log.warning("Could not delete %s: %s" % (path, e))
        else:
            log.warning("Could not delete: %s. Folder does not exist" % path)
        def _on_rm_error(func, path, exc_info):
            """
            Error function called whenever shutil.rmtree fails to remove
            a file system item. Exceptions raised by this function will not
            be caught.

            :param func: The function which raised the exception; it will be:
                         os.path.islink(), os.listdir(),
                         os.remove() or os.rmdir().
            :param path: The path name passed to function.
            :param exc_info: The exception information return
                             by sys.exc_info().
            """
            if func == os.unlink or func == os.remove or func == os.rmdir:
                try:
                    attr = get_permissions(path)
                    if not (attr & stat.S_IWRITE):
                        os.chmod(path, stat.S_IWRITE | attr)
                        try:
                            func(path)
                        except Exception as e:
                            log.warning("Couldn't delete %s: %s. Skipping" %
                                        (path, e))
                    else:
                        log.warning("Couldn't delete %s: Skipping" % path)
                except Exception as e:
                    log.warning("Could not delete %s: %s. Skipping" %
                                (path, e))
            else:
                log.warning("Couldn't delete %s. Skipping." % path)
    def safe_delete_file(path):
        """
        Deletes the given file if it exists.

        Ignores any errors raised in the process and logs them as warnings.
        If the user does not have sufficient permissions to
        remove the file, nothing will happen, it will simply
        be skipped over.

        :param path: Full path to file to remove
        """
        try:
            if os.path.exists(path):
                # on windows, make sure file is not read-only
                if sys.platform == "win32":
                    # make sure we have write permission
                    attr = os.stat(path)[0]
                    if not attr & stat.S_IWRITE:
                        os.chmod(path, stat.S_IWRITE)
                os.remove(path)
        except Exception as e:
            log.warning("File '%s' could not be deleted, skipping: %s" %
                        (path, e))