Пример #1
0
def _item_duplicate_check(lib, task):
    """Check whether an item already exists in the library. Returns a
    list of Item objects.
    """
    assert task.choice_flag in (action.ASIS, action.APPLY)
    artist, title = task.chosen_ident()

    found_items = []
    query = library.AndQuery((
        library.MatchQuery('artist', artist),
        library.MatchQuery('title', title),
    ))
    for other_item in lib.items(query):
        # Existing items not considered duplicates.
        if other_item.path == task.item.path:
            continue
        found_items.append(other_item)
    return found_items
Пример #2
0
 def get_item(self, path):
     """Return the beets item related to path.
     """
     query = library.MatchQuery('path', path)
     item = self.lib.items(query).get()
     if item:
         return item
     else:
         log.info(u'mpdstats: item not found: {0}'.format(
             displayable_path(path)))
Пример #3
0
def _duplicate_check(lib, task):
    """Check whether an album already exists in the library. Returns a
    list of Album objects (empty if no duplicates are found).
    """
    assert task.choice_flag in (action.ASIS, action.APPLY)
    artist, album = task.chosen_ident()

    if artist is None:
        # As-is import with no artist. Skip check.
        return []

    found_albums = []
    cur_paths = set(i.path for i in task.items if i)
    for album_cand in lib.albums(library.MatchQuery('albumartist', artist)):
        if album_cand.album == album:
            # Check whether the album is identical in contents, in which
            # case it is not a duplicate (will be replaced).
            other_paths = set(i.path for i in album_cand.items())
            if other_paths == cur_paths:
                continue
            found_albums.append(album_cand)
    return found_albums
Пример #4
0
def apply_choices(session):
    """A coroutine for applying changes to albums and singletons during
    the autotag process.
    """
    task = None
    while True:
        task = yield task
        if task.should_skip():
            continue

        items = task.imported_items()
        # Clear IDs in case the items are being re-tagged.
        for item in items:
            item.id = None
            item.album_id = None

        # Change metadata.
        if task.should_write_tags():
            if task.is_album:
                autotag.apply_metadata(task.match.info, task.match.mapping)
            else:
                autotag.apply_item_metadata(task.item, task.match.info)
            plugins.send('import_task_apply', session=session, task=task)

        # Infer album-level fields.
        if task.is_album:
            _infer_album_fields(task)

        # Find existing item entries that these are replacing (for
        # re-imports). Old album structures are automatically cleaned up
        # when the last item is removed.
        task.replaced_items = defaultdict(list)
        for item in items:
            dup_items = session.lib.items(library.MatchQuery(
                'path', item.path))
            for dup_item in dup_items:
                task.replaced_items[item].append(dup_item)
                log.debug('replacing item %i: %s' %
                          (dup_item.id, displayable_path(item.path)))
        log.debug('%i of %i items replaced' %
                  (len(task.replaced_items), len(items)))

        # Find old items that should be replaced as part of a duplicate
        # resolution.
        duplicate_items = []
        if task.remove_duplicates:
            if task.is_album:
                for album in _duplicate_check(session.lib, task):
                    duplicate_items += album.items()
            else:
                duplicate_items = _item_duplicate_check(session.lib, task)
            log.debug('removing %i old duplicated items' %
                      len(duplicate_items))

            # Delete duplicate files that are located inside the library
            # directory.
            for duplicate_path in [i.path for i in duplicate_items]:
                if session.lib.directory in util.ancestry(duplicate_path):
                    log.debug(u'deleting replaced duplicate %s' %
                              util.displayable_path(duplicate_path))
                    util.remove(duplicate_path)
                    util.prune_dirs(os.path.dirname(duplicate_path),
                                    session.lib.directory)

        # Add items -- before path changes -- to the library. We add the
        # items now (rather than at the end) so that album structures
        # are in place before calls to destination().
        with session.lib.transaction():
            # Remove old items.
            for replaced in task.replaced_items.itervalues():
                for item in replaced:
                    session.lib.remove(item)
            for item in duplicate_items:
                session.lib.remove(item)

            # Add new ones.
            if task.is_album:
                # Add an album.
                album = session.lib.add_album(items)
                task.album_id = album.id
            else:
                # Add tracks.
                for item in items:
                    session.lib.add(item)
Пример #5
0
def apply_choices(config):
    """A coroutine for applying changes to albums during the autotag
    process.
    """
    lib = _reopen_lib(config.lib)
    task = None
    while True:    
        task = yield task
        if task.should_skip():
            continue

        items = [i for i in task.items if i] if task.is_album else [task.item]
        # Clear IDs in case the items are being re-tagged.
        for item in items:
            item.id = None
            item.album_id = None

        # Change metadata.
        if task.should_write_tags():
            if task.is_album:
                autotag.apply_metadata(task.items, task.info)
            else:
                autotag.apply_item_metadata(task.item, task.info)

        # Infer album-level fields.
        if task.is_album:
            _infer_album_fields(task)

        # Find existing item entries that these are replacing. Old
        # album structures are automatically cleaned up when the
        # last item is removed.
        replaced_items = defaultdict(list)
        for item in items:
            dup_items = lib.items(library.MatchQuery('path', item.path))
            for dup_item in dup_items:
                replaced_items[item].append(dup_item)
                log.debug('replacing item %i: %s' %
                          (dup_item.id, displayable_path(item.path)))
        log.debug('%i of %i items replaced' % (len(replaced_items),
                                               len(items)))

        # Move/copy files.
        task.old_paths = [item.path for item in items]
        for item in items:
            if config.copy:
                # If we're replacing an item, then move rather than
                # copying.
                do_copy = not bool(replaced_items[item])
                lib.move(item, do_copy, task.is_album)
            if config.write and task.should_write_tags():
                item.write()

        # Add items to library. We consolidate this at the end to avoid
        # locking while we do the copying and tag updates.
        try:
            # Remove old items.
            for replaced in replaced_items.itervalues():
                for item in replaced:
                    lib.remove(item)

            # Add new ones.
            if task.is_album:
                # Add an album.
                album = lib.add_album(items)
                task.album_id = album.id
            else:
                # Add tracks.
                for item in items:
                    lib.add(item)
        finally:
            lib.save()