mirror of
https://github.com/beetbox/beets.git
synced 2026-02-17 12:56:05 +01:00
lastgenre: Named types; Document flatten_tree
- Define types for whitelist and canonicalization tree - Better document the flatten_tree function
This commit is contained in:
parent
9116de0c56
commit
0f131b5dee
4 changed files with 60 additions and 9 deletions
|
|
@ -41,6 +41,8 @@ if TYPE_CHECKING:
|
|||
|
||||
from beets.library import LibModel
|
||||
|
||||
from .types import CanonTree
|
||||
|
||||
|
||||
class LastGenrePlugin(plugins.BeetsPlugin):
|
||||
def __init__(self) -> None:
|
||||
|
|
@ -116,7 +118,7 @@ class LastGenrePlugin(plugins.BeetsPlugin):
|
|||
return [p[1] for p in depth_tag_pairs]
|
||||
|
||||
@staticmethod
|
||||
def find_parents(candidate: str, branches: list[list[str]]) -> list[str]:
|
||||
def find_parents(candidate: str, branches: CanonTree) -> list[str]:
|
||||
"""Find parent genres of a given genre, ordered from closest to furthest."""
|
||||
for branch in branches:
|
||||
try:
|
||||
|
|
|
|||
|
|
@ -31,6 +31,8 @@ if TYPE_CHECKING:
|
|||
|
||||
from beets.logging import Logger
|
||||
|
||||
from .types import GenreCache
|
||||
|
||||
LASTFM = pylast.LastFMNetwork(api_key=plugins.LASTFM_KEY)
|
||||
|
||||
PYLAST_EXCEPTIONS = (
|
||||
|
|
@ -51,7 +53,7 @@ class LastFmClient:
|
|||
self._log = log
|
||||
self._tunelog = make_tunelog(log)
|
||||
self._min_weight = min_weight
|
||||
self._genre_cache: dict[str, list[str]] = {}
|
||||
self._genre_cache: GenreCache = {}
|
||||
|
||||
def fetch_genre(
|
||||
self, lastfm_obj: pylast.Album | pylast.Artist | pylast.Track
|
||||
|
|
|
|||
|
|
@ -28,6 +28,8 @@ if TYPE_CHECKING:
|
|||
|
||||
from beets.logging import Logger
|
||||
|
||||
from .types import CanonTree, Whitelist
|
||||
|
||||
|
||||
class DataFileLoader:
|
||||
"""Loads genre-related data files for the lastgenre plugin."""
|
||||
|
|
@ -36,8 +38,8 @@ class DataFileLoader:
|
|||
self,
|
||||
log: Logger,
|
||||
plugin_dir: Path,
|
||||
whitelist: set[str],
|
||||
c14n_branches: list[list[str]],
|
||||
whitelist: Whitelist,
|
||||
c14n_branches: CanonTree,
|
||||
canonicalize: bool,
|
||||
):
|
||||
"""Initialize with pre-loaded data.
|
||||
|
|
@ -83,7 +85,7 @@ class DataFileLoader:
|
|||
@staticmethod
|
||||
def _load_whitelist(
|
||||
log: Logger, config_value: str | bool | None, default_path: str
|
||||
) -> set[str]:
|
||||
) -> Whitelist:
|
||||
"""Load the whitelist from a text file.
|
||||
|
||||
Returns set of valid genre names (lowercase).
|
||||
|
|
@ -107,12 +109,12 @@ class DataFileLoader:
|
|||
config_value: str | bool | None,
|
||||
default_path: str,
|
||||
prefer_specific: bool,
|
||||
) -> tuple[list[list[str]], bool]:
|
||||
) -> tuple[CanonTree, bool]:
|
||||
"""Load the canonicalization tree from a YAML file.
|
||||
|
||||
Returns tuple of (branches, canonicalize_enabled).
|
||||
"""
|
||||
c14n_branches: list[list[str]] = []
|
||||
c14n_branches: CanonTree = []
|
||||
c14n_filename = config_value
|
||||
canonicalize = c14n_filename is not False
|
||||
# Default tree
|
||||
|
|
@ -133,9 +135,24 @@ class DataFileLoader:
|
|||
def flatten_tree(
|
||||
elem: dict[str, Any] | list[Any] | str,
|
||||
path: list[str],
|
||||
branches: list[list[str]],
|
||||
branches: CanonTree,
|
||||
) -> None:
|
||||
"""Flatten nested lists/dictionaries into lists of strings (branches)."""
|
||||
"""Flatten nested YAML structure into genre hierarchy branches.
|
||||
|
||||
Recursively converts nested dicts/lists from YAML into a flat list
|
||||
of genre paths, where each path goes from general to specific genre.
|
||||
|
||||
Args:
|
||||
elem: The YAML element to process (dict, list, or string leaf).
|
||||
path: Current path from root to this element (used in recursion).
|
||||
branches: OUTPUT PARAMETER - Empty list that will be populated
|
||||
with genre paths. Gets mutated by this method.
|
||||
|
||||
Example:
|
||||
branches = []
|
||||
flatten_tree({'rock': ['indie', 'punk']}, [], branches)
|
||||
# branches is now: [['rock', 'indie'], ['rock', 'punk']]
|
||||
"""
|
||||
if not path:
|
||||
path = []
|
||||
|
||||
|
|
|
|||
30
beetsplug/lastgenre/types.py
Normal file
30
beetsplug/lastgenre/types.py
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
# This file is part of beets.
|
||||
# Copyright 2026, J0J0 Todos.
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining
|
||||
# a copy of this software and associated documentation files (the
|
||||
# "Software"), to deal in the Software without restriction, including
|
||||
# without limitation the rights to use, copy, modify, merge, publish,
|
||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
||||
# permit persons to whom the Software is furnished to do so, subject to
|
||||
# the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be
|
||||
# included in all copies or substantial portions of the Software.
|
||||
|
||||
|
||||
"""Type aliases for the lastgenre plugin."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
Whitelist = set[str]
|
||||
"""Set of valid genre names (lowercase). Empty set means all genres allowed."""
|
||||
|
||||
CanonTree = list[list[str]]
|
||||
"""Genre hierarchy as list of paths from general to specific.
|
||||
Example: [['electronic', 'house'], ['electronic', 'techno']]"""
|
||||
|
||||
GenreCache = dict[str, list[str]]
|
||||
"""Cache mapping entity keys to their genre lists.
|
||||
Keys are formatted as 'entity.arg1-arg2-...' (e.g., 'album.artist-title').
|
||||
Values are lists of lowercase genre strings."""
|
||||
Loading…
Reference in a new issue