Permalink
Comparing changes
Open a pull request
- 17 commits
- 8 files changed
- 0 commit comments
- 1 contributor
Unified
Split
Showing
with
145 additions
and 206 deletions.
- +1 −1 beets/autotag/__init__.py
- +20 −12 beets/autotag/match.py
- +7 −10 beets/importer.py
- +111 −162 beets/ui/commands.py
- +1 −1 beetsplug/acousticbrainz.py
- +2 −0 docs/changelog.rst
- +3 −5 docs/dev/plugins.rst
- +0 −15 test/test_ui.py
| @@ -23,7 +23,7 @@ | ||
| # Parts of external interface. | ||
| from .hooks import AlbumInfo, TrackInfo, AlbumMatch, TrackMatch # noqa | ||
| from .match import tag_item, tag_album # noqa | ||
| from .match import tag_item, tag_album, Proposal # noqa | ||
| from .match import Recommendation # noqa | ||
| # Global logger. | ||
| @@ -22,6 +22,7 @@ | ||
| import datetime | ||
| import re | ||
| from munkres import Munkres | ||
| from collections import namedtuple | ||
| from beets import logging | ||
| from beets import plugins | ||
| @@ -52,6 +53,13 @@ class Recommendation(OrderedEnum): | ||
| strong = 3 | ||
| # A structure for holding a set of possible matches to choose between. This | ||
| # consists of a list of possible candidates (i.e., AlbumInfo or TrackInfo | ||
| # objects) and a recommendation value. | ||
| Proposal = namedtuple('Proposal', ('candidates', 'recommendation')) | ||
| # Primary matching functionality. | ||
| def current_metadata(items): | ||
| @@ -379,9 +387,8 @@ def _add_candidate(items, results, info): | ||
| def tag_album(items, search_artist=None, search_album=None, | ||
| search_ids=[]): | ||
| """Return a tuple of a artist name, an album name, a list of | ||
| `AlbumMatch` candidates from the metadata backend, and a | ||
| `Recommendation`. | ||
| """Return a tuple of the current artist name, the current album | ||
| name, and a `Proposal` containing `AlbumMatch` candidates. | ||
| The artist and album are the most common values of these fields | ||
| among `items`. | ||
| @@ -429,7 +436,7 @@ def tag_album(items, search_artist=None, search_album=None, | ||
| if rec == Recommendation.strong: | ||
| log.debug(u'ID match.') | ||
| return cur_artist, cur_album, \ | ||
| list(candidates.values()), rec | ||
| Proposal(list(candidates.values()), rec) | ||
| # Search terms. | ||
| if not (search_artist and search_album): | ||
| @@ -454,14 +461,15 @@ def tag_album(items, search_artist=None, search_album=None, | ||
| # Sort and get the recommendation. | ||
| candidates = _sort_candidates(candidates.values()) | ||
| rec = _recommendation(candidates) | ||
| return cur_artist, cur_album, candidates, rec | ||
| return cur_artist, cur_album, Proposal(candidates, rec) | ||
| def tag_item(item, search_artist=None, search_title=None, | ||
| search_ids=[]): | ||
| """Attempts to find metadata for a single track. Returns a | ||
| `(candidates, recommendation)` pair where `candidates` is a list of | ||
| TrackMatch objects. `search_artist` and `search_title` may be used | ||
| """Find metadata for a single track. Return a `Proposal` consisting | ||
| of `TrackMatch` objects. | ||
| `search_artist` and `search_title` may be used | ||
| to override the current metadata for the purposes of the MusicBrainz | ||
| title. `search_ids` may be used for restricting the search to a list | ||
| of metadata backend IDs. | ||
| @@ -484,14 +492,14 @@ def tag_item(item, search_artist=None, search_title=None, | ||
| if rec == Recommendation.strong and \ | ||
| not config['import']['timid']: | ||
| log.debug(u'Track ID match.') | ||
| return _sort_candidates(candidates.values()), rec | ||
| return Proposal(_sort_candidates(candidates.values()), rec) | ||
| # If we're searching by ID, don't proceed. | ||
| if search_ids: | ||
| if candidates: | ||
| return _sort_candidates(candidates.values()), rec | ||
| return Proposal(_sort_candidates(candidates.values()), rec) | ||
| else: | ||
| return [], Recommendation.none | ||
| return Proposal([], Recommendation.none) | ||
| # Search terms. | ||
| if not (search_artist and search_title): | ||
| @@ -507,4 +515,4 @@ def tag_item(item, search_artist=None, search_title=None, | ||
| log.debug(u'Found {0} candidates.', len(candidates)) | ||
| candidates = _sort_candidates(candidates.values()) | ||
| rec = _recommendation(candidates) | ||
| return candidates, rec | ||
| return Proposal(candidates, rec) | ||
| @@ -43,8 +43,7 @@ | ||
| from beets import mediafile | ||
| action = Enum('action', | ||
| ['SKIP', 'ASIS', 'TRACKS', 'MANUAL', 'APPLY', 'MANUAL_ID', | ||
| 'ALBUMS', 'RETAG']) | ||
| ['SKIP', 'ASIS', 'TRACKS', 'APPLY', 'ALBUMS', 'RETAG']) | ||
| # The RETAG action represents "don't apply any match, but do record | ||
| # new metadata". It's not reachable via the standard command prompt but | ||
| # can be used by plugins. | ||
| @@ -443,7 +442,6 @@ def set_choice(self, choice): | ||
| indicates that an action has been selected for this task. | ||
| """ | ||
| # Not part of the task structure: | ||
| assert choice not in (action.MANUAL, action.MANUAL_ID) | ||
| assert choice != action.APPLY # Only used internally. | ||
| if choice in (action.SKIP, action.ASIS, action.TRACKS, action.ALBUMS, | ||
| action.RETAG): | ||
| @@ -587,12 +585,12 @@ def lookup_candidates(self): | ||
| candidate IDs are stored in self.search_ids: if present, the | ||
| initial lookup is restricted to only those IDs. | ||
| """ | ||
| artist, album, candidates, recommendation = \ | ||
| artist, album, prop = \ | ||
| autotag.tag_album(self.items, search_ids=self.search_ids) | ||
| self.cur_artist = artist | ||
| self.cur_album = album | ||
| self.candidates = candidates | ||
| self.rec = recommendation | ||
| self.candidates = prop.candidates | ||
| self.rec = prop.recommendation | ||
| def find_duplicates(self, lib): | ||
| """Return a list of albums from `lib` with the same artist and | ||
| @@ -830,10 +828,9 @@ def _emit_imported(self, lib): | ||
| plugins.send('item_imported', lib=lib, item=item) | ||
| def lookup_candidates(self): | ||
| candidates, recommendation = autotag.tag_item( | ||
| self.item, search_ids=self.search_ids) | ||
| self.candidates = candidates | ||
| self.rec = recommendation | ||
| prop = autotag.tag_item(self.item, search_ids=self.search_ids) | ||
| self.candidates = prop.candidates | ||
| self.rec = prop.recommendation | ||
| def find_duplicates(self, lib): | ||
| """Return a list of items from `lib` that have the same artist | ||
Oops, something went wrong.