def show_change(cur_artist, cur_album, items, info, dist, color=True): """Print out a representation of the changes that will be made if tags are changed from (cur_artist, cur_album, items) to info with distance dist. """ def show_album(artist, album): if artist: print_(' %s - %s' % (artist, album)) else: print_(' %s' % album) # Identify the album in question. if cur_artist != info['artist'] or \ (cur_album != info['album'] and info['album'] != VARIOUS_ARTISTS): artist_l, artist_r = cur_artist or '', info['artist'] album_l, album_r = cur_album or '', info['album'] if artist_r == VARIOUS_ARTISTS: # Hide artists for VA releases. artist_l, artist_r = u'', u'' if color: artist_l, artist_r = ui.colordiff(artist_l, artist_r) album_l, album_r = ui.colordiff(album_l, album_r) print_("Correcting tags from:") show_album(artist_l, album_l) print_("To:") show_album(artist_r, album_r) else: print_("Tagging: %s - %s" % (info['artist'], info['album'])) # Distance/similarity. print_('(Similarity: %s)' % dist_string(dist, color)) # Tracks. for i, (item, track_data) in enumerate(zip(items, info['tracks'])): cur_track = str(item.track) new_track = str(i+1) cur_title = item.title new_title = track_data['title'] # Possibly colorize changes. if color: cur_title, new_title = ui.colordiff(cur_title, new_title) if cur_track != new_track: cur_track = ui.colorize('red', cur_track) new_track = ui.colorize('red', new_track) if cur_title != new_title and cur_track != new_track: print_(" * %s (%s) -> %s (%s)" % ( cur_title, cur_track, new_title, new_track )) elif cur_title != new_title: print_(" * %s -> %s" % (cur_title, new_title)) elif cur_track != new_track: print_(" * %s (%s -> %s)" % (item.title, cur_track, new_track))
def _showdiff(field, oldval, newval): """Prints out a human-readable field difference line.""" # Considering floats incomparable for perfect equality, introduce # an epsilon tolerance. if isinstance(oldval, float) and isinstance(newval, float) and abs(oldval - newval) < FLOAT_EPSILON: return if newval != oldval: oldval, newval = ui.colordiff(oldval, newval) print_(u" %s: %s -> %s" % (field, oldval, newval))
def show_item_change(item, match): """Print out the change that would occur by tagging `item` with the metadata from `match`, a TrackMatch object. """ cur_artist, new_artist = item.artist, match.info.artist cur_title, new_title = item.title, match.info.title if cur_artist != new_artist or cur_title != new_title: cur_artist, new_artist = ui.colordiff(cur_artist, new_artist) cur_title, new_title = ui.colordiff(cur_title, new_title) print_("Correcting track tags from:") print_(" %s - %s" % (cur_artist, cur_title)) print_("To:") print_(" %s - %s" % (new_artist, new_title)) else: print_("Tagging track: %s - %s" % (cur_artist, cur_title)) print_('(Similarity: %s)' % dist_string(match.distance))
def show_item_change(item, info, dist, color): """Print out the change that would occur by tagging `item` with the metadata from `info`. """ cur_artist, new_artist = item.artist, info.artist cur_title, new_title = item.title, info.title if cur_artist != new_artist or cur_title != new_title: if color: cur_artist, new_artist = ui.colordiff(cur_artist, new_artist) cur_title, new_title = ui.colordiff(cur_title, new_title) print_("Correcting track tags from:") print_(" %s - %s" % (cur_artist, cur_title)) print_("To:") print_(" %s - %s" % (new_artist, new_title)) else: print_("Tagging track: %s - %s" % (cur_artist, cur_title)) print_('(Similarity: %s)' % dist_string(dist, color))
def show_change(cur_artist, cur_album, items, info, dist, color=True): """Print out a representation of the changes that will be made if tags are changed from (cur_artist, cur_album, items) to info with distance dist. """ if cur_artist != info['artist'] or cur_album != info['album']: artist_l, artist_r = cur_artist or '', info['artist'] album_l, album_r = cur_album or '', info['album'] if color: artist_l, artist_r = ui.colordiff(artist_l, artist_r) album_l, album_r = ui.colordiff(album_l, album_r) print_("Correcting tags from:") print_(' %s - %s' % (artist_l, album_l)) print_("To:") print_(' %s - %s' % (artist_r, album_r)) else: print_("Tagging: %s - %s" % (info['artist'], info['album'])) print_('(Distance: %s)' % dist_string(dist, color)) for i, (item, track_data) in enumerate(zip(items, info['tracks'])): cur_track = str(item.track) new_track = str(i+1) cur_title = item.title new_title = track_data['title'] # Possibly colorize changes. if color: cur_title, new_title = ui.colordiff(cur_title, new_title) if cur_track != new_track: cur_track = ui.colorize('red', cur_track) new_track = ui.colorize('red', new_track) if cur_title != new_title and cur_track != new_track: print_(" * %s (%s) -> %s (%s)" % ( cur_title, cur_track, new_title, new_track )) elif cur_title != new_title: print_(" * %s -> %s" % (cur_title, new_title)) elif cur_track != new_track: print_(" * %s (%s -> %s)" % (item.title, cur_track, new_track))
def _showdiff(field, oldval, newval, color): """Prints out a human-readable field difference line.""" # Considering floats incomparable for perfect equality, introduce # an epsilon tolerance. if isinstance(oldval, float) and isinstance(newval, float) and \ abs(oldval - newval) < FLOAT_EPSILON: return if newval != oldval: if color: oldval, newval = ui.colordiff(oldval, newval) else: oldval, newval = unicode(oldval), unicode(newval) print_(u' %s: %s -> %s' % (field, oldval, newval))
def show_item_change(item, match): """Print out the change that would occur by tagging `item` with the metadata from `match`, a TrackMatch object. """ cur_artist, new_artist = item.artist, match.info.artist cur_title, new_title = item.title, match.info.title if cur_artist != new_artist or cur_title != new_title: cur_artist, new_artist = ui.colordiff(cur_artist, new_artist) cur_title, new_title = ui.colordiff(cur_title, new_title) print_("Correcting track tags from:") print_(" %s - %s" % (cur_artist, cur_title)) print_("To:") print_(" %s - %s" % (new_artist, new_title)) else: print_("Tagging track: %s - %s" % (cur_artist, cur_title)) # Data URL. if match.info.data_url: print_('URL:\n %s' % match.info.data_url) # Info line. info = [] # Similarity. info.append('(Similarity: %s)' % dist_string(match.distance)) # Penalties. penalties = penalty_string(match.distance) if penalties: info.append(penalties) # Disambiguation. disambig = disambig_string(match.info) if disambig: info.append(ui.colorize('lightgray', '(%s)' % disambig)) print_(' '.join(info))
def _showdiff(field, oldval, newval): """Print out a human-readable field difference line if `oldval` and `newval` differ. Return a boolean indicating whether anything was printed (i.e., if any change needs to be made). """ # Considering floats incomparable for perfect equality, introduce # an epsilon tolerance. if isinstance(oldval, float) and isinstance(newval, float) and \ abs(oldval - newval) < FLOAT_EPSILON: return False if newval != oldval: oldval, newval = ui.colordiff(oldval, newval) print_(u' %s: %s -> %s' % (field, oldval, newval)) return True return False
def show_change(cur_artist, cur_album, items, info, dist, color=True): """Print out a representation of the changes that will be made if tags are changed from (cur_artist, cur_album, items) to info with distance dist. """ def show_album(artist, album, partial=False): if artist: album_description = u' %s - %s' % (artist, album) elif album: album_description = u' %s' % album else: album_description = u' (unknown album)' # Add a suffix if this is a partial match. if partial: warning = PARTIAL_MATCH_MESSAGE else: warning = None if color and warning: warning = ui.colorize('yellow', warning) out = album_description if warning: out += u' ' + warning print_(out) # Record if the match is partial or not. partial_match = None in items # Identify the album in question. if cur_artist != info.artist or \ (cur_album != info.album and info.album != VARIOUS_ARTISTS): artist_l, artist_r = cur_artist or '', info.artist album_l, album_r = cur_album or '', info.album if artist_r == VARIOUS_ARTISTS: # Hide artists for VA releases. artist_l, artist_r = u'', u'' if color: artist_l, artist_r = ui.colordiff(artist_l, artist_r) album_l, album_r = ui.colordiff(album_l, album_r) print_("Correcting tags from:") show_album(artist_l, album_l) print_("To:") show_album(artist_r, album_r) else: message = u"Tagging: %s - %s" % (info.artist, info.album) if partial_match: warning = PARTIAL_MATCH_MESSAGE if color: warning = ui.colorize('yellow', PARTIAL_MATCH_MESSAGE) message += u' ' + warning print_(message) # Distance/similarity. print_('(Similarity: %s)' % dist_string(dist, color)) # Tracks. missing_tracks = [] for i, (item, track_info) in enumerate(zip(items, info.tracks)): if not item: missing_tracks.append((i, track_info)) continue cur_track = unicode(item.track) new_track = unicode(i+1) cur_title = item.title new_title = track_info.title # Possibly colorize changes. if color: cur_title, new_title = ui.colordiff(cur_title, new_title) if cur_track != new_track: cur_track = ui.colorize('red', cur_track) new_track = ui.colorize('red', new_track) # Show filename (non-colorized) when title is not set. if not item.title.strip(): cur_title = displayable_path(os.path.basename(item.path)) if cur_title != new_title and cur_track != new_track: print_(u" * %s (%s) -> %s (%s)" % ( cur_title, cur_track, new_title, new_track )) elif cur_title != new_title: print_(u" * %s -> %s" % (cur_title, new_title)) elif cur_track != new_track: print_(u" * %s (%s -> %s)" % (item.title, cur_track, new_track)) for i, track_info in missing_tracks: line = u' * Missing track: %s (%d)' % (track_info.title, i+1) if color: line = ui.colorize('yellow', line) print_(line)
def show_change(cur_artist, cur_album, items, info, dist, color=True, per_disc_numbering=False): """Print out a representation of the changes that will be made if tags are changed from (cur_artist, cur_album, items) to info with distance dist. """ def show_album(artist, album, partial=False): if artist: album_description = u' %s - %s' % (artist, album) elif album: album_description = u' %s' % album else: album_description = u' (unknown album)' # Add a suffix if this is a partial match. if partial: warning = PARTIAL_MATCH_MESSAGE else: warning = None if color and warning: warning = ui.colorize('yellow', warning) out = album_description if warning: out += u' ' + warning print_(out) # Record if the match is partial or not. partial_match = None in items # Identify the album in question. if cur_artist != info.artist or \ (cur_album != info.album and info.album != VARIOUS_ARTISTS): artist_l, artist_r = cur_artist or '', info.artist album_l, album_r = cur_album or '', info.album if artist_r == VARIOUS_ARTISTS: # Hide artists for VA releases. artist_l, artist_r = u'', u'' if color: artist_l, artist_r = ui.colordiff(artist_l, artist_r) album_l, album_r = ui.colordiff(album_l, album_r) print_("Correcting tags from:") show_album(artist_l, album_l) print_("To:") show_album(artist_r, album_r) else: message = u"Tagging: %s - %s" % (info.artist, info.album) if partial_match: warning = PARTIAL_MATCH_MESSAGE if color: warning = ui.colorize('yellow', PARTIAL_MATCH_MESSAGE) message += u' ' + warning print_(message) # Distance/similarity. print_('(Similarity: %s)' % dist_string(dist, color)) # Tracks. missing_tracks = [] for i, (item, track_info) in enumerate(zip(items, info.tracks)): if not item: missing_tracks.append((i, track_info)) continue # Get displayable LHS and RHS values. cur_track = unicode(item.track) if per_disc_numbering: if info.mediums > 1: new_track = u'{0}-{1}'.format(track_info.medium, track_info.medium_index) else: new_track = unicode(track_info.medium_index) else: new_track = unicode(i + 1) tracks_differ = item.track not in (i + 1, track_info.medium_index) cur_title = item.title new_title = track_info.title if item.length and track_info.length: cur_length = ui.human_seconds_short(item.length) new_length = ui.human_seconds_short(track_info.length) if color: cur_length = ui.colorize('red', cur_length) new_length = ui.colorize('red', new_length) # Possibly colorize changes. if color: cur_title, new_title = ui.colordiff(cur_title, new_title) cur_track = ui.colorize('red', cur_track) new_track = ui.colorize('red', new_track) # Show filename (non-colorized) when title is not set. if not item.title.strip(): cur_title = displayable_path(os.path.basename(item.path)) if cur_title != new_title: lhs, rhs = cur_title, new_title if tracks_differ: lhs += u' (%s)' % cur_track rhs += u' (%s)' % new_track print_(u" * %s -> %s" % (lhs, rhs)) else: line = u' * %s' % item.title display = False if tracks_differ: display = True line += u' (%s -> %s)' % (cur_track, new_track) if item.length and track_info.length and \ abs(item.length - track_info.length) > 2.0: display = True line += u' (%s vs. %s)' % (cur_length, new_length) if display: print_(line) for i, track_info in missing_tracks: line = u' * Missing track: %s (%d)' % (track_info.title, i+1) if color: line = ui.colorize('yellow', line) print_(line)
def show_change(cur_artist, cur_album, items, info, dist, color=True): """Print out a representation of the changes that will be made if tags are changed from (cur_artist, cur_album, items) to info with distance dist. """ def show_album(artist, album, partial=False): if artist: album_description = u' %s - %s' % (artist, album) elif album: album_description = u' %s' % album else: album_description = u' (unknown album)' # Add a suffix if this is a partial match. if partial: warning = PARTIAL_MATCH_MESSAGE else: warning = None if color and warning: warning = ui.colorize('yellow', warning) out = album_description if warning: out += u' ' + warning print_(out) # Record if the match is partial or not. partial_match = None in items # Identify the album in question. if cur_artist != info.artist or \ (cur_album != info.album and info.album != VARIOUS_ARTISTS): artist_l, artist_r = cur_artist or '', info.artist album_l, album_r = cur_album or '', info.album if artist_r == VARIOUS_ARTISTS: # Hide artists for VA releases. artist_l, artist_r = u'', u'' if color: artist_l, artist_r = ui.colordiff(artist_l, artist_r) album_l, album_r = ui.colordiff(album_l, album_r) print_("Correcting tags from:") show_album(artist_l, album_l) print_("To:") show_album(artist_r, album_r) else: message = u"Tagging: %s - %s" % (info.artist, info.album) if partial_match: warning = PARTIAL_MATCH_MESSAGE if color: warning = ui.colorize('yellow', PARTIAL_MATCH_MESSAGE) message += u' ' + warning print_(message) # Distance/similarity. print_('(Similarity: %s)' % dist_string(dist, color)) # Tracks. missing_tracks = [] for i, (item, track_info) in enumerate(zip(items, info.tracks)): if not item: missing_tracks.append((i, track_info)) continue cur_track = unicode(item.track) new_track = unicode(i + 1) cur_title = item.title new_title = track_info.title # Possibly colorize changes. if color: cur_title, new_title = ui.colordiff(cur_title, new_title) if cur_track != new_track: cur_track = ui.colorize('red', cur_track) new_track = ui.colorize('red', new_track) # Show filename (non-colorized) when title is not set. if not item.title.strip(): cur_title = displayable_path(os.path.basename(item.path)) if cur_title != new_title and cur_track != new_track: print_(u" * %s (%s) -> %s (%s)" % (cur_title, cur_track, new_title, new_track)) elif cur_title != new_title: print_(u" * %s -> %s" % (cur_title, new_title)) elif cur_track != new_track: print_(u" * %s (%s -> %s)" % (item.title, cur_track, new_track)) for i, track_info in missing_tracks: line = u' * Missing track: %s (%d)' % (track_info.title, i + 1) if color: line = ui.colorize('yellow', line) print_(line)
def show_change(cur_artist, cur_album, match, color=True, per_disc_numbering=False): """Print out a representation of the changes that will be made if an album's tags are changed according to `match`, which must be an AlbumMatch object. """ def show_album(artist, album, partial=False): if artist: album_description = u' %s - %s' % (artist, album) elif album: album_description = u' %s' % album else: album_description = u' (unknown album)' # Add a suffix if this is a partial match. if partial: warning = PARTIAL_MATCH_MESSAGE else: warning = None if color and warning: warning = ui.colorize('yellow', warning) out = album_description if warning: out += u' ' + warning print_(out) def format_index(track_info): """Return a string representing the track index of the given TrackInfo object. """ if per_disc_numbering: if match.info.mediums > 1: return u'{0}-{1}'.format(track_info.medium, track_info.medium_index) else: return unicode(track_info.medium_index) else: return unicode(track_info.index) # Identify the album in question. if cur_artist != match.info.artist or \ (cur_album != match.info.album and match.info.album != VARIOUS_ARTISTS): artist_l, artist_r = cur_artist or '', match.info.artist album_l, album_r = cur_album or '', match.info.album if artist_r == VARIOUS_ARTISTS: # Hide artists for VA releases. artist_l, artist_r = u'', u'' if color: artist_l, artist_r = ui.colordiff(artist_l, artist_r) album_l, album_r = ui.colordiff(album_l, album_r) print_("Correcting tags from:") show_album(artist_l, album_l) print_("To:") show_album(artist_r, album_r) else: message = u"Tagging: %s - %s" % (match.info.artist, match.info.album) if match.extra_items or match.extra_tracks: warning = PARTIAL_MATCH_MESSAGE if color: warning = ui.colorize('yellow', PARTIAL_MATCH_MESSAGE) message += u' ' + warning print_(message) # Distance/similarity. print_('(Similarity: %s)' % dist_string(match.distance, color)) # Tracks. pairs = match.mapping.items() pairs.sort(key=lambda (_, track_info): track_info.index) for item, track_info in pairs: # Get displayable LHS and RHS values. cur_track = unicode(item.track) new_track = format_index(track_info) tracks_differ = item.track not in (track_info.index, track_info.medium_index) cur_title = item.title new_title = track_info.title if item.length and track_info.length: cur_length = ui.human_seconds_short(item.length) new_length = ui.human_seconds_short(track_info.length) if color: cur_length = ui.colorize('red', cur_length) new_length = ui.colorize('red', new_length) # Possibly colorize changes. if color: cur_title, new_title = ui.colordiff(cur_title, new_title) cur_track = ui.colorize('red', cur_track) new_track = ui.colorize('red', new_track) # Show filename (non-colorized) when title is not set. if not item.title.strip(): cur_title = displayable_path(os.path.basename(item.path)) if cur_title != new_title: lhs, rhs = cur_title, new_title if tracks_differ: lhs += u' (%s)' % cur_track rhs += u' (%s)' % new_track print_(u" * %s -> %s" % (lhs, rhs)) else: line = u' * %s' % item.title display = False if tracks_differ: display = True line += u' (%s -> %s)' % (cur_track, new_track) if item.length and track_info.length and \ abs(item.length - track_info.length) > 2.0: display = True line += u' (%s vs. %s)' % (cur_length, new_length) if display: print_(line) # Missing and unmatched tracks. for track_info in match.extra_tracks: line = u' * Missing track: {0} ({1})'.format(track_info.title, format_index(track_info)) if color: line = ui.colorize('yellow', line) print_(line) for item in match.extra_items: line = u' * Unmatched track: {0} ({1})'.format(item.title, item.track) if color: line = ui.colorize('yellow', line) print_(line)
def show_change(cur_artist, cur_album, match): """Print out a representation of the changes that will be made if an album's tags are changed according to `match`, which must be an AlbumMatch object. """ def show_album(artist, album): if artist: album_description = u' %s - %s' % (artist, album) elif album: album_description = u' %s' % album else: album_description = u' (unknown album)' print_(album_description) def format_index(track_info): """Return a string representing the track index of the given TrackInfo or Item object. """ if isinstance(track_info, hooks.TrackInfo): index = track_info.index medium_index = track_info.medium_index medium = track_info.medium mediums = match.info.mediums else: index = medium_index = track_info.track medium = track_info.disc mediums = track_info.disctotal if config['per_disc_numbering']: if mediums > 1: return u'{0}-{1}'.format(medium, medium_index) else: return unicode(medium_index) else: return unicode(index) # Identify the album in question. if cur_artist != match.info.artist or \ (cur_album != match.info.album and match.info.album != VARIOUS_ARTISTS): artist_l, artist_r = cur_artist or '', match.info.artist album_l, album_r = cur_album or '', match.info.album if artist_r == VARIOUS_ARTISTS: # Hide artists for VA releases. artist_l, artist_r = u'', u'' artist_l, artist_r = ui.colordiff(artist_l, artist_r) album_l, album_r = ui.colordiff(album_l, album_r) print_("Correcting tags from:") show_album(artist_l, album_l) print_("To:") show_album(artist_r, album_r) else: print_(u"Tagging:\n {0.artist} - {0.album}".format(match.info)) # Data URL. if match.info.data_url: print_('URL:\n %s' % match.info.data_url) # Info line. info = [] # Similarity. info.append('(Similarity: %s)' % dist_string(match.distance)) # Penalties. penalties = penalty_string(match.distance) if penalties: info.append(penalties) # Disambiguation. disambig = disambig_string(match.info) if disambig: info.append(ui.colorize('lightgray', '(%s)' % disambig)) print_(' '.join(info)) # Tracks. pairs = match.mapping.items() pairs.sort(key=lambda (_, track_info): track_info.index) # Build up LHS and RHS for track difference display. The `lines` list # contains ``(lhs, rhs, width)`` tuples where `width` is the length (in # characters) of the uncolorized LHS. lines = [] medium = disctitle = None for item, track_info in pairs: # Medium number and title. if medium != track_info.medium or disctitle != track_info.disctitle: media = match.info.media or 'Media' if match.info.mediums > 1 and track_info.disctitle: lhs = '%s %s: %s' % (media, track_info.medium, track_info.disctitle) elif match.info.mediums > 1: lhs = '%s %s' % (media, track_info.medium) elif track_info.disctitle: lhs = '%s: %s' % (media, track_info.disctitle) else: lhs = None if lhs: lines.append((lhs, '', 0)) medium, disctitle = track_info.medium, track_info.disctitle # Titles. new_title = track_info.title if not item.title.strip(): # If there's no title, we use the filename. cur_title = displayable_path(os.path.basename(item.path)) lhs, rhs = cur_title, new_title else: cur_title = item.title.strip() lhs, rhs = ui.colordiff(cur_title, new_title) lhs_width = len(cur_title) # Track number change. cur_track, new_track = format_index(item), format_index(track_info) if cur_track != new_track: if item.track in (track_info.index, track_info.medium_index): color = 'lightgray' else: color = 'red' if (cur_track + new_track).count('-') == 1: lhs_track, rhs_track = ui.colorize(color, cur_track), \ ui.colorize(color, new_track) else: color = 'red' lhs_track, rhs_track = ui.color_diff_suffix(cur_track, new_track) templ = ui.colorize(color, u' (#') + u'{0}' + \ ui.colorize(color, u')') lhs += templ.format(lhs_track) rhs += templ.format(rhs_track) lhs_width += len(cur_track) + 4 # Length change. if item.length and track_info.length and \ abs(item.length - track_info.length) > \ config['ui']['length_diff_thresh'].as_number(): cur_length = ui.human_seconds_short(item.length) new_length = ui.human_seconds_short(track_info.length) lhs_length, rhs_length = ui.color_diff_suffix(cur_length, new_length) templ = ui.colorize('red', u' (') + u'{0}' + \ ui.colorize('red', u')') lhs += templ.format(lhs_length) rhs += templ.format(rhs_length) lhs_width += len(cur_length) + 3 # Penalties. penalties = penalty_string(match.distance.tracks[track_info]) if penalties: rhs += ' %s' % penalties if lhs != rhs: lines.append((' * %s' % lhs, rhs, lhs_width)) elif config['import']['detail']: lines.append((' * %s' % lhs, '', lhs_width)) # Print each track in two columns, or across two lines. col_width = (ui.term_width() - len(''.join([' * ', ' -> ']))) // 2 if lines: max_width = max(w for _, _, w in lines) for lhs, rhs, lhs_width in lines: if not rhs: print_(lhs) elif max_width > col_width: print_(u'%s ->\n %s' % (lhs, rhs)) else: pad = max_width - lhs_width print_(u'%s%s -> %s' % (lhs, ' ' * pad, rhs)) # Missing and unmatched tracks. if match.extra_tracks: print_('Missing tracks:') for track_info in match.extra_tracks: line = ' ! %s (#%s)' % (track_info.title, format_index(track_info)) if track_info.length: line += ' (%s)' % ui.human_seconds_short(track_info.length) print_(ui.colorize('yellow', line)) if match.extra_items: print_('Unmatched tracks:') for item in match.extra_items: line = ' ! %s (#%s)' % (item.title, format_index(item)) if item.length: line += ' (%s)' % ui.human_seconds_short(item.length) print_(ui.colorize('yellow', line))
def show_change(cur_artist, cur_album, match): """Print out a representation of the changes that will be made if an album's tags are changed according to `match`, which must be an AlbumMatch object. """ def show_album(artist, album, partial=False): if artist: album_description = u' %s - %s' % (artist, album) elif album: album_description = u' %s' % album else: album_description = u' (unknown album)' out = album_description # Add a suffix if this is a partial match. if partial: out += u' %s' % ui.colorize('yellow', PARTIAL_MATCH_MESSAGE) print_(out) def format_index(track_info): """Return a string representing the track index of the given TrackInfo or Item object. """ if isinstance(track_info, autotag.hooks.TrackInfo): index = track_info.index medium_index = track_info.medium_index medium = track_info.medium mediums = match.info.mediums else: index = medium_index = track_info.track medium = track_info.disc mediums = track_info.disctotal if config['per_disc_numbering'].get(bool): if mediums > 1: return u'{0}-{1}'.format(medium, medium_index) else: return unicode(medium_index) else: return unicode(index) # Identify the album in question. if cur_artist != match.info.artist or \ (cur_album != match.info.album and match.info.album != VARIOUS_ARTISTS): artist_l, artist_r = cur_artist or '', match.info.artist album_l, album_r = cur_album or '', match.info.album if artist_r == VARIOUS_ARTISTS: # Hide artists for VA releases. artist_l, artist_r = u'', u'' artist_l, artist_r = ui.colordiff(artist_l, artist_r) album_l, album_r = ui.colordiff(album_l, album_r) print_("Correcting tags from:") show_album(artist_l, album_l) print_("To:") show_album(artist_r, album_r) else: message = u"Tagging:\n %s - %s" % (match.info.artist, match.info.album) if match.extra_items or match.extra_tracks: message += u' %s' % ui.colorize('yellow', PARTIAL_MATCH_MESSAGE) print_(message) # Data URL. if match.info.data_url: print_('URL:\n %s' % match.info.data_url) # Info line. info = [] info.append('(Similarity: %s)' % dist_string(match.distance)) if match.info.data_source != 'MusicBrainz': info.append(ui.colorize('turquoise', '(%s)' % match.info.data_source)) disambig = disambig_string(match.info) if disambig: info.append(ui.colorize('lightgray', '(%s)' % disambig)) print_(' '.join(info)) # Tracks. pairs = match.mapping.items() pairs.sort(key=lambda (_, track_info): track_info.index) # Build up LHS and RHS for track difference display. The `lines` list # contains ``(lhs, rhs, width)`` tuples where `width` is the length (in # characters) of the uncolorized LHS. lines = [] medium = disctitle = None for item, track_info in pairs: # Medium number and title. if medium != track_info.medium or disctitle != track_info.disctitle: media = match.info.media or 'Media' if match.info.mediums > 1 and track_info.disctitle: lhs = '%s %s: %s' % (media, track_info.medium, track_info.disctitle) elif match.info.mediums > 1: lhs = '%s %s' % (media, track_info.medium) elif track_info.disctitle: lhs = '%s: %s' % (media, track_info.disctitle) else: lhs = None if lhs: lines.append((lhs, '', 0)) medium, disctitle = track_info.medium, track_info.disctitle # Titles. new_title = track_info.title if not item.title.strip(): # If there's no title, we use the filename. cur_title = displayable_path(os.path.basename(item.path)) lhs, rhs = cur_title, new_title else: cur_title = item.title.strip() lhs, rhs = ui.colordiff(cur_title, new_title) lhs_width = len(cur_title) # Track number change. cur_track, new_track = format_index(item), format_index(track_info) if cur_track != new_track: if item.track in (track_info.index, track_info.medium_index): color = 'yellow' else: color = 'red' if (cur_track + new_track).count('-') == 1: lhs_track, rhs_track = ui.colorize(color, cur_track), \ ui.colorize(color, new_track) else: color = 'red' lhs_track, rhs_track = ui.color_diff_suffix( cur_track, new_track) templ = ui.colorize(color, u' (#') + u'{0}' + \ ui.colorize(color, u')') lhs += templ.format(lhs_track) rhs += templ.format(rhs_track) lhs_width += len(cur_track) + 4 # Length change. if item.length and track_info.length and \ abs(item.length - track_info.length) > \ config['ui']['length_diff_thresh'].as_number(): cur_length = ui.human_seconds_short(item.length) new_length = ui.human_seconds_short(track_info.length) lhs_length, rhs_length = ui.color_diff_suffix( cur_length, new_length) templ = ui.colorize('red', u' (') + u'{0}' + \ ui.colorize('red', u')') lhs += templ.format(lhs_length) rhs += templ.format(rhs_length) lhs_width += len(cur_length) + 3 # Hidden penalties. No LHS/RHS diff is displayed, but we still want to # indicate that a penalty has been applied to explain the similarity # score. penalties = [] if match.info.va and track_info.artist and \ item.artist.lower() not in VA_ARTISTS: penalties.append('artist') if item.mb_trackid and item.mb_trackid != track_info.track_id: penalties.append('ID') if penalties: rhs += ' %s' % ui.colorize('red', '(%s)' % ', '.join(penalties)) if lhs != rhs: lines.append((' * %s' % lhs, rhs, lhs_width)) elif config['import']['detail']: lines.append((' * %s' % lhs, '', lhs_width)) # Print each track in two columns, or across two lines. col_width = (ui.term_width() - len(''.join([' * ', ' -> ']))) // 2 if lines: max_width = max(w for _, _, w in lines) for lhs, rhs, lhs_width in lines: if not rhs: print_(lhs) elif max_width > col_width: print_(u'%s ->\n %s' % (lhs, rhs)) else: pad = max_width - lhs_width print_(u'%s%s -> %s' % (lhs, ' ' * pad, rhs)) # Missing and unmatched tracks. if match.extra_tracks: print_('Missing tracks:') for track_info in match.extra_tracks: line = ' ! %s (#%s)' % (track_info.title, format_index(track_info)) if track_info.length: line += ' (%s)' % ui.human_seconds_short(track_info.length) print_(ui.colorize('yellow', line)) if match.extra_items: print_('Unmatched tracks:') for item in match.extra_items: line = ' ! %s (#%s)' % (item.title, format_index(item)) if item.length: line += ' (%s)' % ui.human_seconds_short(item.length) print_(ui.colorize('yellow', line))
def _showdiff(field, oldval, newval, color): """Prints out a human-readable field difference line.""" if newval != oldval: if color: oldval, newval = ui.colordiff(oldval, newval) print_(u' %s: %s -> %s' % (field, oldval, newval))
def show_change(cur_artist, cur_album, match): """Print out a representation of the changes that will be made if an album's tags are changed according to `match`, which must be an AlbumMatch object. """ def show_album(artist, album, partial=False): if artist: album_description = u' %s - %s' % (artist, album) elif album: album_description = u' %s' % album else: album_description = u' (unknown album)' out = album_description # Add a suffix if this is a partial match. if partial: out += u' ' + ui.colorize('yellow', PARTIAL_MATCH_MESSAGE) print_(out) def format_index(track_info): """Return a string representing the track index of the given TrackInfo object. """ if config['per_disc_numbering'].get(bool): if match.info.mediums > 1: return u'{0}-{1}'.format(track_info.medium, track_info.medium_index) else: return unicode(track_info.medium_index) else: return unicode(track_info.index) # Identify the album in question. if cur_artist != match.info.artist or \ (cur_album != match.info.album and match.info.album != VARIOUS_ARTISTS): artist_l, artist_r = cur_artist or '', match.info.artist album_l, album_r = cur_album or '', match.info.album if artist_r == VARIOUS_ARTISTS: # Hide artists for VA releases. artist_l, artist_r = u'', u'' artist_l, artist_r = ui.colordiff(artist_l, artist_r) album_l, album_r = ui.colordiff(album_l, album_r) print_("Correcting tags from:") show_album(artist_l, album_l) print_("To:") show_album(artist_r, album_r) else: message = u"Tagging: %s - %s" % (match.info.artist, match.info.album) if match.extra_items or match.extra_tracks: message += u' ' + ui.colorize('yellow', PARTIAL_MATCH_MESSAGE) print_(message) # Distance/similarity. print_('(Similarity: %s)' % dist_string(match.distance)) # Tracks. pairs = match.mapping.items() pairs.sort(key=lambda (_, track_info): track_info.index) # Build up LHS and RHS for track difference display. The `lines` # list contains ``(current title, new title, width)`` tuples where # `width` is the length (in characters) of the uncolorized LHS. lines = [] for item, track_info in pairs: # Titles. new_title = track_info.title if not item.title.strip(): # If there's no title, we use the filename. cur_title = displayable_path(os.path.basename(item.path)) lhs, rhs = cur_title, new_title else: cur_title = item.title.strip() lhs, rhs = ui.colordiff(cur_title, new_title) lhs_width = len(cur_title) # Track number change. if item.track not in (track_info.index, track_info.medium_index): cur_track, new_track = unicode( item.track), format_index(track_info) lhs_track, rhs_track = ui.color_diff_suffix(cur_track, new_track) templ = ui.colorize('red', u' (#') + u'{0}' + \ ui.colorize('red', u')') lhs += templ.format(lhs_track) rhs += templ.format(rhs_track) lhs_width += len(cur_track) + 4 # Length change. if item.length and track_info.length and \ abs(item.length - track_info.length) > \ config['ui']['length_diff_thresh'].as_number(): cur_length = ui.human_seconds_short(item.length) new_length = ui.human_seconds_short(track_info.length) lhs_length, rhs_length = ui.color_diff_suffix( cur_length, new_length) templ = ui.colorize('red', u' (') + u'{0}' + \ ui.colorize('red', u')') lhs += templ.format(lhs_length) rhs += templ.format(rhs_length) lhs_width += len(cur_length) + 3 if lhs != rhs: lines.append((lhs, rhs, lhs_width)) # Print each track in two columns, or across two lines. col_width = (ui.term_width() - len(''.join([' * ', ' -> ']))) // 2 if lines: max_width = max(w for _, _, w in lines) for lhs, rhs, lhs_width in lines: if max_width > col_width: print_(u' * %s ->\n %s' % (lhs, rhs)) else: pad = max_width - lhs_width print_(u' * %s%s -> %s' % (lhs, ' ' * pad, rhs)) # Missing and unmatched tracks. for track_info in match.extra_tracks: line = u' * Missing track: {0} ({1})'.format(track_info.title, format_index(track_info)) line = ui.colorize('yellow', line) print_(line) for item in match.extra_items: line = u' * Unmatched track: {0} ({1})'.format(item.title, item.track) line = ui.colorize('yellow', line) print_(line)
def show_change(cur_artist, cur_album, match): """Print out a representation of the changes that will be made if an album's tags are changed according to `match`, which must be an AlbumMatch object. """ def show_album(artist, album, partial=False): if artist: album_description = u' %s - %s' % (artist, album) elif album: album_description = u' %s' % album else: album_description = u' (unknown album)' out = album_description # Add a suffix if this is a partial match. if partial: out += u' ' + ui.colorize('yellow', PARTIAL_MATCH_MESSAGE) print_(out) def format_index(track_info): """Return a string representing the track index of the given TrackInfo object. """ if config['per_disc_numbering'].get(bool): if match.info.mediums > 1: return u'{0}-{1}'.format(track_info.medium, track_info.medium_index) else: return unicode(track_info.medium_index) else: return unicode(track_info.index) # Identify the album in question. if cur_artist != match.info.artist or \ (cur_album != match.info.album and match.info.album != VARIOUS_ARTISTS): artist_l, artist_r = cur_artist or '', match.info.artist album_l, album_r = cur_album or '', match.info.album if artist_r == VARIOUS_ARTISTS: # Hide artists for VA releases. artist_l, artist_r = u'', u'' artist_l, artist_r = ui.colordiff(artist_l, artist_r) album_l, album_r = ui.colordiff(album_l, album_r) print_("Correcting tags from:") show_album(artist_l, album_l) print_("To:") show_album(artist_r, album_r) else: message = u"Tagging: %s - %s" % (match.info.artist, match.info.album) if match.extra_items or match.extra_tracks: message += u' ' + ui.colorize('yellow', PARTIAL_MATCH_MESSAGE) print_(message) # Distance/similarity. print_('(Similarity: %s)' % dist_string(match.distance)) # Tracks. pairs = match.mapping.items() pairs.sort(key=lambda (_, track_info): track_info.index) # Build up LHS and RHS for track difference display. The `lines` # list contains ``(current title, new title, width)`` tuples where # `width` is the length (in characters) of the uncolorized LHS. lines = [] for item, track_info in pairs: # Titles. new_title = track_info.title if not item.title.strip(): # If there's no title, we use the filename. cur_title = displayable_path(os.path.basename(item.path)) lhs, rhs = cur_title, new_title else: cur_title = item.title.strip() lhs, rhs = ui.colordiff(cur_title, new_title) lhs_width = len(cur_title) # Track number change. if item.track not in (track_info.index, track_info.medium_index): cur_track, new_track = unicode(item.track), format_index(track_info) lhs_track, rhs_track = ui.color_diff_suffix(cur_track, new_track) templ = ui.colorize('red', u' (#') + u'{0}' + \ ui.colorize('red', u')') lhs += templ.format(lhs_track) rhs += templ.format(rhs_track) lhs_width += len(cur_track) + 4 # Length change. if item.length and track_info.length and \ abs(item.length - track_info.length) > \ config['ui']['length_diff_thresh'].as_number(): cur_length = ui.human_seconds_short(item.length) new_length = ui.human_seconds_short(track_info.length) lhs_length, rhs_length = ui.color_diff_suffix(cur_length, new_length) templ = ui.colorize('red', u' (') + u'{0}' + \ ui.colorize('red', u')') lhs += templ.format(lhs_length) rhs += templ.format(rhs_length) lhs_width += len(cur_length) + 3 if lhs != rhs: lines.append((lhs, rhs, lhs_width)) elif config['import']['detail']: lines.append((lhs, '', lhs_width)) # Print each track in two columns, or across two lines. col_width = (ui.term_width() - len(''.join([' * ', ' -> ']))) // 2 if lines: max_width = max(w for _, _, w in lines) for lhs, rhs, lhs_width in lines: if not rhs: print_(u' * {0}'.format(lhs)) elif max_width > col_width: print_(u' * %s ->\n %s' % (lhs, rhs)) else: pad = max_width - lhs_width print_(u' * %s%s -> %s' % (lhs, ' ' * pad, rhs)) # Missing and unmatched tracks. for track_info in match.extra_tracks: line = u' * Missing track: {0} ({1})'.format(track_info.title, format_index(track_info)) line = ui.colorize('yellow', line) print_(line) for item in match.extra_items: line = u' * Unmatched track: {0} ({1})'.format(item.title, item.track) line = ui.colorize('yellow', line) print_(line)
def show_change(cur_artist, cur_album, items, info, dist, color=True, per_disc_numbering=False): """Print out a representation of the changes that will be made if tags are changed from (cur_artist, cur_album, items) to info with distance dist. """ def show_album(artist, album, partial=False): if artist: album_description = u' %s - %s' % (artist, album) elif album: album_description = u' %s' % album else: album_description = u' (unknown album)' # Add a suffix if this is a partial match. if partial: warning = PARTIAL_MATCH_MESSAGE else: warning = None if color and warning: warning = ui.colorize('yellow', warning) out = album_description if warning: out += u' ' + warning print_(out) # Record if the match is partial or not. partial_match = None in items # Identify the album in question. if cur_artist != info.artist or \ (cur_album != info.album and info.album != VARIOUS_ARTISTS): artist_l, artist_r = cur_artist or '', info.artist album_l, album_r = cur_album or '', info.album if artist_r == VARIOUS_ARTISTS: # Hide artists for VA releases. artist_l, artist_r = u'', u'' if color: artist_l, artist_r = ui.colordiff(artist_l, artist_r) album_l, album_r = ui.colordiff(album_l, album_r) print_("Correcting tags from:") show_album(artist_l, album_l) print_("To:") show_album(artist_r, album_r) else: message = u"Tagging: %s - %s" % (info.artist, info.album) if partial_match: warning = PARTIAL_MATCH_MESSAGE if color: warning = ui.colorize('yellow', PARTIAL_MATCH_MESSAGE) message += u' ' + warning print_(message) # Distance/similarity. print_('(Similarity: %s)' % dist_string(dist, color)) # Tracks. missing_tracks = [] for i, (item, track_info) in enumerate(zip(items, info.tracks)): if not item: missing_tracks.append((i, track_info)) continue # Get displayable LHS and RHS values. cur_track = unicode(item.track) if per_disc_numbering: if info.mediums > 1: new_track = u'{0}-{1}'.format(track_info.medium, track_info.medium_index) else: new_track = unicode(track_info.medium_index) else: new_track = unicode(i + 1) tracks_differ = item.track not in (i + 1, track_info.medium_index) cur_title = item.title new_title = track_info.title if item.length and track_info.length: cur_length = ui.human_seconds_short(item.length) new_length = ui.human_seconds_short(track_info.length) if color: cur_length = ui.colorize('red', cur_length) new_length = ui.colorize('red', new_length) # Possibly colorize changes. if color: cur_title, new_title = ui.colordiff(cur_title, new_title) cur_track = ui.colorize('red', cur_track) new_track = ui.colorize('red', new_track) # Show filename (non-colorized) when title is not set. if not item.title.strip(): cur_title = displayable_path(os.path.basename(item.path)) if cur_title != new_title: lhs, rhs = cur_title, new_title if tracks_differ: lhs += u' (%s)' % cur_track rhs += u' (%s)' % new_track print_(u" * %s -> %s" % (lhs, rhs)) else: line = u' * %s' % item.title display = False if tracks_differ: display = True line += u' (%s -> %s)' % (cur_track, new_track) if item.length and track_info.length and \ abs(item.length - track_info.length) > 2.0: display = True line += u' (%s vs. %s)' % (cur_length, new_length) if display: print_(line) for i, track_info in missing_tracks: line = u' * Missing track: %s (%d)' % (track_info.title, i + 1) if color: line = ui.colorize('yellow', line) print_(line)