def resolve_duplicate(task, config): """Decide what to do when a new album or item seems similar to one that's already in the library. """ log.warn("This %s is already in the library!" % ("album" if task.is_album else "item")) if config.quiet: # In quiet mode, don't prompt -- just skip. log.info('Skipping.') sel = 's' else: sel = ui.input_options( ('Skip new', 'Keep both', 'Remove old'), color=config.color ) if sel == 's': # Skip new. task.set_choice(importer.action.SKIP) elif sel == 'k': # Keep both. Do nothing; leave the choice intact. pass elif sel == 'r': # Remove old. task.remove_duplicates = True else: assert False
def choose_candidate(candidates, singleton, rec, color, timid, cur_artist=None, cur_album=None, item=None, itemcount=None, per_disc_numbering=False): """Given a sorted list of candidates, ask the user for a selection of which candidate to use. Applies to both full albums and singletons (tracks). Candidates are either AlbumMatch or TrackMatch objects depending on `singleton`. for albums, `cur_artist`, `cur_album`, and `itemcount` must be provided. For singletons, `item` must be provided. Returns the result of the choice, which may SKIP, ASIS, TRACKS, or MANUAL or a candidate (an AlbumMatch/TrackMatch object). """ # Sanity check. if singleton: assert item is not None else: assert cur_artist is not None assert cur_album is not None # Zero candidates. if not candidates: if singleton: print_("No matching recordings found.") opts = ('Use as-is', 'Skip', 'Enter search', 'enter Id', 'aBort') else: print_("No matching release found for {0} tracks." .format(itemcount)) print_('For help, see: ' 'https://github.com/sampsyo/beets/wiki/FAQ#wiki-nomatch') opts = ('Use as-is', 'as Tracks', 'Skip', 'Enter search', 'enter Id', 'aBort') sel = ui.input_options(opts, color=color) if sel == 'u': return importer.action.ASIS elif sel == 't': assert not singleton return importer.action.TRACKS elif sel == 'e': return importer.action.MANUAL elif sel == 's': return importer.action.SKIP elif sel == 'b': raise importer.ImportAbort() elif sel == 'i': return importer.action.MANUAL_ID else: assert False # Is the change good enough? bypass_candidates = False if rec != autotag.RECOMMEND_NONE: match = candidates[0] bypass_candidates = True while True: # Display and choose from candidates. if not bypass_candidates: # Display list of candidates. if singleton: print_('Finding tags for track "%s - %s".' % (item.artist, item.title)) print_('Candidates:') for i, match in enumerate(candidates): print_('%i. %s - %s (%s)' % (i + 1, match.info.artist, match.info.title, dist_string(match.distance, color))) else: print_('Finding tags for album "%s - %s".' % (cur_artist, cur_album)) print_('Candidates:') for i, match in enumerate(candidates): line = '%i. %s - %s' % (i + 1, match.info.artist, match.info.album) # Label and year disambiguation, if available. label, year = None, None if match.info.label: label = match.info.label if match.info.year: year = unicode(match.info.year) if label and year: line += u' [%s, %s]' % (label, year) elif label: line += u' [%s]' % label elif year: line += u' [%s]' % year line += ' (%s)' % dist_string(match.distance, color) # Point out the partial matches. if match.extra_items or match.extra_tracks: warning = PARTIAL_MATCH_MESSAGE if color: warning = ui.colorize('yellow', warning) line += u' %s' % warning print_(line) # Ask the user for a choice. if singleton: opts = ('Skip', 'Use as-is', 'Enter search', 'enter Id', 'aBort') else: opts = ('Skip', 'Use as-is', 'as Tracks', 'Enter search', 'enter Id', 'aBort') sel = ui.input_options(opts, numrange=(1, len(candidates)), color=color) if sel == 's': return importer.action.SKIP elif sel == 'u': return importer.action.ASIS elif sel == 'e': return importer.action.MANUAL elif sel == 't': assert not singleton return importer.action.TRACKS elif sel == 'b': raise importer.ImportAbort() elif sel == 'i': return importer.action.MANUAL_ID else: # Numerical selection. if singleton: match = candidates[sel - 1] else: match = candidates[sel - 1] bypass_candidates = False # Show what we're about to do. if singleton: show_item_change(item, match, color) else: show_change(cur_artist, cur_album, match, color, per_disc_numbering) # Exact match => tag automatically if we're not in timid mode. if rec == autotag.RECOMMEND_STRONG and not timid: return match # Ask for confirmation. if singleton: opts = ('Apply', 'More candidates', 'Skip', 'Use as-is', 'Enter search', 'enter Id', 'aBort') else: opts = ('Apply', 'More candidates', 'Skip', 'Use as-is', 'as Tracks', 'Enter search', 'enter Id', 'aBort') sel = ui.input_options(opts, color=color) if sel == 'a': return match elif sel == 'm': pass elif sel == 's': return importer.action.SKIP elif sel == 'u': return importer.action.ASIS elif sel == 't': assert not singleton return importer.action.TRACKS elif sel == 'e': return importer.action.MANUAL elif sel == 'b': raise importer.ImportAbort() elif sel == 'i': return importer.action.MANUAL_ID
def choose_candidate(candidates, singleton, rec, color, timid, cur_artist=None, cur_album=None, item=None): """Given a sorted list of candidates, ask the user for a selection of which candidate to use. Applies to both full albums and singletons (tracks). For albums, the candidates are `(dist, items, info)` triples and `cur_artist` and `cur_album` must be provided. For singletons, the candidates are `(dist, info)` pairs and `item` must be provided. Returns the result of the choice, which may SKIP, ASIS, TRACKS, or MANUAL or a candidate. For albums, a candidate is a `(info, items)` pair; for items, it is just a TrackInfo object. """ # Sanity check. if singleton: assert item is not None else: assert cur_artist is not None assert cur_album is not None # Zero candidates. if not candidates: print_("No match found.") if singleton: opts = ('Use as-is', 'Skip', 'Enter search', 'enter Id', 'aBort') else: opts = ('Use as-is', 'as Tracks', 'Skip', 'Enter search', 'enter Id', 'aBort') sel = ui.input_options(opts, color=color) if sel == 'u': return importer.action.ASIS elif sel == 't': assert not singleton return importer.action.TRACKS elif sel == 'e': return importer.action.MANUAL elif sel == 's': return importer.action.SKIP elif sel == 'b': raise importer.ImportAbort() elif sel == 'i': return importer.action.MANUAL_ID else: assert False # Is the change good enough? bypass_candidates = False if rec != autotag.RECOMMEND_NONE: if singleton: dist, info = candidates[0] else: dist, items, info = candidates[0] bypass_candidates = True while True: # Display and choose from candidates. if not bypass_candidates: # Display list of candidates. if singleton: print_('Finding tags for track "%s - %s".' % (item.artist, item.title)) print_('Candidates:') for i, (dist, info) in enumerate(candidates): print_('%i. %s - %s (%s)' % (i+1, info.artist, info.title, dist_string(dist, color))) else: print_('Finding tags for album "%s - %s".' % (cur_artist, cur_album)) print_('Candidates:') for i, (dist, items, info) in enumerate(candidates): line = '%i. %s - %s' % (i+1, info.artist, info.album) # Label and year disambiguation, if available. label, year = None, None if info.label: label = info.label if info.year: year = unicode(info.year) if label and year: line += u' [%s, %s]' % (label, year) elif label: line += u' [%s]' % label elif year: line += u' [%s]' % year line += ' (%s)' % dist_string(dist, color) # Point out the partial matches. if None in items: warning = PARTIAL_MATCH_MESSAGE if color: warning = ui.colorize('yellow', warning) line += u' %s' % warning print_(line) # Ask the user for a choice. if singleton: opts = ('Skip', 'Use as-is', 'Enter search', 'enter Id', 'aBort') else: opts = ('Skip', 'Use as-is', 'as Tracks', 'Enter search', 'enter Id', 'aBort') sel = ui.input_options(opts, numrange=(1, len(candidates)), color=color) if sel == 's': return importer.action.SKIP elif sel == 'u': return importer.action.ASIS elif sel == 'e': return importer.action.MANUAL elif sel == 't': assert not singleton return importer.action.TRACKS elif sel == 'b': raise importer.ImportAbort() elif sel == 'i': return importer.action.MANUAL_ID else: # Numerical selection. if singleton: dist, info = candidates[sel-1] else: dist, items, info = candidates[sel-1] bypass_candidates = False # Show what we're about to do. if singleton: show_item_change(item, info, dist, color) else: show_change(cur_artist, cur_album, items, info, dist, color) # Exact match => tag automatically if we're not in timid mode. if rec == autotag.RECOMMEND_STRONG and not timid: if singleton: return info else: return info, items # Ask for confirmation. if singleton: opts = ('Apply', 'More candidates', 'Skip', 'Use as-is', 'Enter search', 'enter Id', 'aBort') else: opts = ('Apply', 'More candidates', 'Skip', 'Use as-is', 'as Tracks', 'Enter search', 'enter Id', 'aBort') sel = ui.input_options(opts, color=color) if sel == 'a': if singleton: return info else: return info, items elif sel == 'm': pass elif sel == 's': return importer.action.SKIP elif sel == 'u': return importer.action.ASIS elif sel == 't': assert not singleton return importer.action.TRACKS elif sel == 'e': return importer.action.MANUAL elif sel == 'b': raise importer.ImportAbort() elif sel == 'i': return importer.action.MANUAL_ID
def choose_candidate(candidates, singleton, rec, color, timid, cur_artist=None, cur_album=None, item=None, itemcount=None, per_disc_numbering=False): """Given a sorted list of candidates, ask the user for a selection of which candidate to use. Applies to both full albums and singletons (tracks). Candidates are either AlbumMatch or TrackMatch objects depending on `singleton`. for albums, `cur_artist`, `cur_album`, and `itemcount` must be provided. For singletons, `item` must be provided. Returns the result of the choice, which may SKIP, ASIS, TRACKS, or MANUAL or a candidate (an AlbumMatch/TrackMatch object). """ # Sanity check. if singleton: assert item is not None else: assert cur_artist is not None assert cur_album is not None # Zero candidates. if not candidates: if singleton: print_("No matching recordings found.") opts = ('Use as-is', 'Skip', 'Enter search', 'enter Id', 'aBort') else: print_( "No matching release found for {0} tracks.".format(itemcount)) print_('For help, see: ' 'https://github.com/sampsyo/beets/wiki/FAQ#wiki-nomatch') opts = ('Use as-is', 'as Tracks', 'Skip', 'Enter search', 'enter Id', 'aBort') sel = ui.input_options(opts, color=color) if sel == 'u': return importer.action.ASIS elif sel == 't': assert not singleton return importer.action.TRACKS elif sel == 'e': return importer.action.MANUAL elif sel == 's': return importer.action.SKIP elif sel == 'b': raise importer.ImportAbort() elif sel == 'i': return importer.action.MANUAL_ID else: assert False # Is the change good enough? bypass_candidates = False if rec != autotag.RECOMMEND_NONE: match = candidates[0] bypass_candidates = True while True: # Display and choose from candidates. if not bypass_candidates: # Display list of candidates. if singleton: print_('Finding tags for track "%s - %s".' % (item.artist, item.title)) print_('Candidates:') for i, match in enumerate(candidates): print_('%i. %s - %s (%s)' % (i + 1, match.info.artist, match.info.title, dist_string(match.distance, color))) else: print_('Finding tags for album "%s - %s".' % (cur_artist, cur_album)) print_('Candidates:') for i, match in enumerate(candidates): line = '%i. %s - %s' % (i + 1, match.info.artist, match.info.album) # Label and year disambiguation, if available. label, year = None, None if match.info.label: label = match.info.label if match.info.year: year = unicode(match.info.year) if label and year: line += u' [%s, %s]' % (label, year) elif label: line += u' [%s]' % label elif year: line += u' [%s]' % year line += ' (%s)' % dist_string(match.distance, color) # Point out the partial matches. if match.extra_items or match.extra_tracks: warning = PARTIAL_MATCH_MESSAGE if color: warning = ui.colorize('yellow', warning) line += u' %s' % warning print_(line) # Ask the user for a choice. if singleton: opts = ('Skip', 'Use as-is', 'Enter search', 'enter Id', 'aBort') else: opts = ('Skip', 'Use as-is', 'as Tracks', 'Enter search', 'enter Id', 'aBort') sel = ui.input_options(opts, numrange=(1, len(candidates)), color=color) if sel == 's': return importer.action.SKIP elif sel == 'u': return importer.action.ASIS elif sel == 'e': return importer.action.MANUAL elif sel == 't': assert not singleton return importer.action.TRACKS elif sel == 'b': raise importer.ImportAbort() elif sel == 'i': return importer.action.MANUAL_ID else: # Numerical selection. if singleton: match = candidates[sel - 1] else: match = candidates[sel - 1] bypass_candidates = False # Show what we're about to do. if singleton: show_item_change(item, match, color) else: show_change(cur_artist, cur_album, match, color, per_disc_numbering) # Exact match => tag automatically if we're not in timid mode. if rec == autotag.RECOMMEND_STRONG and not timid: return match # Ask for confirmation. if singleton: opts = ('Apply', 'More candidates', 'Skip', 'Use as-is', 'Enter search', 'enter Id', 'aBort') else: opts = ('Apply', 'More candidates', 'Skip', 'Use as-is', 'as Tracks', 'Enter search', 'enter Id', 'aBort') sel = ui.input_options(opts, color=color) if sel == 'a': return match elif sel == 'm': pass elif sel == 's': return importer.action.SKIP elif sel == 'u': return importer.action.ASIS elif sel == 't': assert not singleton return importer.action.TRACKS elif sel == 'e': return importer.action.MANUAL elif sel == 'b': raise importer.ImportAbort() elif sel == 'i': return importer.action.MANUAL_ID