Ejemplo n.º 1
0
 def print_tags(self,
                detailed=False,
                as_json=False,
                as_pprint=False,
                to_file=None,
                extended=False,
                header=True,
                subscript=None,
                highlight_title=False):
     if header and not to_file:
         stdout()
         if subscript:
             green(self.full_path(), end='')
             cyan(' (' + subscript + ')')
         else:
             green(self.full_path())
     track = self.get('TRACKNUMBER')
     fix_track = False
     if track.startswith('T'):
         track = track[1:]
         fix_track = True
     if fix_track:
         self.set('TRACKNUMBER', track)
     if detailed:
         self.print(extended, highlight_title)
     elif as_json or as_pprint:
         self.print_json(extended, as_pprint, to_file)
     else:
         self.echo()
Ejemplo n.º 2
0
    def finish_it():
        global errors_fixed

        debug_out('finish_it')

        artist = song.get('ALBUMARTIST')
        contributing_artists = song.get('ARTIST')
        album = song.get('ALBUM')
        title = song.get('TITLE')

        if sung_it:
            report('OK')
        if did_it():
            if silent:
                green('Retagged', project, '/', artist,
                      '(' + contributing_artists + ') /', album, '/', title)
            else:
                stdout('WAS:')
                print_it(keep)
                stdout('BECAME:')
                print_it()
            save_it()  # this is the moment where we save!
            errors_fixed += 1
Ejemplo n.º 3
0
 def rename(to):
     rooted_entity_path_root = root + '/' + unrooted_entity_path_root
     if is_file:
         green('Renaming',
               unrooted_entity_path_root.replace('/', ' / '), '/',
               entity_d + file_extension, 'to', to + file_extension)
         rename_file(rooted_entity_path_root,
                     entity_d + file_extension,
                     to + file_extension,
                     safe_rename=True,
                     add_suffix_if_exists=True,
                     dryrun=dryrun,
                     verbose=verbose,
                     silent=silent,
                     debug=debug)
     elif (path_exists(rooted_entity_path_root + '/' + to)
           and not (is_windows() and entity_d.lower() == to.lower())):
         green('Merging', unrooted_entity_path_root, '/', entity_d,
               'into', to)
         merge_dir(rooted_entity_path_root + '/' + entity_d,
                   rooted_entity_path_root + '/' + to,
                   safe_merge=True,
                   add_suffix_if_exists=True,
                   merge_subdirs=True,
                   dryrun=dryrun,
                   verbose=verbose,
                   silent=silent,
                   debug=debug)
     else:
         green('Renaming',
               unrooted_entity_path_root.replace('/', ' / '), '/',
               entity_d, 'to', to)
         rename_dir(rooted_entity_path_root,
                    entity_d,
                    to,
                    safe_rename=False,
                    dryrun=dryrun,
                    verbose=verbose,
                    silent=silent,
                    debug=debug)
