Beispiel #1
0
def simple_import(lib, paths, copy, delete, resume):
    """Add files from the paths to the library without changing any
    tags.
    """
    for toppath, path, items in read_albums(paths, resume):
        if items is None:
            continue

        if copy:
            if delete:
                old_paths = [os.path.realpath(item.path) for item in items]
            for item in items:
                item.move(lib, True)

        album = lib.add_album(items, True)
        lib.save()            
        if resume is not False:
            progress_set(toppath, path)

        if copy and delete:
            new_paths = [os.path.realpath(item.path) for item in items]
            for old_path in old_paths:
                # Only delete files that were actually moved.
                if old_path not in new_paths:
                    os.remove(library._syspath(old_path))

        log.info('added album: %s - %s' % (album.albumartist, album.album))
Beispiel #2
0
def _sorted_walk(path):
    """Like os.walk, but yields things in sorted, breadth-first
    order.
    """
    # Make sure the path isn't a Unicode string.
    path = library._bytestring_path(path)

    # Get all the directories and files at this level.
    dirs = []
    files = []
    for base in os.listdir(path):
        cur = os.path.join(path, base)
        if os.path.isdir(library._syspath(cur)):
            dirs.append(base)
        else:
            files.append(base)

    # Sort lists and yield the current level.
    dirs.sort()
    files.sort()
    yield (path, dirs, files)

    # Recurse into directories.
    for base in dirs:
        cur = os.path.join(path, base)
        # yield from _sorted_walk(cur)
        for res in _sorted_walk(cur):
            yield res
Beispiel #3
0
def apply_choices(lib, copy, write, art, delete, progress):
    """A coroutine for applying changes to albums during the autotag
    process. The parameters to the generator control the behavior of
    the import. The coroutine accepts (items, info) pairs and yields
    nothing. items the set of Items to import; info is either a
    candidate info dictionary or CHOICE_ASIS.
    """
    lib = _reopen_lib(lib)
    while True:    
        # Get next chunk of work.
        toppath, path, items, info = yield

        # Check for "path finished" message.
        if path is DONE_SENTINEL:
            if progress:
                # Mark path as complete.
                progress_set(toppath, None)
            continue
        
        # Only process the items if info is not None (indicating a
        # skip).
        if info is not None:

            # Change metadata, move, and copy.
            if info is not CHOICE_ASIS:
                autotag.apply_metadata(items, info)
            if copy and delete:
                old_paths = [os.path.realpath(item.path) for item in items]
            for item in items:
                if copy:
                    item.move(lib, True)
                if write and info is not CHOICE_ASIS:
                    item.write()

            # Add items to library. We consolidate this at the end to avoid
            # locking while we do the copying and tag updates.
            albuminfo = lib.add_album(items, infer_aa = (info is CHOICE_ASIS))

            # Get album art if requested.
            if art and info is not CHOICE_ASIS:
                artpath = beets.autotag.art.art_for_album(info)
                if artpath:
                    albuminfo.set_art(artpath)
            
            # Write the database after each album.
            lib.save()

            # Finally, delete old files.
            if copy and delete:
                new_paths = [os.path.realpath(item.path) for item in items]
                for old_path in old_paths:
                    # Only delete files that were actually moved.
                    if old_path not in new_paths:
                        os.remove(library._syspath(old_path))

        # Update progress.
        if progress:
            progress_set(toppath, path)
Beispiel #4
0
def read_albums(paths, resume):
    """A generator yielding all the albums (as sets of Items) found in
    the user-specified list of paths. `progress` specifies whether
    the resuming feature should be used. It may be True (resume if
    possible), False (never resume), or None (ask).
    """
    # Use absolute paths.
    paths = [library._normpath(path) for path in paths]

    # Check the user-specified directories.
    for path in paths:
        if not os.path.isdir(library._syspath(path)):
            raise ui.UserError('not a directory: ' + path)

    # Look for saved progress.
    progress = resume is not False
    if progress:
        resume_dirs = {}
        for path in paths:
            resume_dir = progress_get(path)
            if resume_dir:

                # Either accept immediately or prompt for input to decide.
                if resume:
                    do_resume = True
                    ui.print_('Resuming interrupted import of %s' % path)
                else:
                    do_resume = ui.input_yn("Import of the directory:\n%s"
                                            "\nwas interrupted. Resume (Y/n)?" %
                                            path)
                ui.print_()

                if do_resume:
                    resume_dirs[path] = resume_dir
                else:
                    # Clear progress; we're starting from the top.
                    progress_set(path, None)
    
    for toppath in paths:
        # Produce each path.
        if progress:
            resume_dir = resume_dirs.get(toppath)
        for path, items in autotag.albums_in_dir(os.path.expanduser(toppath)):
            if progress and resume_dir:
                # We're fast-forwarding to resume a previous tagging.
                if path == resume_dir:
                    # We've hit the last good path! Turn off the
                    # fast-forwarding.
                    resume_dir = None
                continue

            yield toppath, path, items

        # Indicate the directory is finished.
        yield toppath, DONE_SENTINEL, None
Beispiel #5
0
def read_albums(paths):
    """A generator yielding all the albums (as sets of Items) found in
    the user-specified list of paths.
    """
    # Use absolute paths.
    paths = [library._normpath(path) for path in paths]

    # Check the user-specified directories.
    for path in paths:
        if not os.path.isdir(library._syspath(path)):
            raise ui.UserError('not a directory: ' + path)
    # Look for saved progress.
    resume_dirs = {}
    for path in paths:
        resume_dir = progress_get(path)
        if resume_dir:
            resume = ui.input_yn("Import of the directory:\n%s"
                                 "\nwas interrupted. Resume (Y/n)? " %
                                 path)
            if resume:
                resume_dirs[path] = resume_dir
            else:
                # Clear progress; we're starting from the top.
                progress_set(path, None)
            ui.print_()
    
    for toppath in paths:
        # Produce each path.
        resume_dir = resume_dirs.get(toppath)
        for path, items in autotag.albums_in_dir(os.path.expanduser(toppath)):
            if resume_dir:
                # We're fast-forwarding to resume a previous tagging.
                if path == resume_dir:
                    # We've hit the last good path! Turn off the
                    # fast-forwarding.
                    resume_dir = None
                continue

            yield toppath, path, items

        # Indicate the directory is finished.
        yield toppath, DONE_SENTINEL, None
Beispiel #6
0
def simple_import(lib, paths, copy, delete):
    """Add files from the paths to the library without changing any
    tags.
    """
    for toppath, path, items in read_albums(paths):
        if items is None:
            continue

        if copy:
            if delete:
                old_paths = [item.path for item in items]
            for item in items:
                item.move(lib, True)

        album = lib.add_album(items)
        lib.save()            
        progress_set(toppath, path)

        if copy and delete:
            for old_path in old_paths:
                os.remove(library._syspath(old_path))

        log.info('added album: %s - %s' % (album.artist, album.album))