Skip to content

Commit 4344896

Browse files
authored
Merge branch 'master' into fix-replace-command-args
2 parents bd13fe6 + f63585f commit 4344896

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

71 files changed

+5725
-2403
lines changed

.git-blame-ignore-revs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,10 @@ f36bc497c8c8f89004f3f6879908d3f0b25123e1
4949
c490ac5810b70f3cf5fd8649669838e8fdb19f4d
5050
# Importer restructure
5151
9147577b2b19f43ca827e9650261a86fb0450cef
52+
# Move functionality under MusicBrainz plugin
53+
529aaac7dced71266c6d69866748a7d044ec20ff
54+
# musicbrainz: reorder methods
55+
5dc6f45110b99f0cc8dbb94251f9b1f6d69583fa
5256
# Copy paste query, types from library to dbcore
5357
1a045c91668c771686f4c871c84f1680af2e944b
5458
# Library restructure (split library.py into multiple modules)
@@ -81,3 +85,5 @@ d93ddf8dd43e4f9ed072a03829e287c78d2570a2
8185
a59e41a88365e414db3282658d2aa456e0b3468a
8286
# pyupgrade Python 3.10
8387
301637a1609831947cb5dd90270ed46c24b1ab1b
88+
# Fix changelog formatting
89+
658b184c59388635787b447983ecd3a575f4fe56

beets/autotag/__init__.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
from .match import Proposal, Recommendation, tag_album, tag_item
3030

3131
if TYPE_CHECKING:
32-
from collections.abc import Mapping, Sequence
32+
from collections.abc import Sequence
3333

3434
from beets.library import Album, Item, LibModel
3535

@@ -204,11 +204,11 @@ def apply_album_metadata(album_info: AlbumInfo, album: Album):
204204
correct_list_fields(album)
205205

206206