Ejemplo n.º 4
0
def get_filtered_songs(path, song_fs,
                       artist_filter=None, album_filter=None,
                       title_filter=None,
                       sort_per_track=False, post_process_songs=False,
                       print_header=True,
                       no_warn=False, deep_warn=False,
                       mark_missing_songs=False, dryrun=True,
                       verbose=False, silent=False, debug=False):
    printed_header = False
    filtered_songs = {}
    missed_songs = []
    warnings = 0
    max_track_len = 0
    total_album_tracks = None  # unknown or inconsistent
    track_info_per_song = {}

    for song in song_fs:
        if is_song_file(song):
            s = Song(path=path, song_f=song, debug=debug)
            if ((not artist_filter or
                 artist_filter.lower() in s.get('ALBUMARTIST').lower()) and
                    ((not album_filter or
                      album_filter.lower() in s.get('ALBUM').lower()) and
                     (not title_filter or
                      title_filter.lower() in s.get('TITLE').lower()))):
                if print_header and not printed_header:
                    green()
                    green('Listing', path)
                    printed_header = True
                if sort_per_track:
                    track_tag = s.get_track_nbr_as_string(verbose=verbose)
                    track_nbr, total = s.parse_track_nbr(track_tag)
                    track_info_per_song[s.name()] = (track_nbr, total)

                    # build up a list, in case of mixes directory, there would
                    # be track number overlaps
                    f_songs = filtered_songs.get(track_nbr)
                    if f_songs:
                        f_songs.append(s)
                    else:
                        filtered_songs[track_nbr] = [s]

                else:
                    track_tag = s.get_track_nbr_as_string(verbose=verbose)
                    filtered_songs[len(filtered_songs)] = [s]

                max_track_len = max(max_track_len, len(track_tag))

    if filtered_songs and sort_per_track and post_process_songs:
        prev_track_nbr = 0
        song_that_gave_total_tracks = None
        total_tracks_is_inconsistent = False
        for track_nbr in sorted(filtered_songs):
            first_song = True
            for song in filtered_songs[track_nbr]:
                song_f = song.name()
                song_base = song_f[:-len(SONG_FILE_EXT)]
                track_nbr, total = track_info_per_song[song_f]
                if missing_file_exists(path, track_nbr):
                    error('.missing file exists for', song_f, end='\n')
                    error('You must delete it:',
                          get_missing_file_full_path(path, track_nbr),
                          end='\n')
                if first_song:
                    if track_nbr != prev_track_nbr + 1:
                        # TODO(if last song is missing, we don't report)
                        for i in range(prev_track_nbr + 1, track_nbr):
                            if not missing_file_exists(path, i):
                                if mark_missing_songs:
                                    add_missing_file(path, i, dryrun)
                                else:
                                    missed_songs.append((path, i))

                    prev_track_nbr = track_nbr
                    first_song = False

                if total and not total_tracks_is_inconsistent:
                    if total_album_tracks is None:
                        total_album_tracks = total
                        song_that_gave_total_tracks = song_base
                    elif total_album_tracks != total:
                        total_tracks_is_inconsistent = True
                        total_album_tracks = None

                        if not no_warn:
                            warn('Within', path, 'album,')
                            yellow('     ', song_base,
                                   'has inconsistent total tracks with',
                                   song_that_gave_total_tracks)
                            if deep_warn:
                                print_songs(path, song_fs,
                                            artist_filter, album_filter,
                                            title_filter, sort_per_track=True,
                                            verbose=verbose, silent=silent,
                                            debug=debug)
                            warnings += 1

        if not silent:
            for song in missed_songs:
                warn(song[0], '[Track', song[1], '\b] is missing')
                warnings += 1

    return (filtered_songs, missed_songs, total_album_tracks, warnings,
            max_track_len)
Ejemplo n.º 5
0
 def retag(to):
     green('Retagging', unrooted_entity_path_root.replace('/', ' / '),
           '/', entity, 'to', to)
     # TODO(do we need to save here?)
     song.set(entity_tag, to, save=True, dryrun=dryrun)
