mirror of
https://github.com/beetbox/beets.git
synced 2026-02-18 05:17:31 +01:00
Adapt code to fully typed confuse library
This commit is contained in:
parent
942638ae28
commit
37e18fbb46
11 changed files with 42 additions and 41 deletions
|
|
@ -37,11 +37,11 @@ class IncludeLazyConfig(confuse.LazyConfig):
|
|||
YAML files specified in an `include` setting.
|
||||
"""
|
||||
|
||||
def read(self, user=True, defaults=True):
|
||||
def read(self, user: bool = True, defaults: bool = True) -> None:
|
||||
super().read(user, defaults)
|
||||
|
||||
try:
|
||||
for view in self["include"]:
|
||||
for view in self["include"].sequence():
|
||||
self.set_file(view.as_filename())
|
||||
except confuse.NotFoundError:
|
||||
pass
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ from beets.util.deprecation import deprecate_for_maintainers, deprecate_for_user
|
|||
if TYPE_CHECKING:
|
||||
from collections.abc import Callable, Iterable, Iterator, Sequence
|
||||
|
||||
from confuse import ConfigView
|
||||
from confuse import Subview
|
||||
|
||||
from beets.dbcore import Query
|
||||
from beets.dbcore.db import FieldQueryType
|
||||
|
|
@ -162,7 +162,7 @@ class BeetsPlugin(metaclass=BeetsPluginMeta):
|
|||
album_template_fields: TFuncMap[Album]
|
||||
|
||||
name: str
|
||||
config: ConfigView
|
||||
config: Subview
|
||||
early_import_stages: list[ImportStageFunc]
|
||||
import_stages: list[ImportStageFunc]
|
||||
|
||||
|
|
|
|||
|
|
@ -30,7 +30,6 @@ import textwrap
|
|||
import traceback
|
||||
from difflib import SequenceMatcher
|
||||
from functools import cache
|
||||
from itertools import chain
|
||||
from typing import TYPE_CHECKING, Any, Literal
|
||||
|
||||
import confuse
|
||||
|
|
@ -551,18 +550,20 @@ def get_color_config() -> dict[ColorName, str]:
|
|||
legacy single-color format. Validates all color names against known codes
|
||||
and raises an error for any invalid entries.
|
||||
"""
|
||||
colors_by_color_name: dict[ColorName, list[str]] = {
|
||||
k: (v if isinstance(v, list) else LEGACY_COLORS.get(v, [v]))
|
||||
for k, v in config["ui"]["colors"].flatten().items()
|
||||
}
|
||||
|
||||
if invalid_colors := (
|
||||
set(chain.from_iterable(colors_by_color_name.values()))
|
||||
- CODE_BY_COLOR.keys()
|
||||
):
|
||||
raise UserError(
|
||||
f"Invalid color(s) in configuration: {', '.join(invalid_colors)}"
|
||||
template_dict: dict[ColorName, confuse.OneOf[str | list[str]]] = {
|
||||
n: confuse.OneOf(
|
||||
[
|
||||
confuse.Choice(sorted(LEGACY_COLORS)),
|
||||
confuse.Sequence(confuse.Choice(sorted(CODE_BY_COLOR))),
|
||||
]
|
||||
)
|
||||
for n in ColorName.__args__ # type: ignore[attr-defined]
|
||||
}
|
||||
template = confuse.MappingTemplate(template_dict)
|
||||
colors_by_color_name = {
|
||||
k: (v if isinstance(v, list) else LEGACY_COLORS.get(v, [v]))
|
||||
for k, v in config["ui"]["colors"].get(template).items()
|
||||
}
|
||||
|
||||
return {
|
||||
n: ";".join(str(CODE_BY_COLOR[c]) for c in colors)
|
||||
|
|
|
|||
|
|
@ -327,7 +327,7 @@ def summarize_items(items, singleton):
|
|||
return ", ".join(summary_parts)
|
||||
|
||||
|
||||
def _summary_judgment(rec):
|
||||
def _summary_judgment(rec: Recommendation) -> importer.Action | None:
|
||||
"""Determines whether a decision should be made without even asking
|
||||
the user. This occurs in quiet mode and when an action is chosen for
|
||||
NONE recommendations. Return None if the user should be queried.
|
||||
|
|
@ -335,6 +335,7 @@ def _summary_judgment(rec):
|
|||
summary judgment is made.
|
||||
"""
|
||||
|
||||
action: importer.Action | None
|
||||
if config["import"]["quiet"]:
|
||||
if rec == Recommendation.strong:
|
||||
return importer.Action.APPLY
|
||||
|
|
|
|||
|
|
@ -355,10 +355,9 @@ class DiscogsPlugin(MetadataSourcePlugin):
|
|||
style = self.format(result.data.get("styles"))
|
||||
base_genre = self.format(result.data.get("genres"))
|
||||
|
||||
if self.config["append_style_genre"] and style:
|
||||
genre = self.config["separator"].as_str().join([base_genre, style])
|
||||
else:
|
||||
genre = base_genre
|
||||
genre = base_genre
|
||||
if self.config["append_style_genre"] and genre is not None and style:
|
||||
genre += f"{self.config['separator'].as_str()}{style}"
|
||||
|
||||
discogs_albumid = self._extract_id(result.data.get("uri"))
|
||||
|
||||
|
|
|
|||
|
|
@ -288,7 +288,8 @@ class Candidate:
|
|||
elif check == ImageAction.REFORMAT:
|
||||
self.path = ArtResizer.shared.reformat(
|
||||
self.path,
|
||||
plugin.cover_format,
|
||||
# TODO: fix this gnarly logic to remove the need for type ignore
|
||||
plugin.cover_format, # type: ignore[arg-type]
|
||||
deinterlaced=plugin.deinterlace,
|
||||
)
|
||||
|
||||
|
|
@ -1367,7 +1368,7 @@ class FetchArtPlugin(plugins.BeetsPlugin, RequestMixin):
|
|||
|
||||
# allow both pixel and percentage-based margin specifications
|
||||
self.enforce_ratio = self.config["enforce_ratio"].get(
|
||||
confuse.OneOf(
|
||||
confuse.OneOf[bool | str](
|
||||
[
|
||||
bool,
|
||||
confuse.String(pattern=self.PAT_PX),
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@ if TYPE_CHECKING:
|
|||
import optparse
|
||||
from collections.abc import Callable
|
||||
|
||||
from beets.importer import ImportSession, ImportTask
|
||||
from beets.library import LibModel
|
||||
|
||||
LASTFM = pylast.LastFMNetwork(api_key=plugins.LASTFM_KEY)
|
||||
|
|
@ -178,14 +179,13 @@ class LastGenrePlugin(plugins.BeetsPlugin):
|
|||
"""A tuple of allowed genre sources. May contain 'track',
|
||||
'album', or 'artist.'
|
||||
"""
|
||||
source = self.config["source"].as_choice(("track", "album", "artist"))
|
||||
if source == "track":
|
||||
return "track", "album", "artist"
|
||||
if source == "album":
|
||||
return "album", "artist"
|
||||
if source == "artist":
|
||||
return ("artist",)
|
||||
return tuple()
|
||||
return self.config["source"].as_choice(
|
||||
{
|
||||
"track": ("track", "album", "artist"),
|
||||
"album": ("album", "artist"),
|
||||
"artist": ("artist",),
|
||||
}
|
||||
)
|
||||
|
||||
# More canonicalization and general helpers.
|
||||
|
||||
|
|
@ -603,10 +603,8 @@ class LastGenrePlugin(plugins.BeetsPlugin):
|
|||
lastgenre_cmd.func = lastgenre_func
|
||||
return [lastgenre_cmd]
|
||||
|
||||
def imported(
|
||||
self, session: library.Session, task: library.ImportTask
|
||||
) -> None:
|
||||
self._process(task.album if task.is_album else task.item, write=False)
|
||||
def imported(self, _: ImportSession, task: ImportTask) -> None:
|
||||
self._process(task.album if task.is_album else task.item, write=False) # type: ignore[attr-defined]
|
||||
|
||||
def _tags_for(
|
||||
self,
|
||||
|
|
|
|||
|
|
@ -358,7 +358,7 @@ class LRCLib(Backend):
|
|||
for group in self.fetch_candidates(artist, title, album, length):
|
||||
candidates = [evaluate_item(item) for item in group]
|
||||
if item := self.pick_best_match(candidates):
|
||||
lyrics = item.get_text(self.config["synced"])
|
||||
lyrics = item.get_text(self.config["synced"].get(bool))
|
||||
return lyrics, f"{self.GET_URL}/{item.id}"
|
||||
|
||||
return None
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ class PlaylistQuery(InQuery[bytes]):
|
|||
relative_to = os.path.dirname(playlist_path)
|
||||
else:
|
||||
relative_to = config["relative_to"].as_filename()
|
||||
relative_to = beets.util.bytestring_path(relative_to)
|
||||
relative_to_bytes = beets.util.bytestring_path(relative_to)
|
||||
|
||||
for line in f:
|
||||
if line[0] == "#":
|
||||
|
|
@ -78,7 +78,7 @@ class PlaylistQuery(InQuery[bytes]):
|
|||
|
||||
paths.append(
|
||||
beets.util.normpath(
|
||||
os.path.join(relative_to, line.rstrip())
|
||||
os.path.join(relative_to_bytes, line.rstrip())
|
||||
)
|
||||
)
|
||||
f.close()
|
||||
|
|
|
|||
|
|
@ -262,8 +262,9 @@ class SmartPlaylistPlugin(BeetsPlugin):
|
|||
"Updating {} smart playlists...", len(self._matched_playlists)
|
||||
)
|
||||
|
||||
playlist_dir = self.config["playlist_dir"].as_filename()
|
||||
playlist_dir = bytestring_path(playlist_dir)
|
||||
playlist_dir = bytestring_path(
|
||||
self.config["playlist_dir"].as_filename()
|
||||
)
|
||||
tpl = self.config["uri_format"].get()
|
||||
prefix = bytestring_path(self.config["prefix"].as_str())
|
||||
relative_to = self.config["relative_to"].get()
|
||||
|
|
|
|||
|
|
@ -104,7 +104,7 @@ class TitlecasePlugin(BeetsPlugin):
|
|||
|
||||
@cached_property
|
||||
def replace(self) -> list[tuple[str, str]]:
|
||||
return self.config["replace"].as_pairs()
|
||||
return self.config["replace"].as_pairs(default_value="")
|
||||
|
||||
@cached_property
|
||||
def the_artist(self) -> bool:
|
||||
|
|
|
|||
Loading…
Reference in a new issue