From 7552464c95d83d2fbecad2cf09df67427fb710b9 Mon Sep 17 00:00:00 2001 From: blissful Date: Wed, 25 Oct 2023 00:44:58 -0400 Subject: [PATCH] improve artist alias config type --- README.md | 5 ++--- rose/config.py | 26 ++++++++++++++++++-------- rose/config_test.py | 27 ++++++++++----------------- 3 files changed, 30 insertions(+), 28 deletions(-) diff --git a/README.md b/README.md index 80e58d2..07377a6 100644 --- a/README.md +++ b/README.md @@ -148,9 +148,8 @@ max_proc = 4 # Artist aliases: Releases belonging to an alias will also appear in the main # artists' releases. artist_aliases = [ - ["main_artist", ["alias1", "alias2"]], - ["Abakus", ["Cinnamon Chasers"]], - ["tripleS", ["EVOLution", "LOVElution", "+(KR)ystal Eyes", "Acid Angel From Asia", "Acid Eyes"]], + { artist = "Abakus", aliases = ["Cinnamon Chasers"] }, + { artist = "tripleS", aliases = ["EVOLution", "LOVElution", "+(KR)ystal Eyes", "Acid Angel From Asia", "Acid Eyes"] }, ] # Artists, genres, and labels to hide from the virtual filesystem navigation. fuse_hide_artists = [ "xxx" ] diff --git a/rose/config.py b/rose/config.py index 5276d4c..5270953 100644 --- a/rose/config.py +++ b/rose/config.py @@ -21,6 +21,10 @@ class ConfigNotFoundError(RoseError): pass +class ConfigDecodeError(RoseError): + pass + + class MissingConfigKeyError(RoseError): pass @@ -59,6 +63,8 @@ def read(cls, config_path_override: Path | None = None) -> Config: data = tomllib.loads(cfgtext) except FileNotFoundError as e: raise ConfigNotFoundError(f"Configuration file not found ({cfgpath})") from e + except tomllib.TOMLDecodeError as e: + raise ConfigDecodeError("Failed to decode configuration file: invalid TOML") from e try: music_source_dir = Path(data["music_source_dir"]).expanduser() @@ -109,18 +115,22 @@ def read(cls, config_path_override: Path | None = None) -> Config: artist_aliases_map: dict[str, list[str]] = defaultdict(list) artist_aliases_parents_map: dict[str, list[str]] = defaultdict(list) try: - for parent, subs in data.get("artist_aliases", []): - artist_aliases_map[parent] = subs - if not isinstance(subs, list): - raise ValueError(f"Aliases must be of type list[str]: got {type(subs)}") - for s in subs: + for entry in data.get("artist_aliases", []): + if not isinstance(entry["artist"], str): + raise ValueError(f"Artists must be of type str: got {type(entry['artist'])}") + artist_aliases_map[entry["artist"]] = entry["aliases"] + if not isinstance(entry["aliases"], list): + raise ValueError( + f"Aliases must be of type list[str]: got {type(entry['aliases'])}" + ) + for s in entry["aliases"]: if not isinstance(s, str): raise ValueError(f"Each alias must be of type str: got {type(s)}") - artist_aliases_parents_map[s].append(parent) - except (ValueError, TypeError) as e: + artist_aliases_parents_map[s].append(entry["artist"]) + except (ValueError, TypeError, KeyError) as e: raise InvalidConfigValueError( f"Invalid value for artist_aliases in configuration file ({cfgpath}): " - "must be a list of (parent: str, aliases: list[str]) tuples" + "must be a list of { artist = str, aliases = list[str] } records" ) from e try: diff --git a/rose/config_test.py b/rose/config_test.py index 8a6071d..7f9d93d 100644 --- a/rose/config_test.py +++ b/rose/config_test.py @@ -34,8 +34,8 @@ def test_config_full() -> None: cache_dir = "{cache_dir}" max_proc = 8 artist_aliases = [ - ["Abakus", ["Cinnamon Chasers"]], - ["tripleS", ["EVOLution", "LOVElution", "+(KR)ystal Eyes", "Acid Angel From Asia", "Acid Eyes"]], + {{ artist = "Abakus", aliases = ["Cinnamon Chasers"] }}, + {{ artist = "tripleS", aliases = ["EVOLution", "LOVElution", "+(KR)ystal Eyes", "Acid Angel From Asia", "Acid Eyes"] }}, ] fuse_hide_artists = [ "xxx" ] fuse_hide_genres = [ "yyy" ] @@ -153,44 +153,37 @@ def write(x: str) -> None: Config.read(config_path_override=path) assert ( str(excinfo.value) - == f"Invalid value for artist_aliases in configuration file ({path}): must be a list of (parent: str, aliases: list[str]) tuples" # noqa + == f"Invalid value for artist_aliases in configuration file ({path}): must be a list of {{ artist = str, aliases = list[str] }} records" # noqa ) write(config + '\nartist_aliases = ["lalala"]') with pytest.raises(InvalidConfigValueError) as excinfo: Config.read(config_path_override=path) assert ( str(excinfo.value) - == f"Invalid value for artist_aliases in configuration file ({path}): must be a list of (parent: str, aliases: list[str]) tuples" # noqa + == f"Invalid value for artist_aliases in configuration file ({path}): must be a list of {{ artist = str, aliases = list[str] }} records" # noqa ) write(config + '\nartist_aliases = [["lalala"]]') with pytest.raises(InvalidConfigValueError) as excinfo: Config.read(config_path_override=path) assert ( str(excinfo.value) - == f"Invalid value for artist_aliases in configuration file ({path}): must be a list of (parent: str, aliases: list[str]) tuples" # noqa + == f"Invalid value for artist_aliases in configuration file ({path}): must be a list of {{ artist = str, aliases = list[str] }} records" # noqa ) - write(config + '\nartist_aliases = [["lalala", "lalala"]]') + write(config + '\nartist_aliases = [{artist="lalala", aliases="lalala"}]') with pytest.raises(InvalidConfigValueError) as excinfo: Config.read(config_path_override=path) assert ( str(excinfo.value) - == f"Invalid value for artist_aliases in configuration file ({path}): must be a list of (parent: str, aliases: list[str]) tuples" # noqa + == f"Invalid value for artist_aliases in configuration file ({path}): must be a list of {{ artist = str, aliases = list[str] }} records" # noqa ) - write(config + '\nartist_aliases = [["lalala", "lalala", "lalala"]]') + write(config + '\nartist_aliases = [{artist="lalala", aliases=[123]}]') with pytest.raises(InvalidConfigValueError) as excinfo: Config.read(config_path_override=path) assert ( str(excinfo.value) - == f"Invalid value for artist_aliases in configuration file ({path}): must be a list of (parent: str, aliases: list[str]) tuples" # noqa + == f"Invalid value for artist_aliases in configuration file ({path}): must be a list of {{ artist = str, aliases = list[str] }} records" # noqa ) - write(config + '\nartist_aliases = [["lalala", [123]]]') - with pytest.raises(InvalidConfigValueError) as excinfo: - Config.read(config_path_override=path) - assert ( - str(excinfo.value) - == f"Invalid value for artist_aliases in configuration file ({path}): must be a list of (parent: str, aliases: list[str]) tuples" # noqa - ) - config += '\nartist_aliases = [["tripleS", ["EVOLution"]]]' + config += '\nartist_aliases = [{artist="tripleS", aliases=["EVOLution"]}]' # fuse_hide_artists write(config + '\nfuse_hide_artists = "lalala"')