Ejemplo n.º 6
0
def diff_files(root1,
               root2,
               name1,
               name2,
               ignore_files_only_dirs=False,
               ignore_not_existing=False,
               ignore_file_differences=True,
               extended=False,
               synchronize=False,
               delete_root1_files_only=False,
               dryrun=True,
               verbose=False,
               minimal_verbose=False,
               debug=False):
    diff_cnt = 0

    # minimal verbose: start
    index_c = '('  # always diff
    minimal_verbose_diff_cnt = -1
    # minimal verbose: end

    for dir_name, _, file_names in os.walk(root1):
        if dir_name == root1:
            continue
        else:
            unrooted = dir_name.replace(root1 + '/', '')
        target_dir_name = dir_name.replace(root1, root2)

        if minimal_verbose:
            if '/' not in unrooted:
                cur_index_c = unrooted[0:1].upper()
                if cur_index_c != index_c:
                    if minimal_verbose_diff_cnt != diff_cnt:
                        stdout(PROCESSING, end='')
                        minimal_verbose_diff_cnt = diff_cnt
                    stdout('\b' + cur_index_c, end='')
                    index_c = cur_index_c

        if not os.path.exists(target_dir_name) and not ignore_not_existing:
            if synchronize:
                if delete_root1_files_only:
                    remove_dir(root1, unrooted, dryrun=dryrun, verbose=True)
                else:
                    make_dir(root2, unrooted, dryrun=dryrun, verbose=True)
            else:
                if minimal_verbose:
                    stdout('\b' * len(PROCESSING), end='')
                red(target_dir_name, 'does not exist')

        if ignore_files_only_dirs:
            continue

        for file_name in file_names:

            if is_supported_file_ext(file_name, include_shadow_files=False):
                base_file = dir_name + '/' + file_name
                target_file = target_dir_name + '/' + file_name
                if os.path.exists(target_file):
                    if ignore_file_differences:
                        continue

                    action = (ConsoleColors.WARNING +
                              'DIFF .../{}/{}'.format(unrooted, file_name) +
                              ConsoleColors.ENDC)
                    if (extended and file_name.endswith(SONG_FILE_EXT) and
                            diff_tags(base_file,
                                      target_file,
                                      name1,
                                      name2,
                                      print_on_diff_f=(
                                          ('\n' if minimal_verbose else '') +
                                          action + ConsoleColors.ALERT +
                                          ' DIFF' + ConsoleColors.ENDC)
                                      if not synchronize else None,
                                      debug=debug)):

                        diff_cnt += 1

                        if synchronize:
                            copy_file(root1 + '/' + unrooted + '/' + file_name,
                                      root2 + '/' + unrooted + '/' + file_name,
                                      safe_copy=False,
                                      dryrun=dryrun,
                                      verbose=True,
                                      debug=debug)

                    elif verbose:
                        stdout(action, end='')
                        green(' OK')

                elif not ignore_not_existing:
                    if synchronize:
                        if delete_root1_files_only:
                            remove_file(root1 + '/' + unrooted,
                                        file_name,
                                        safe_remove=False,
                                        dryrun=dryrun,
                                        verbose=verbose,
                                        debug=debug)
                        else:
                            copy_file(root1 + '/' + unrooted + '/' + file_name,
                                      root2 + '/' + unrooted + '/' + file_name,
                                      safe_copy=False,
                                      dryrun=dryrun,
                                      verbose=True,
                                      debug=debug)
                    else:
                        if minimal_verbose:
                            stdout('\b' * len(PROCESSING), end='')
                        red(target_file, 'does not exist')

                    diff_cnt += 1

            elif verbose:
                warn(file_name, 'is ignored in diff!')

    return diff_cnt
