From b68d6b17678e5577f70c059c4358d3fafb473de5 Mon Sep 17 00:00:00 2001 From: Max Goltzsche Date: Mon, 12 Feb 2024 00:24:19 +0100 Subject: [PATCH] feat: store single `genre`, write list to `genres` This is a breaking change (but I don't want to bump to v1 yet): * When `lastgenre.count` > 1 configured, multiple genres are stored within the `genres` field (along with the first genre's parent genres) but the `genre` field holds only the first genre of the `genres` list. * The `genre_primary` field has been dropped correspondingly. --- beetsplug/autogenre/__init__.py | 39 ++++++++++++++++++--------------- tests/e2e/tests.bats | 2 +- 2 files changed, 22 insertions(+), 19 deletions(-) diff --git a/beetsplug/autogenre/__init__.py b/beetsplug/autogenre/__init__.py index ce2a6d4..3d9bd83 100644 --- a/beetsplug/autogenre/__init__.py +++ b/beetsplug/autogenre/__init__.py @@ -3,6 +3,7 @@ import os import re import yaml +from beets import ui from beets.plugins import BeetsPlugin from beets.dbcore import types from beets.dbcore.query import FixedFieldSort @@ -127,44 +128,46 @@ def _run_autogenre_cmd(self, lib, opts, args): filtered_items = [item for item in items if _filter_item(item, all, force)] self._log.info('Selected {} items for genre update...', len(filtered_items)) for item in items: - genre, source = self._item_genre(item, all, force, opts, genre_tree) + genres, source = self._item_genres(item, all, force, opts, genre_tree) + genrel = self._str2list(genres) + genre = genres and genrel[0] or None - if genre: - genre_primary = genre and self._str2list(genre)[0] or None - if opts.parent_genres and genre_primary: - parent_genres = genre_tree.parents(genre_primary) + if genres: + if opts.parent_genres and genre: + # Append primary genre's parent genres to genre list + parent_genres = genre_tree.parents(genre) parent_genres = [self._format_genre(g) for g in parent_genres] - genres = self._str2list(genre) - genres = genres + [g for g in parent_genres if g not in genres] - genre = self._list2str(genres) + genrel = genrel + [g for g in parent_genres if g not in genrel] + genres = self._list2str(genrel) genre_changed = genre != item.get('genre') - genre_primary_changed = genre_primary != item.get('genre_primary') + genres_changed = genres != item.get('genres') genre_source_changed = source != item.get('genre_source') - changed = genre_changed or genre_primary_changed or genre_source_changed - if changed and genre is not None: + changed = genre_changed or genres_changed or genre_source_changed + if changed and genres is not None: msg = "Changing genre from '{}' to '{}' ({}) for item: {}" self._log.info(msg, item.get('genre'), genre, source, item) + write = ui.should_write() if not opts.pretend: item.genre = genre - item.genre_primary = genre_primary + item.genres = genres item.genre_source = source + if write: + item.try_write() item.store() # TODO: match remix artist within title and get genre from artist: TITLE (ARTIST remix) - def _item_genre(self, item, all, force, opts, genre_tree): - genre = item.get('genre') + def _item_genres(self, item, all, force, opts, genre_tree): + genre = item.get('genres') + if not genre: + genre = item.get('genre') source = item.get('genre_source') orig_genre = genre orig_source = source - genre_primary = item.get('genre_primary') if _filter_item(item, all, force): if opts.genre is not None: source = opts.genre and 'user' or None genre = self._format_genre(opts.genre.lower()) - elif source == 'user' and genre_primary: - if not genre: - genre = genre_primary if source != 'user' or not genre: # auto-detect genre if opts.lastgenre: diff --git a/tests/e2e/tests.bats b/tests/e2e/tests.bats index 1a35c9f..24cae4e 100644 --- a/tests/e2e/tests.bats +++ b/tests/e2e/tests.bats @@ -1,7 +1,7 @@ #!/usr/bin/env bats assertGenre() { - FMT='$genre_source | $genre_primary | $genre' + FMT='$genre_source | $genre | $genres' ACTUAL="$(beet ls $1 -f "$FMT")" [ "$ACTUAL" = "$2" ] || ( echo "ERROR: Expected query '$1' with format '$FMT' to evaluate to '$2' but was '$ACTUAL'" >&2