mirror of
https://github.com/beetbox/beets.git
synced 2026-02-08 08:25:23 +01:00
lastgenre: File loaders module
This commit is contained in:
parent
18b6d30b49
commit
ae7e265fd8
2 changed files with 140 additions and 51 deletions
|
|
@ -24,18 +24,16 @@ https://gist.github.com/1241307
|
|||
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
from functools import singledispatchmethod
|
||||
from pathlib import Path
|
||||
from typing import TYPE_CHECKING, Any
|
||||
|
||||
import yaml
|
||||
|
||||
from beets import config, library, plugins, ui
|
||||
from beets.library import Album, Item
|
||||
from beets.util import plurality, unique_list
|
||||
|
||||
from .client import LastFmClient
|
||||
from .loaders import DataFileLoader
|
||||
from .utils import make_tunelog
|
||||
|
||||
if TYPE_CHECKING:
|
||||
|
|
@ -81,12 +79,6 @@ def find_parents(candidate: str, branches: list[list[str]]) -> list[str]:
|
|||
return [candidate]
|
||||
|
||||
|
||||
# Main plugin logic.
|
||||
|
||||
WHITELIST = os.path.join(os.path.dirname(__file__), "genres.txt")
|
||||
C14N_TREE = os.path.join(os.path.dirname(__file__), "genres-tree.yaml")
|
||||
|
||||
|
||||
class LastGenrePlugin(plugins.BeetsPlugin):
|
||||
def __init__(self) -> None:
|
||||
super().__init__()
|
||||
|
|
@ -119,49 +111,13 @@ class LastGenrePlugin(plugins.BeetsPlugin):
|
|||
self.client = LastFmClient(
|
||||
self._log, self.config["min_weight"].get(int)
|
||||
)
|
||||
self.whitelist = self._load_whitelist()
|
||||
self.c14n_branches, self.canonicalize = self._load_c14n_tree()
|
||||
|
||||
def _load_whitelist(self) -> set[str]:
|
||||
"""Load the whitelist from a text file.
|
||||
|
||||
Default whitelist is used if config is True, empty string or set to "nothing".
|
||||
"""
|
||||
whitelist = set()
|
||||
wl_filename = self.config["whitelist"].get()
|
||||
if wl_filename in (True, "", None): # Indicates the default whitelist.
|
||||
wl_filename = WHITELIST
|
||||
if wl_filename:
|
||||
self._log.debug("Loading whitelist {}", wl_filename)
|
||||
text = Path(wl_filename).expanduser().read_text(encoding="utf-8")
|
||||
for line in text.splitlines():
|
||||
if (line := line.strip().lower()) and not line.startswith("#"):
|
||||
whitelist.add(line)
|
||||
|
||||
return whitelist
|
||||
|
||||
def _load_c14n_tree(self) -> tuple[list[list[str]], bool]:
|
||||
"""Load the canonicalization tree from a YAML file.
|
||||
|
||||
Default tree is used if config is True, empty string, set to "nothing"
|
||||
or if prefer_specific is enabled.
|
||||
"""
|
||||
c14n_branches: list[list[str]] = []
|
||||
c14n_filename = self.config["canonical"].get()
|
||||
canonicalize = c14n_filename is not False
|
||||
# Default tree
|
||||
if c14n_filename in (True, "", None) or (
|
||||
# prefer_specific requires a tree, load default tree
|
||||
not canonicalize and self.config["prefer_specific"].get()
|
||||
):
|
||||
c14n_filename = C14N_TREE
|
||||
# Read the tree
|
||||
if c14n_filename:
|
||||
self._log.debug("Loading canonicalization tree {}", c14n_filename)
|
||||
with Path(c14n_filename).expanduser().open(encoding="utf-8") as f:
|
||||
genres_tree = yaml.safe_load(f)
|
||||
flatten_tree(genres_tree, [], c14n_branches)
|
||||
return c14n_branches, canonicalize
|
||||
loader = DataFileLoader.from_config(
|
||||
self.config, self._log, Path(__file__).parent, flatten_tree
|
||||
)
|
||||
self.whitelist = loader.whitelist
|
||||
self.c14n_branches = loader.c14n_branches
|
||||
self.canonicalize = loader.canonicalize
|
||||
|
||||
@property
|
||||
def sources(self) -> tuple[str, ...]:
|
||||
|
|
|
|||
133
beetsplug/lastgenre/loaders.py
Normal file
133
beetsplug/lastgenre/loaders.py
Normal file
|
|
@ -0,0 +1,133 @@
|
|||
# This file is part of beets.
|
||||
# Copyright 2016, Adrian Sampson.
|
||||
# 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.
|
||||
|
||||
|
||||
"""Data file loaders for the lastgenre plugin."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from pathlib import Path
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
import yaml
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from confuse import ConfigView
|
||||
|
||||
from beets.logging import Logger
|
||||
|
||||
|
||||
class DataFileLoader:
|
||||
"""Loads genre-related data files for the lastgenre plugin."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
log: Logger,
|
||||
plugin_dir: Path,
|
||||
whitelist: set[str],
|
||||
c14n_branches: list[list[str]],
|
||||
canonicalize: bool,
|
||||
):
|
||||
"""Initialize with pre-loaded data.
|
||||
|
||||
Use from_config() classmethod to construct from plugin config.
|
||||
"""
|
||||
self._log = log
|
||||
self._plugin_dir = plugin_dir
|
||||
self.whitelist = whitelist
|
||||
self.c14n_branches = c14n_branches
|
||||
self.canonicalize = canonicalize
|
||||
|
||||
@classmethod
|
||||
def from_config(
|
||||
cls,
|
||||
config: ConfigView,
|
||||
log: Logger,
|
||||
plugin_dir: Path,
|
||||
flatten_func: Callable,
|
||||
) -> DataFileLoader:
|
||||
"""Create a DataFileLoader from plugin configuration.
|
||||
|
||||
Reads config values and loads all data files during construction.
|
||||
"""
|
||||
# Default paths
|
||||
default_whitelist = str(plugin_dir / "genres.txt")
|
||||
default_tree = str(plugin_dir / "genres-tree.yaml")
|
||||
|
||||
# Load whitelist
|
||||
whitelist = cls._load_whitelist(
|
||||
log, config["whitelist"].get(), default_whitelist
|
||||
)
|
||||
|
||||
# Load tree
|
||||
c14n_branches, canonicalize = cls._load_tree(
|
||||
log,
|
||||
config["canonical"].get(),
|
||||
default_tree,
|
||||
config["prefer_specific"].get(),
|
||||
flatten_func,
|
||||
)
|
||||
|
||||
return cls(log, plugin_dir, whitelist, c14n_branches, canonicalize)
|
||||
|
||||
@staticmethod
|
||||
def _load_whitelist(
|
||||
log: Logger, config_value: str | bool | None, default_path: str
|
||||
) -> set[str]:
|
||||
"""Load the whitelist from a text file.
|
||||
|
||||
Returns set of valid genre names (lowercase).
|
||||
"""
|
||||
whitelist = set()
|
||||
wl_filename = config_value
|
||||
if wl_filename in (True, "", None): # Indicates the default whitelist.
|
||||
wl_filename = default_path
|
||||
if wl_filename:
|
||||
log.debug("Loading whitelist {}", wl_filename)
|
||||
text = Path(wl_filename).expanduser().read_text(encoding="utf-8")
|
||||
for line in text.splitlines():
|
||||
if (line := line.strip().lower()) and not line.startswith("#"):
|
||||
whitelist.add(line)
|
||||
|
||||
return whitelist
|
||||
|
||||
@staticmethod
|
||||
def _load_tree(
|
||||
log: Logger,
|
||||
config_value: str | bool | None,
|
||||
default_path: str,
|
||||
prefer_specific: bool,
|
||||
flatten_func: Callable,
|
||||
) -> tuple[list[list[str]], bool]:
|
||||
"""Load the canonicalization tree from a YAML file.
|
||||
|
||||
Returns tuple of (branches, canonicalize_enabled).
|
||||
"""
|
||||
c14n_branches: list[list[str]] = []
|
||||
c14n_filename = config_value
|
||||
canonicalize = c14n_filename is not False
|
||||
# Default tree
|
||||
if c14n_filename in (True, "", None) or (
|
||||
# prefer_specific requires a tree, load default tree
|
||||
not canonicalize and prefer_specific
|
||||
):
|
||||
c14n_filename = default_path
|
||||
# Read the tree
|
||||
if c14n_filename:
|
||||
log.debug("Loading canonicalization tree {}", c14n_filename)
|
||||
with Path(c14n_filename).expanduser().open(encoding="utf-8") as f:
|
||||
genres_tree = yaml.safe_load(f)
|
||||
flatten_func(genres_tree, [], c14n_branches)
|
||||
return c14n_branches, canonicalize
|
||||
Loading…
Reference in a new issue