Ejemplo n.º 7
0
def main():
    program = 'diff_songs'
    description = '''
    Diffs songs'''

    parser = argparse.ArgumentParser(prog=program, description=description)
    parser.add_argument('-p',
                        '--production',
                        help='Enable production run',
                        action='store_true')
    parser.add_argument('-x1',
                        '--path1',
                        type=str,
                        help='Path to music file 1 or dir 1 of music files')
    parser.add_argument('-x2',
                        '--path2',
                        type=str,
                        help='Path to music file 2 or dir 2 of music files')
    parser.add_argument('-n1',
                        '--name1',
                        type=str,
                        help='A name for music file 1 or dir 1 of music files')
    parser.add_argument('-n2',
                        '--name2',
                        type=str,
                        help='A name for music file 2 or dir 2 of music files')
    parser.add_argument('-r',
                        '--recursive',
                        help='Treat paths recursively',
                        action='store_true')
    parser.add_argument('-e',
                        '--extended',
                        help='Comparing also the song tags',
                        action='store_true')
    parser.add_argument('-v',
                        '--verbose',
                        help='Enable verbosity',
                        action='store_true')
    parser.add_argument('-d',
                        '--debug',
                        help='Enable debug',
                        action='store_true')
    parser.add_argument('-m',
                        '--minimal_verbose',
                        help='Enable minimal verbosity',
                        action='store_true')
    parser.add_argument('-s',
                        '--synchronize',
                        help='Synchronize differences',
                        action='store_true')
    parser.add_argument('--ignore-not-existing',
                        help='Ignore not-existing files',
                        action='store_true')
    parser.add_argument('--ignore-file-differences',
                        help='Ignore file differences',
                        action='store_true')
    parser.add_argument('--ignore-files-only-dirs',
                        help='Ignore files; only focuses on dirs',
                        action='store_true')
    parser.add_argument('--delete-orphan-files',
                        help='Delete orphan path2 files. '
                        'CAUTION is to be applied!',
                        action='store_true')

    args = parser.parse_args()
    dryrun = not args.production or get_env_var('DRYRUN')
    debug = args.debug or get_env_var('DEBUG')
    verbose = args.verbose or get_env_var('VERBOSE') or debug
    minimal_verbose = args.minimal_verbose or get_env_var('MINIMAL_VERBOSE')
    if args.production and not args.synchronize:
        fatal_error('Pointless production run while not synchronizing. '
                    'Give -s -p instead.')

    mark_dry_or_production_run(dryrun)

    root1 = args.path1
    root2 = args.path2

    if not root1 or not root2:
        parser.print_help()
        return

    name1 = args.name1 or '1'
    name2 = args.name2 or '2'

    if args.recursive:
        if root1.endswith('/'):
            root1 = root1[:-1]  # needed for checks below
        if root2.endswith('/'):
            root2 = root2[:-1]  # needed for checks below

        if args.synchronize:
            stdout('=== Diff\'ing and Syncing music files ===\n')
        else:
            stdout('=== Diff\'ing music files ===\n')

        stdout('SOURCE:', root1)
        stdout('TARGET:', root2)
        stdout()

        cnt = diff_files(root1,
                         root2,
                         name1,
                         name2,
                         args.ignore_files_only_dirs,
                         args.ignore_not_existing,
                         args.ignore_file_differences,
                         args.extended,
                         args.synchronize,
                         dryrun=dryrun,
                         verbose=verbose,
                         minimal_verbose=minimal_verbose,
                         debug=debug)
        if minimal_verbose:
            stdout('\bCOMPLETE\n')
        elif cnt:
            stdout()
        diff_cnt = cnt

        if not args.ignore_not_existing and args.delete_orphan_files:
            stdout('CHECKING TARGET FOR ORPHANS (MIND!)')
            stdout()
            cnt = diff_files(
                root2,
                root1,
                name2,
                name1,  # mind, swapped
                args.ignore_files_only_dirs,
                synchronize=args.synchronize,
                delete_root1_files_only=True,  # in reality root2
                dryrun=dryrun,
                verbose=verbose,
                minimal_verbose=minimal_verbose,
                debug=debug)
            if minimal_verbose:
                stdout('\bCOMPLETE\n')
            elif cnt:
                stdout()
            diff_cnt += cnt

        if diff_cnt:
            if args.synchronize:
                stdout(diff_cnt, 'diffs corrected')
            else:
                stdout(diff_cnt, 'diffs observed')
        else:
            stdout('No diff observed')

    elif diff_tags(root1, root2, name1, name2):
        red('Different')
    else:
        green('Equal')
Ejemplo n.º 8
0
        dryrun=dryrun,
        verbose=verbose,
        silent=silent)
    remove_file('.',
                'test3.txt',
                safe_remove=safe_remove,
                dryrun=dryrun,
                verbose=verbose,
                silent=silent)
    remove_file('.',
                'test3 (1).txt',
                safe_remove=safe_remove,
                dryrun=dryrun,
                verbose=verbose,
                silent=silent)
    cyan('test_file_manipulation_2 OK')


if __name__ == "__main__":
    test_colours()
    test_windows()
    test_error()
    test_to_camel_case()
    test_file_extension()
    test_file_manipulation_1()
    test_file_manipulation_2()
    green('ALL TESTS PASS. Happy day :)')
    cyan('Final test is a fatal error:')
    fatal_error('The world exploded')
    error('SHOULD NOT HAVE COME HERE!')