From 334fa56a2c87bd3dc0d1768f1a21531e3a5baff9 Mon Sep 17 00:00:00 2001 From: Jamie Hardt Date: Sat, 24 May 2025 20:59:53 -0700 Subject: [PATCH 01/10] Update __main__.py --- mfbatch/__main__.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/mfbatch/__main__.py b/mfbatch/__main__.py index 988c158..4078148 100644 --- a/mfbatch/__main__.py +++ b/mfbatch/__main__.py @@ -105,6 +105,9 @@ def main(): op.add_argument('-c', '--create', default=False, action='store_true', help='create a new list') + + # add an option here to get a file list from a file instead of + # from cwd. op.add_argument('-e', '--edit', action='store_true', help="open batch file in the default editor", default=False) From 2c135d413e237f21bac358f3568f939ce1a3c818 Mon Sep 17 00:00:00 2001 From: Jamie Hardt Date: Sat, 24 May 2025 21:30:14 -0700 Subject: [PATCH 02/10] twiddle text --- mfbatch/__main__.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/mfbatch/__main__.py b/mfbatch/__main__.py index 4078148..da9c522 100644 --- a/mfbatch/__main__.py +++ b/mfbatch/__main__.py @@ -106,8 +106,7 @@ def main(): action='store_true', help='create a new list') - # add an option here to get a file list from a file instead of - # from cwd. + # add an option here to get a file list from a file instead of from cwd. op.add_argument('-e', '--edit', action='store_true', help="open batch file in the default editor", default=False) From ba3b0dbf96ca24ad76d4c088480cebf1a69a5b5c Mon Sep 17 00:00:00 2001 From: Jamie Hardt Date: Sun, 25 May 2025 08:27:11 -0700 Subject: [PATCH 03/10] Added implementation --- mfbatch/__main__.py | 39 ++++++++++++++++++--------------------- 1 file changed, 18 insertions(+), 21 deletions(-) diff --git a/mfbatch/__main__.py b/mfbatch/__main__.py index da9c522..e719da8 100644 --- a/mfbatch/__main__.py +++ b/mfbatch/__main__.py @@ -8,7 +8,7 @@ from subprocess import CalledProcessError, run import sys from argparse import ArgumentParser import shlex -from typing import Callable +from typing import Callable, List import inspect from tqdm import tqdm @@ -29,33 +29,21 @@ def execute_batch_list(batch_list_path: str, dry_run: bool, interactive: bool): parser.eval(line, line_no, interactive) -def create_batch_list(command_file: str, recursive=True, sort_mode='path'): +def create_batch_list(flac_files: List[str], command_file: str, + sort_mode='path'): """ Read all FLAC files in the cwd and create a batchfile that re-creates all of their metadata. - :param recursive: Recursively enter directories + :param flac_files: Paths of files to create batchfile from + :param command_file: What to name the new batchfile :param sort_mode: Order of paths in the batch list. Either 'path', 'mtime', 'ctime', 'name' + :param input_files: FLAC files to scan """ with open(command_file, mode='w', encoding='utf-8') as f: f.write("# mfbatch\n\n") -# f.write(""" -# # :set DESCRIPTION "" -# # :set TITLE "" -# # :set VERSION "" -# # :set ALBUM "" -# # :set ARTIST "" -# # :set TRACKNUMBER "" -# # :set COPYRIGHT "" -# # :set LICENSE "" -# # :set CONTACT "" -# # :set ORGAIZATION "" -# # :set LOCATION "" -# # :set MICROPHONE "" -# """) metadatums = {} - flac_files = glob('./**/*.flac', recursive=recursive) if sort_mode == 'path': flac_files = sorted(flac_files) @@ -105,8 +93,10 @@ def main(): op.add_argument('-c', '--create', default=False, action='store_true', help='create a new list') - - # add an option here to get a file list from a file instead of from cwd. + op.add_argument('-F', '--from-file', metavar='FILE_LIST', action='store', + default=None, help="Instead of scanning directory for " + "FLAC files, get file paths from FILE_LIST when creating " + "a new list") op.add_argument('-e', '--edit', action='store_true', help="open batch file in the default editor", default=False) @@ -154,7 +144,14 @@ def main(): if options.create: mode_given = True - create_batch_list(options.batchfile, sort_mode=options.sort) + + if options.from_file: + with open(options.from_file, 'r') as from_file: + flac_files = from_file.readlines() + else: + flac_files = glob('./**/*.flac', recursive=True) + + create_batch_list(flac_files, options.batchfile, sort_mode=options.sort) if options.edit: mode_given = True From 549f49da31b970c056fcbdc66c31e347300317e9 Mon Sep 17 00:00:00 2001 From: Jamie Hardt Date: Sun, 25 May 2025 08:28:32 -0700 Subject: [PATCH 04/10] autopep --- mfbatch/__main__.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/mfbatch/__main__.py b/mfbatch/__main__.py index e719da8..2bb3c0b 100644 --- a/mfbatch/__main__.py +++ b/mfbatch/__main__.py @@ -29,7 +29,7 @@ def execute_batch_list(batch_list_path: str, dry_run: bool, interactive: bool): parser.eval(line, line_no, interactive) -def create_batch_list(flac_files: List[str], command_file: str, +def create_batch_list(flac_files: List[str], command_file: str, sort_mode='path'): """ Read all FLAC files in the cwd and create a batchfile that re-creates all @@ -151,7 +151,8 @@ def main(): else: flac_files = glob('./**/*.flac', recursive=True) - create_batch_list(flac_files, options.batchfile, sort_mode=options.sort) + create_batch_list(flac_files, options.batchfile, + sort_mode=options.sort) if options.edit: mode_given = True From 49898322472c58c27d62d060bd51bbc744935ef1 Mon Sep 17 00:00:00 2001 From: Jamie Hardt Date: Sun, 25 May 2025 08:29:57 -0700 Subject: [PATCH 05/10] autopep (added explicit encoding for from-file) --- mfbatch/__main__.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mfbatch/__main__.py b/mfbatch/__main__.py index 2bb3c0b..eba6cca 100644 --- a/mfbatch/__main__.py +++ b/mfbatch/__main__.py @@ -146,7 +146,8 @@ def main(): mode_given = True if options.from_file: - with open(options.from_file, 'r') as from_file: + with open(options.from_file, mode='r', + encoding='utf-8') as from_file: flac_files = from_file.readlines() else: flac_files = glob('./**/*.flac', recursive=True) From 532f67e3a8980045afbd4519518ea88ea22c0432 Mon Sep 17 00:00:00 2001 From: Jamie Hardt Date: Sun, 25 May 2025 09:32:59 -0700 Subject: [PATCH 06/10] Refactored some code --- mfbatch/__main__.py | 99 ++++++++++++++++++++++++++++----------------- 1 file changed, 61 insertions(+), 38 deletions(-) diff --git a/mfbatch/__main__.py b/mfbatch/__main__.py index eba6cca..d68ecb6 100644 --- a/mfbatch/__main__.py +++ b/mfbatch/__main__.py @@ -10,6 +10,7 @@ from argparse import ArgumentParser import shlex from typing import Callable, List import inspect +from io import StringIO from tqdm import tqdm @@ -29,6 +30,53 @@ def execute_batch_list(batch_list_path: str, dry_run: bool, interactive: bool): parser.eval(line, line_no, interactive) +def sort_flac_files(file_list, mode): + if mode == 'path': + return sorted(file_list) + elif mode == 'mtime': + return sorted(file_list, key=os.path.getmtime) + elif mode == 'ctime': + return sorted(file_list, key=os.path.getctime) + elif mode == 'name': + return sorted(file_list, key=os.path.basename) + else: + return file_list + + +def write_batchfile_entries_for_file(path, metadatums): + buffer = StringIO() + + try: + this_file_metadata = metadata_funcs.read_metadata(path) + + except CalledProcessError as e: + buffer.write(f"# !!! METAFLAC ERROR ({e.returncode}) while reading " + f"metadata from the file {path}\n\n") + return metadatums, buffer + + for this_key, this_value in this_file_metadata.items(): + if this_key not in metadatums: + buffer.write(f":set {this_key} " + f"{shlex.quote(this_value)}\n") + metadatums[this_key] = this_value + else: + if this_value != metadatums[this_key]: + buffer.write(f":set {this_key} " + f"{shlex.quote(this_value)}" + "\n") + metadatums[this_key] = this_value + + keys = list(metadatums.keys()) + for key in keys: + if key not in this_file_metadata: + buffer.write(f":unset {key}\n") + del metadatums[key] + + buffer.write(path + "\n\n") + + return metadatums, buffer + + def create_batch_list(flac_files: List[str], command_file: str, sort_mode='path'): """ @@ -36,52 +84,27 @@ def create_batch_list(flac_files: List[str], command_file: str, of their metadata. :param flac_files: Paths of files to create batchfile from - :param command_file: What to name the new batchfile + :param command_file: Name of new batchfile :param sort_mode: Order of paths in the batch list. Either 'path', 'mtime', 'ctime', 'name' :param input_files: FLAC files to scan """ + + flac_files = sort_flac_files(flac_files, sort_mode) + with open(command_file, mode='w', encoding='utf-8') as f: - f.write("# mfbatch\n\n") metadatums = {} - if sort_mode == 'path': - flac_files = sorted(flac_files) - elif sort_mode == 'mtime': - flac_files = sorted(flac_files, key=os.path.getmtime) - elif sort_mode == 'ctime': - flac_files = sorted(flac_files, key=os.path.getctime) - elif sort_mode == 'name': - flac_files = sorted(flac_files, key=os.path.basename) + f.write("# mfbatch\n\n") - for path in tqdm(flac_files, unit='File', desc='Scanning FLAC files'): - try: - this_file_metadata = metadata_funcs.read_metadata(path) - except CalledProcessError as e: - f.write(f"# !!! METAFLAC ERROR ({e.returncode}) while reading " - f"metadata from the file {path}\n\n") - continue + for path in tqdm(flac_files, unit='File', + desc='Scanning with metaflac...'): - for this_key, this_value in this_file_metadata.items(): - if this_key not in metadatums: - f.write(f":set {this_key} " - f"{shlex.quote(this_value)}\n") - metadatums[this_key] = this_value - else: - if this_value != metadatums[this_key]: - f.write(f":set {this_key} " - f"{shlex.quote(this_value)}" - "\n") - metadatums[this_key] = this_value - - keys = list(metadatums.keys()) - for key in keys: - if key not in this_file_metadata: - f.write(f":unset {key}\n") - del metadatums[key] - - f.write(path + "\n\n") + metadatums, buffer = write_batchfile_entries_for_file(path, + metadatums) + f.write(buffer.read()) + f.write("# mfbatch create batchlist operation complete\n") def main(): """ @@ -94,8 +117,8 @@ def main(): action='store_true', help='create a new list') op.add_argument('-F', '--from-file', metavar='FILE_LIST', action='store', - default=None, help="Instead of scanning directory for " - "FLAC files, get file paths from FILE_LIST when creating " + default=None, help="get file paths from FILE_LIST when " + "creating, instead of scanning directory" "a new list") op.add_argument('-e', '--edit', action='store_true', help="open batch file in the default editor", From 2d4ea5a8d8df00785cfff10295c41c961e5ee3d0 Mon Sep 17 00:00:00 2001 From: Jamie Hardt Date: Sun, 25 May 2025 10:52:59 -0700 Subject: [PATCH 07/10] /John/George --- mfbatch/__main__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mfbatch/__main__.py b/mfbatch/__main__.py index d68ecb6..9c73125 100644 --- a/mfbatch/__main__.py +++ b/mfbatch/__main__.py @@ -104,7 +104,7 @@ def create_batch_list(flac_files: List[str], command_file: str, metadatums) f.write(buffer.read()) - f.write("# mfbatch create batchlist operation complete\n") + f.write("# mfbatch: create batchlist operation complete\n") def main(): """ From 538da34a0c30e510b8a687cca7fad4d8907aac69 Mon Sep 17 00:00:00 2001 From: Jamie Hardt Date: Sun, 25 May 2025 10:55:09 -0700 Subject: [PATCH 08/10] lint --- mfbatch/__main__.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/mfbatch/__main__.py b/mfbatch/__main__.py index 9c73125..e64cc34 100644 --- a/mfbatch/__main__.py +++ b/mfbatch/__main__.py @@ -31,19 +31,21 @@ def execute_batch_list(batch_list_path: str, dry_run: bool, interactive: bool): def sort_flac_files(file_list, mode): + "Sort flac files" if mode == 'path': return sorted(file_list) - elif mode == 'mtime': + if mode == 'mtime': return sorted(file_list, key=os.path.getmtime) - elif mode == 'ctime': + if mode == 'ctime': return sorted(file_list, key=os.path.getctime) - elif mode == 'name': + if mode == 'name': return sorted(file_list, key=os.path.basename) - else: - return file_list + + return file_list def write_batchfile_entries_for_file(path, metadatums): + "Create batchfile entries for `path`" buffer = StringIO() try: @@ -106,6 +108,7 @@ def create_batch_list(flac_files: List[str], command_file: str, f.write("# mfbatch: create batchlist operation complete\n") + def main(): """ Entry point implementation From ecc93640c269783c7ef258651cca53dcdbb1a6f4 Mon Sep 17 00:00:00 2001 From: Jamie Hardt Date: Sun, 25 May 2025 11:23:55 -0700 Subject: [PATCH 09/10] Completed the feature. --- mfbatch/__main__.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/mfbatch/__main__.py b/mfbatch/__main__.py index e64cc34..5f2c62f 100644 --- a/mfbatch/__main__.py +++ b/mfbatch/__main__.py @@ -8,7 +8,7 @@ from subprocess import CalledProcessError, run import sys from argparse import ArgumentParser import shlex -from typing import Callable, List +from typing import Callable, List, Tuple import inspect from io import StringIO @@ -44,7 +44,7 @@ def sort_flac_files(file_list, mode): return file_list -def write_batchfile_entries_for_file(path, metadatums): +def write_batchfile_entries_for_file(path, metadatums) -> Tuple[dict, str]: "Create batchfile entries for `path`" buffer = StringIO() @@ -54,7 +54,7 @@ def write_batchfile_entries_for_file(path, metadatums): except CalledProcessError as e: buffer.write(f"# !!! METAFLAC ERROR ({e.returncode}) while reading " f"metadata from the file {path}\n\n") - return metadatums, buffer + return metadatums, buffer.getvalue() for this_key, this_value in this_file_metadata.items(): if this_key not in metadatums: @@ -75,8 +75,8 @@ def write_batchfile_entries_for_file(path, metadatums): del metadatums[key] buffer.write(path + "\n\n") - - return metadatums, buffer + + return metadatums, buffer.getvalue() def create_batch_list(flac_files: List[str], command_file: str, @@ -104,7 +104,7 @@ def create_batch_list(flac_files: List[str], command_file: str, metadatums, buffer = write_batchfile_entries_for_file(path, metadatums) - f.write(buffer.read()) + f.write(buffer) f.write("# mfbatch: create batchlist operation complete\n") @@ -170,14 +170,16 @@ def main(): if options.create: mode_given = True + flac_files: List[str] = [] if options.from_file: with open(options.from_file, mode='r', encoding='utf-8') as from_file: - flac_files = from_file.readlines() + flac_files = [line.strip() for line in from_file.readlines()] else: flac_files = glob('./**/*.flac', recursive=True) + # print(flac_files) create_batch_list(flac_files, options.batchfile, sort_mode=options.sort) From 49055ef881c3d304bc2140ed8f399b2bc22ca775 Mon Sep 17 00:00:00 2001 From: Jamie Hardt Date: Sun, 25 May 2025 11:25:54 -0700 Subject: [PATCH 10/10] lint --- mfbatch/__main__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mfbatch/__main__.py b/mfbatch/__main__.py index 5f2c62f..44dae88 100644 --- a/mfbatch/__main__.py +++ b/mfbatch/__main__.py @@ -75,7 +75,7 @@ def write_batchfile_entries_for_file(path, metadatums) -> Tuple[dict, str]: del metadatums[key] buffer.write(path + "\n\n") - + return metadatums, buffer.getvalue()