def on_import_task_before_choice(self, task, session): if hasattr(task, '_badfiles_checks_failed'): ui.print_('{} one or more files failed checks:'.format( ui.colorize('text_warning', 'BAD'))) for error in task._badfiles_checks_failed: for error_line in error: ui.print_(error_line) ui.print_() ui.print_('What would you like to do?') sel = ui.input_options(['aBort', 'skip', 'continue']) if sel == 's': return importer.action.SKIP elif sel == 'c': return None elif sel == 'b': raise importer.ImportAbort() else: raise Exception('Unexpected selection: {}'.format(sel))
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, cur_artist=None, cur_album=None, item=None, itemcount=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). 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) 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 != recommendation.none: match = candidates[0] bypass_candidates = True while True: # Display and choose from candidates. require = rec <= recommendation.low 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))) else: print_('Finding tags for album "%s - %s".' % (cur_artist, cur_album)) print_('Candidates:') for i, match in enumerate(candidates): line = [ '%i. %s - %s (%s)' % (i + 1, match.info.artist, match.info.album, dist_string(match.distance)) ] # Point out the partial matches. if match.extra_items or match.extra_tracks: line.append( ui.colorize('yellow', PARTIAL_MATCH_MESSAGE)) # Sources other than MusicBrainz. source = match.info.data_source if source != 'MusicBrainz': line.append(ui.colorize('turquoise', '(%s)' % source)) disambig = disambig_string(match.info) if disambig: line.append(ui.colorize('lightgray', '(%s)' % disambig)) print_(' '.join(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))) 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. match = candidates[sel - 1] if sel != 1: # When choosing anything but the first match, # disable the default action. require = True bypass_candidates = False # Show what we're about to do. if singleton: show_item_change(item, match) else: show_change(cur_artist, cur_album, match) # Exact match => tag automatically if we're not in timid mode. if rec == recommendation.strong and not config['import']['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') default = config['import']['default_action'].as_choice({ 'apply': 'a', 'skip': 's', 'asis': 'u', 'none': None, }) if default is None: require = True sel = ui.input_options(opts, require=require, default=default) 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, cur_artist=None, cur_album=None, item=None, itemcount=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). 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: ' 'http://beets.readthedocs.org/en/latest/faq.html#nomatch') opts = ('Use as-is', 'as Tracks', 'Skip', 'Enter search', 'enter Id', 'aBort') sel = ui.input_options(opts) 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 != recommendation.none: match = candidates[0] bypass_candidates = True while True: # Display and choose from candidates. require = rec <= recommendation.low if not bypass_candidates: # Display list of candidates. print_(u'Finding tags for {0} "{1} - {2}".'.format( u'track' if singleton else u'album', item.artist if singleton else cur_artist, item.title if singleton else cur_album, )) print_(u'Candidates:') for i, match in enumerate(candidates): # Index, metadata, and distance. line = [ u'{0}.'.format(i + 1), u'{0} - {1}'.format( match.info.artist, match.info.title if singleton else match.info.album, ), u'({0})'.format(dist_string(match.distance)), ] # Penalties. penalties = penalty_string(match.distance, 3) if penalties: line.append(penalties) # Disambiguation disambig = disambig_string(match.info) if disambig: line.append(ui.colorize('lightgray', '(%s)' % disambig)) print_(' '.join(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))) 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. match = candidates[sel - 1] if sel != 1: # When choosing anything but the first match, # disable the default action. require = True bypass_candidates = False # Show what we're about to do. if singleton: show_item_change(item, match) else: show_change(cur_artist, cur_album, match) # Exact match => tag automatically if we're not in timid mode. if rec == recommendation.strong and not config['import']['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') default = config['import']['default_action'].as_choice({ 'apply': 'a', 'skip': 's', 'asis': 'u', 'none': None, }) if default is None: require = True sel = ui.input_options(opts, require=require, default=default) 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, 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, cur_artist=None, cur_album=None, item=None, itemcount=None, extra_choices=[]): """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. `extra_choices` is a list of `PromptChoice`s, containg the choices appended by the plugins after receiving the `before_choose_candidate` event. If not empty, the choices are appended to the prompt presented to the user. Returns one of the following: * the result of the choice, which may be SKIP, ASIS, TRACKS, or MANUAL * a candidate (an AlbumMatch/TrackMatch object) * the short letter of a `PromptChoice` (if the user selected one of the `extra_choices`). """ # Sanity check. assert not singleton assert cur_artist is not None assert cur_album is not None # Zero candidates. if not candidates: print_(u"No matching release found for {0} tracks.".format(itemcount)) print_(u'For help, see: ' u'http://beets.readthedocs.org/en/latest/faq.html#nomatch') opts = (u'Skip', u'Enter search', u'enter Id', u'aBort') sel = ui.input_options(opts) if sel == u'e': return importer.action.MANUAL elif sel == u's': return importer.action.SKIP elif sel == u'b': raise importer.ImportAbort() elif sel == u'i': return importer.action.MANUAL_ID else: assert False while True: # Display and choose from candidates. require = rec <= Recommendation.low # Display list of candidates. print_(u'Finding tags for {0} "{1} - {2}".'.format( u'album', cur_artist, cur_album, )) print_(u'Candidates:') for i, match in enumerate(candidates): # Index, metadata, and distance. line = [ u'{0}.'.format(i + 1), u'{0} - {1}'.format( match.info.artist, match.info.album, ), u'({0})'.format(dist_string(match.distance)), ] # Penalties. penalties = penalty_string(match.distance, 3) if penalties: line.append(penalties) # Disambiguation disambig = disambig_string(match.info) if disambig: line.append( ui.colorize('text_highlight_minor', u'(%s)' % disambig)) print_(u' '.join(line)) # Ask the user for a choice. opts = (u'Skip', u'Enter search', u'enter Id', u'aBort') sel = ui.input_options(opts, numrange=(1, len(candidates))) if sel == u's': return importer.action.SKIP elif sel == u'e': return importer.action.MANUAL elif sel == u'b': raise importer.ImportAbort() elif sel == u'i': return importer.action.MANUAL_ID else: # Numerical selection. match = candidates[sel - 1] if sel != 1: # When choosing anything but the first match, # disable the default action. require = True # Show what we're about to do. show_change(cur_artist, cur_album, match) # Exact match => tag automatically. if rec == Recommendation.strong: return match # Ask for confirmation. opts = (u'Apply', u'More candidates', u'Skip', u'Enter search', u'enter Id', u'aBort') default = config['import']['default_action'].as_choice({ u'apply': u'a', u'skip': u's', u'none': None, }) if default is None: require = True sel = ui.input_options(opts, require=require, default=default) if sel == u'a': return match elif sel == u's': return importer.action.SKIP elif sel == u'e': return importer.action.MANUAL elif sel == u'b': raise importer.ImportAbort() elif sel == u'i': return importer.action.MANUAL_ID
def choose_candidate(candidates, singleton, rec, color, interactive_autotag, 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 an `info` dictionary. """ # 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', 'aBort') else: opts = ('Use as-is', 'as Tracks', 'Skip', 'Enter search', 'aBort') sel = ui.input_options(opts) 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() 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): print_('%i. %s - %s (%s)' % (i + 1, info['artist'], info['album'], dist_string(dist, color))) # Ask the user for a choice. if singleton: opts = ('Skip', 'Use as-is', 'Enter search', 'aBort') else: opts = ('Skip', 'Use as-is', 'as Tracks', 'Enter search', 'aBort') sel = ui.input_options(opts, numrange=(1, len(candidates))) 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() 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 no interactive tagging is requested. if rec == autotag.RECOMMEND_STRONG and not interactive_autotag: if singleton: return info else: return info, items # Ask for confirmation. if singleton: opts = ('Apply', 'More candidates', 'Skip', 'Use as-is', 'Enter search', 'aBort') else: opts = ('Apply', 'More candidates', 'Skip', 'Use as-is', 'as Tracks', 'Enter search', 'aBort') sel = ui.input_options(opts) 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()