This commit is contained in:
Jamie Hardt
2024-07-01 21:23:10 -07:00
parent 649b1189ee
commit 60bdb32dea
2 changed files with 50 additions and 21 deletions

View File

@@ -1,25 +1,27 @@
"""
mfbatch main - Command entrypoint for mfbatch
"""
# __main__.py # __main__.py
import os import os
from glob import glob from glob import glob
from subprocess import run from subprocess import run
import sys
from optparse import OptionParser from optparse import OptionParser
import shlex import shlex
from typing import Callable from typing import Callable
import inspect import inspect
from tqdm import tqdm
from mfbatch.util import readline_with_escaped_newlines from mfbatch.util import readline_with_escaped_newlines
import mfbatch.metaflac as flac import mfbatch.metaflac as flac
from mfbatch.commands import BatchfileParser from mfbatch.commands import BatchfileParser
from tqdm import tqdm
# import readline
def execute_batch_list(batch_list_path: str, dry_run: bool, interactive: bool): def execute_batch_list(batch_list_path: str, dry_run: bool, interactive: bool):
with open(batch_list_path, mode='r') as f: "Acts on a batch list"
with open(batch_list_path, mode='r', encoding='utf-8') as f:
parser = BatchfileParser() parser = BatchfileParser()
parser.dry_run = dry_run parser.dry_run = dry_run
@@ -29,25 +31,28 @@ def execute_batch_list(batch_list_path: str, dry_run: bool, interactive: bool):
def create_batch_list(command_file: str): def create_batch_list(command_file: str):
"""
with open(command_file, mode='w') as f: Read all FLAC files in the cwd recursively and create a batchfile that
re-creates all of their metadata.
"""
with open(command_file, mode='w', encoding='utf-8') as f:
f.write("# mfbatch\n\n") f.write("# mfbatch\n\n")
metadatums = {} metadatums = {}
flac_files = glob('./**/*.flac', recursive=True) flac_files = glob('./**/*.flac', recursive=True)
flac_files = sorted(flac_files) flac_files = sorted(flac_files)
for path in tqdm(flac_files, unit='File', desc='Scanning FLAC files'): for path in tqdm(flac_files, unit='File', desc='Scanning FLAC files'):
this_file_metadata = flac.read_metadata(path) this_file_metadata = flac.read_metadata(path)
for this_key in this_file_metadata.keys(): for this_key, this_value in this_file_metadata.items():
if this_key not in metadatums: if this_key not in metadatums:
f.write(f":set {this_key} " f.write(f":set {this_key} "
f"{shlex.quote(this_file_metadata[this_key])}\n") f"{shlex.quote(this_value)}\n")
metadatums[this_key] = this_file_metadata[this_key] metadatums[this_key] = this_value
else: else:
if this_file_metadata[this_key] != metadatums[this_key]: if this_value != metadatums[this_key]:
f.write(f":set {this_key} " f.write(f":set {this_key} "
f"{shlex.quote(this_file_metadata[this_key])}" f"{shlex.quote(this_value)}"
"\n") "\n")
metadatums[this_key] = this_file_metadata[this_key] metadatums[this_key] = this_value
keys = list(metadatums.keys()) keys = list(metadatums.keys())
for key in keys: for key in keys:
@@ -59,6 +64,9 @@ def create_batch_list(command_file: str):
def main(): def main():
"""
Entry point implementation
"""
op = OptionParser(usage="%prog (-c | -e | -W) [options]") op = OptionParser(usage="%prog (-c | -e | -W) [options]")
op.add_option('-c', '--create', default=False, op.add_option('-c', '--create', default=False,
@@ -100,7 +108,7 @@ def main():
if isinstance(meth, Callable): if isinstance(meth, Callable):
print(f"{inspect.cleandoc(meth.__doc__ or '')}\n") print(f"{inspect.cleandoc(meth.__doc__ or '')}\n")
exit(0) sys.exit(0)
mode_given = False mode_given = False
if options.path is not None: if options.path is not None:
@@ -113,7 +121,7 @@ def main():
if options.edit: if options.edit:
mode_given = True mode_given = True
editor_command = [os.getenv('EDITOR'), options.batchfile] editor_command = [os.getenv('EDITOR'), options.batchfile]
run(editor_command) run(editor_command, check=True)
if options.write: if options.write:
mode_given = True mode_given = True
@@ -123,7 +131,7 @@ def main():
if mode_given == False: if mode_given == False:
op.print_usage() op.print_usage()
exit(-1) sys.exit(-1)
if __name__ == "__main__": if __name__ == "__main__":

View File

@@ -1,3 +1,6 @@
"""
mfbatch commands and batchfile parser
"""
# commands.py # commands.py
# mfbatch # mfbatch
@@ -14,6 +17,7 @@ from typing import Dict, Tuple, Optional
class UnrecognizedCommandError(Exception): class UnrecognizedCommandError(Exception):
"A command in the batchfile was not recognized"
command: str command: str
line: int line: int
@@ -23,6 +27,10 @@ class UnrecognizedCommandError(Exception):
class CommandArgumentError(Exception): class CommandArgumentError(Exception):
"""
A command line in the batchfile did not have the correct number of argumets
"""
command: str command: str
line: int line: int
@@ -32,6 +40,9 @@ class CommandArgumentError(Exception):
class CommandEnv: class CommandEnv:
"""
Stores values and state for commands
"""
metadatums: Dict[str, str] metadatums: Dict[str, str]
incr: Dict[str, str] incr: Dict[str, str]
patterns: Dict[str, Tuple[str, str, str]] patterns: Dict[str, Tuple[str, str, str]]
@@ -41,21 +52,31 @@ class CommandEnv:
artwork_desc: Optional[str] artwork_desc: Optional[str]
def __init__(self) -> None: def __init__(self) -> None:
self.metadatums = dict() self.metadatums = {}
self.incr = dict() self.incr = {}
self.patterns = dict() self.patterns = {}
self.onces = dict() self.onces = {}
def unset_key(self, k): def unset_key(self, k):
"""
Delete a key from the environment
"""
del self.metadatums[k] del self.metadatums[k]
self.incr.pop(k, None) self.incr.pop(k, None)
self.patterns.pop(k, None) self.patterns.pop(k, None)
def set_pattern(self, to: str, frm: str, pattern: str, repl: str): def set_pattern(self, to: str, frm: str, pattern: str, repl: str):
"""
Establish a pattern replacement in the environment
"""
self.patterns[to] = (frm, pattern, repl) self.patterns[to] = (frm, pattern, repl)
def evaluate_patterns(self): def evaluate_patterns(self):
"""
Evaluate all patterns, this must run once and exactly once before
writing file metadata.
"""
for to_key in self.patterns.keys(): for to_key in self.patterns.keys():
from_key, pattern, replacement = self.patterns[to_key] from_key, pattern, replacement = self.patterns[to_key]
from_value = self.metadatums[from_key] from_value = self.metadatums[from_key]