Skip to content

Commit 26bfd75

Browse files
committed
hooks: make AlbumMatch.mapping a tuple
1 parent 07445fd commit 26bfd75

File tree

12 files changed

+64
-51
lines changed

12 files changed

+64
-51
lines changed

beets/autotag/__init__.py

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

3232
if TYPE_CHECKING:
33-
from collections.abc import Mapping, Sequence
33+
from collections.abc import Sequence
3434

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

@@ -210,11 +210,11 @@ def apply_album_metadata(album_info: AlbumInfo, album: Album):
210210
correct_list_fields(album)
211211

212212

213-
def apply_metadata(album_info: AlbumInfo, mapping: Mapping[Item, TrackInfo]):
214-
"""Set the items' metadata to match an AlbumInfo object using a
215-
mapping from Items to TrackInfo objects.
216-
"""
217-
for item, track_info in mapping.items():
213+
def apply_metadata(
214+
album_info: AlbumInfo, item_info_pairs: list[tuple[Item, TrackInfo]]
215+
):
216+
"""Set items metadata to match corresponding tagged info."""
217+
for item, track_info in item_info_pairs:
218218
# Artist or artist credit.
219219
if config["artist_credit"]:
220220
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: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,14 @@ class AlbumMatch(NamedTuple):
223223
extra_items: list[Item]
224224
extra_tracks: list[TrackInfo]
225225

226+
@property
227+
def item_info_pairs(self) -> list[tuple[Item, TrackInfo]]:
228+
return list(self.mapping.items())
229+
230+
@property
231+
def items(self) -> list[Item]:
232+
return [i for i, _ in self.item_info_pairs]
233+
226234

227235
class TrackMatch(NamedTuple):
228236
distance: Distance

beets/autotag/match.py