207-
def apply_metadata(album_info: AlbumInfo, mapping: Mapping[Item, TrackInfo]):
208-
"""Set the items' metadata to match an AlbumInfo object using a
209-
mapping from Items to TrackInfo objects.
210-
"""
211-
for item, track_info in mapping.items():
207+
def apply_metadata(
208+
album_info: AlbumInfo, item_info_pairs: list[tuple[Item, TrackInfo]]
209+
):
210+
"""Set items metadata to match corresponding tagged info."""
211+
for item, track_info in item_info_pairs:
212212
# Artist or artist credit.
213213
if config["artist_credit"]:
214214
item.artist = (

beets/autotag/distance.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -422,7 +422,7 @@ def track_distance(
422422
def distance(
423423
items: Sequence[Item],
424424
album_info: AlbumInfo,
425-
mapping: dict[Item, TrackInfo],
425+
item_info_pairs: list[tuple[Item, TrackInfo]],
426426
) -> Distance:
427427
"""Determines how "significant" an album metadata change would be.
428428
Returns a Distance object. `album_info` is an AlbumInfo object
@@ -518,16 +518,16 @@ def distance(
518518

519519
# Tracks.
520520
dist.tracks = {}
521-
for item, track in mapping.items():
521+
for item, track in item_info_pairs:
522522
dist.tracks[track] = track_distance(item, track, album_info.va)
523523
dist.add("tracks", dist.tracks[track].distance)
524524

525525
# Missing tracks.
526-
for _ in range(len(album_info.tracks) - len(mapping)):
526+
for _ in range(len(album_info.tracks) - len(item_info_pairs)):
527527
dist.add("missing_tracks", 1.0)
528528

529529
# Unmatched tracks.
530-
for _ in range(len(items) - len(mapping)):
530+
for _ in range(len(items) - len(item_info_pairs)):
531531
dist.add("unmatched_tracks", 1.0)
532532

533533
dist.add_data_source(likelies["data_source"], album_info.data_source)

beets/autotag/hooks.py

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,14 @@
1717
from __future__ import annotations
1818

1919
from copy import deepcopy
20-
from typing import TYPE_CHECKING, Any, NamedTuple, TypeVar
20+
from dataclasses import dataclass
21+
from functools import cached_property
22+
from typing import TYPE_CHECKING, Any, TypeVar
2123

2224
from typing_extensions import Self
2325

26+
from beets.util import cached_classproperty
27+
2428
if TYPE_CHECKING:
2529
from beets.library import Item
2630

@@ -54,6 +58,10 @@ def __hash__(self) -> int: # type: ignore[override]
5458
class Info(AttrDict[Any]):
5559
"""Container for metadata about a musical entity."""
5660

61+
@cached_property
62+
def name(self) -> str:
63+
raise NotImplementedError
64+
5765
def __init__(
5866
self,
5967
album: str | None = None,
@@ -95,6 +103,10 @@ class AlbumInfo(Info):
95103
user items, and later to drive tagging decisions once selected.
96104
"""
97105

106+
@cached_property
107+
def name(self) -> str:
108+
return self.album or ""
109+
98110
def __init__(
99111
self,
100112
tracks: list[TrackInfo],
@@ -167,6 +179,10 @@ class TrackInfo(Info):
167179
stand alone for singleton matching.
168180
"""
169181

182+
@cached_property
183+
def name(self) -> str:
184+
return self.title or ""
185+
170186
def __init__(
171187
self,
172188
*,
@@ -214,16 +230,32 @@ def __init__(
214230

215231

216232
# Structures that compose all the information for a candidate match.
233+
@dataclass
234+
class Match:
235+
distance: Distance
236+
info: Info
217237

238+
@cached_classproperty
239+
def type(cls) -> str:
240+
return cls.__name__.removesuffix("Match") # type: ignore[attr-defined]
218241

219-
class AlbumMatch(NamedTuple):
220-
distance: Distance
242+
243+
@dataclass
244+
class AlbumMatch(Match):
221245
info: AlbumInfo
222246
mapping: dict[Item, TrackInfo]
223247
extra_items: list[Item]
224248
extra_tracks: list[TrackInfo]
225249

250+
@property
251+
def item_info_pairs(self) -> list[tuple[Item, TrackInfo]]:
252+
return list(self.mapping.items())
226253

227-
class TrackMatch(NamedTuple):
228-
distance: Distance
254+
@property
255+
def items(self) -> list[Item]:
256+
return [i for i, _ in self.item_info_pairs]
257+
258+
259+
@dataclass
260+
class TrackMatch(Match):
229261
info: TrackInfo

beets/autotag/match.py

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ class Proposal(NamedTuple):
6969
def assign_items(
7070
items: Sequence[Item],
7171
tracks: Sequence[TrackInfo],
72-
) -> tuple[dict[Item, TrackInfo], list[Item], list[TrackInfo]]:
72+
) -> tuple[list[tuple[Item, TrackInfo]], list[Item], list[TrackInfo]]:
7373
"""Given a list of Items and a list of TrackInfo objects, find the
7474
best mapping between them. Returns a mapping from Items to TrackInfo
7575
objects, a set of extra Items, and a set of extra TrackInfo
@@ -95,7 +95,7 @@ def assign_items(
9595
extra_items.sort(key=lambda i: (i.disc, i.track, i.title))
9696
extra_tracks = list(set(tracks) - set(mapping.values()))
9797
extra_tracks.sort(key=lambda t: (t.index, t.title))
98-
return mapping, extra_items, extra_tracks
98+
return list(mapping.items()), extra_items, extra_tracks
9999

100100

101101
def match_by_id(items: Iterable[Item]) -> AlbumInfo | None:
@@ -217,10 +217,12 @@ def _add_candidate(
217217
return
218218

219219
# Find mapping between the items and the track info.
220-
mapping, extra_items, extra_tracks = assign_items(items, info.tracks)
220+
item_info_pairs, extra_items, extra_tracks = assign_items(
221+
items, info.tracks
222+
)
221223

222224
# Get the change distance.
223-
dist = distance(items, info, mapping)
225+
dist = distance(items, info, item_info_pairs)
224226

225227
# Skip matches with ignored penalties.
226228
penalties = [key for key, _ in dist]
@@ -232,14 +234,14 @@ def _add_candidate(
232234

233235
log.debug("Success. Distance: {}", dist)
234236
results[info.album_id] = hooks.AlbumMatch(
235-
dist, info, mapping, extra_items, extra_tracks
237+
dist, info, dict(item_info_pairs), extra_items, extra_tracks
236238
)
237239

238240

239241
def tag_album(
240242
items,
241243
search_artist: str | None = None,
242-
search_album: str | None = None,
244+
search_name: str | None = None,
243245
search_ids: list[str] = [],
244246
) -> tuple[str, str, Proposal]:
245247
"""Return a tuple of the current artist name, the current album
@@ -300,10 +302,10 @@ def tag_album(
300302
)
301303

302304
# Search terms.
303-
if not (search_artist and search_album):
305+
if not (search_artist and search_name):
304306
# No explicit search terms -- use current metadata.
305-
search_artist, search_album = cur_artist, cur_album
306-
log.debug("Search terms: {} - {}", search_artist, search_album)
307+
search_artist, search_name = cur_artist, cur_album
308+
log.debug("Search terms: {} - {}", search_artist, search_name)
307309

308310
# Is this album likely to be a "various artist" release?
309311
va_likely = (
@@ -315,7 +317,7 @@ def tag_album(
315317

316318
# Get the results from the data sources.
317319
for matched_candidate in metadata_plugins.candidates(
318-
items, search_artist, search_album, va_likely
320+
items, search_artist, search_name, va_likely
319321
):
320322
_add_candidate(items, candidates, matched_candidate)
321323
if opt_candidate := candidates.get(matched_candidate.album_id):
@@ -331,7 +333,7 @@ def tag_album(
331333
def tag_item(
332334
item,
333335
search_artist: str | None = None,
334-
search_title: str | None = None,
336+
search_name: str | None = None,
335337
search_ids: list[str] | None = None,
336338
) -> Proposal:
337339
"""Find metadata for a single track. Return a `Proposal` consisting
@@ -373,12 +375,12 @@ def tag_item(
373375

374376
# Search terms.
375377
search_artist = search_artist or item.artist
376-
search_title = search_title or item.title
377-
log.debug("Item search terms: {} - {}", search_artist, search_title)
378+
search_name = search_name or item.title
379+
log.debug("Item search terms: {} - {}", search_artist, search_name)
378380

379381
# Get and evaluate candidate metadata.
380382
for track_info in metadata_plugins.item_candidates(
381-
item, search_artist, search_title
383+
item, search_artist, search_name
382384
):
383385
dist = track_distance(item, track_info, incl_artist=True)
384386
candidates[track_info.track_id] = hooks.TrackMatch(dist, track_info)

0 commit comments

Comments
 (0)