Lines changed: 13 additions & 10 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
@@ -86,16 +86,17 @@ def assign_items(
8686
# Each item in `assigned_item_idxs` list corresponds to a track in the
8787
# `tracks` list. Each value is either an index into the assigned item in
8888
# `items` list, or -1 if that track has no match.
89-
mapping = {
90-
items[iidx]: t
89+
item_info_pairs = [
90+
(items[iidx], t)
9191
for iidx, t in zip(assigned_item_idxs, tracks)
9292
if iidx != -1
93-
}
94-
extra_items = list(set(items) - mapping.keys())
93+
]
94+
item_info_pairs.sort(key=lambda it: (it[0].disc, it[0].track, it[0].title))
95+
extra_items = list(set(items) - {i for i, _ in item_info_pairs})
9596
extra_items.sort(key=lambda i: (i.disc, i.track, i.title))
96-
extra_tracks = list(set(tracks) - set(mapping.values()))
97+
extra_tracks = list(set(tracks) - {t for _, t in item_info_pairs})
9798
extra_tracks.sort(key=lambda t: (t.index, t.title))
98-
return mapping, extra_items, extra_tracks
99+
return item_info_pairs, extra_items, extra_tracks
99100

100101

101102
def match_by_id(items: Iterable[Item]) -> AlbumInfo | None:
@@ -217,10 +218,12 @@ def _add_candidate(
217218
return
218219

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

222225
# Get the change distance.
223-
dist = distance(items, info, mapping)
226+
dist = distance(items, info, item_info_pairs)
224227

225228
# Skip matches with ignored penalties.
226229
penalties = [key for key, _ in dist]
@@ -232,7 +235,7 @@ def _add_candidate(
232235

233236
log.debug("Success. Distance: {}", dist)
234237
results[info.album_id] = hooks.AlbumMatch(
235-
dist, info, mapping, extra_items, extra_tracks
238+
dist, info, dict(item_info_pairs), extra_items, extra_tracks
236239
)
237240

238241

beets/importer/tasks.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -245,21 +245,21 @@ def imported_items(self):
245245
matched items.
246246
"""
247247
if self.choice_flag in (Action.ASIS, Action.RETAG):
248-
return list(self.items)
248+
return self.items
249249
elif self.choice_flag == Action.APPLY and isinstance(
250250
self.match, autotag.AlbumMatch
251251
):
252-
return list(self.match.mapping.keys())
252+
return self.match.items
253253
else:
254254
assert False
255255

256256
def apply_metadata(self):
257257
"""Copy metadata from match info to the items."""
258258
if config["import"]["from_scratch"]:
259-
for item in self.match.mapping:
259+
for item in self.match.items:
260260
item.clear()
261261

262-
autotag.apply_metadata(self.match.info, self.match.mapping)
262+
autotag.apply_metadata(self.match.info, self.match.item_info_pairs)
263263

264264
def duplicate_items(self, lib: library.Library):
265265
duplicate_items = []

beets/ui/commands/import_/display.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -373,8 +373,9 @@ def show_match_tracks(self):
373373
# Tracks.
374374
# match is an AlbumMatch NamedTuple, mapping is a dict
375375
# Sort the pairs by the track_info index (at index 1 of the NamedTuple)
376-
pairs = list(self.match.mapping.items())
377-
pairs.sort(key=lambda item_and_track_info: item_and_track_info[1].index)
376+
pairs = sorted(
377+
self.match.item_info_pairs, key=lambda pair: pair[1].index
378+
)
378379
# Build up LHS and RHS for track difference display. The `lines` list
379380
# contains `(left, right)` tuples.
380381
lines = []

beetsplug/bpsync.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -149,14 +149,14 @@ def albums(self, lib, query, move, pretend, write):
149149
library_trackid_to_item = {
150150
int(item.mb_trackid): item for item in items
151151
}
152-
item_to_trackinfo = {
153-
item: beatport_trackid_to_trackinfo[track_id]
152+
item_info_pairs = [
153+
(item, beatport_trackid_to_trackinfo[track_id])
154154
for track_id, item in library_trackid_to_item.items()
155-
}
155+
]
156156

157157
self._log.info("applying changes to {}", album)
158158
with lib.transaction():
159-
autotag.apply_metadata(albuminfo, item_to_trackinfo)
159+
autotag.apply_metadata(albuminfo, item_info_pairs)
160160
changed = False
161161
# Find any changed item to apply Beatport changes to album.
162162
any_changed_item = items[0]

beetsplug/mbpseudo.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -278,11 +278,8 @@ def _adjust_final_album_match(self, match: AlbumMatch):
278278
album_info.album_id,
279279
)
280280
album_info.use_pseudo_as_ref()
281-
mapping = match.mapping
282-
new_mappings, _, _ = assign_items(
283-
list(mapping.keys()), album_info.tracks
284-
)
285-
mapping.update(new_mappings)
281+
new_pairs, *_ = assign_items(match.items, album_info.tracks)
282+
album_info.mapping = dict(new_pairs)
286283

287284
if album_info.data_source == self.data_source:
288285
album_info.data_source = "MusicBrainz"

beetsplug/mbsync.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -121,18 +121,20 @@ def albums(self, lib, query, move, pretend, write):
121121
# Construct a track mapping according to MBIDs (release track MBIDs
122122
# first, if available, and recording MBIDs otherwise). This should
123123
# work for albums that have missing or extra tracks.
124-
mapping = {}
124+
item_info_pairs = []
125125
items = list(album.items())
126126
for item in items:
127127
if (
128128
item.mb_releasetrackid
129129
and item.mb_releasetrackid in releasetrack_index
130130
):
131-
mapping[item] = releasetrack_index[item.mb_releasetrackid]
131+
item_info_pairs.append(
132+
(item, releasetrack_index[item.mb_releasetrackid])
133+
)
132134
else:
133135
candidates = track_index[item.mb_trackid]
134136
if len(candidates) == 1:
135-
mapping[item] = candidates[0]
137+
item_info_pairs.append((item, candidates[0]))
136138
else:
137139
# If there are multiple copies of a recording, they are
138140
# disambiguated using their disc and track number.
@@ -141,13 +143,13 @@ def albums(self, lib, query, move, pretend, write):
141143
c.medium_index == item.track
142144
and c.medium == item.disc
143145
):
144-
mapping[item] = c
146+
item_info_pairs.append((item, c))
145147
break
146148

147149
# Apply.
148150
self._log.debug("applying changes to {}", album)
149151
with lib.transaction():
150-
autotag.apply_metadata(album_info, mapping)
152+
autotag.apply_metadata(album_info, item_info_pairs)
151153
changed = False
152154
# Find any changed item to apply changes to album.
153155
any_changed_item = items[0]

test/autotag/test_distance.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ def items(self):
182182
@pytest.fixture
183183
def get_dist(self, items):
184184
def inner(info: AlbumInfo):
185-
return distance(items, info, dict(zip(items, info.tracks)))
185+
return distance(items, info, list(zip(items, info.tracks)))
186186

187187
return inner
188188

0 commit comments

Comments
 (0)