From b8aba4d3822c44edf0e76bc737a23907c6f20805 Mon Sep 17 00:00:00 2001 From: drewcassidy Date: Sat, 10 Apr 2021 01:28:03 -0700 Subject: [PATCH] move common code to its own module and out of __init__.py --- quicktex/cli/__init__.py | 27 ----------------- quicktex/cli/common.py | 62 ++++++++++++++++++++++++++++++++++++++++ quicktex/cli/decode.py | 45 +++++++---------------------- 3 files changed, 72 insertions(+), 62 deletions(-) create mode 100644 quicktex/cli/common.py diff --git a/quicktex/cli/__init__.py b/quicktex/cli/__init__.py index 84ea843..e69de29 100644 --- a/quicktex/cli/__init__.py +++ b/quicktex/cli/__init__.py @@ -1,27 +0,0 @@ -from PIL import Image -from typing import List -import click - - -def get_decoded_extensions(feature: str = 'open') -> List[str]: - """Gets a list of extensions for Pillow formats supporting a supplied feature""" - extensions = Image.registered_extensions() # using registered_extensions() triggers lazy loading of format data - formats = getattr(Image, feature.upper()).keys() - - return [ext for ext, fmt in extensions.items() if fmt in formats] - - -# noinspection PyUnusedLocal -def validate_decoded_extension(ctx, param, value): - """Check if an extension for a decoded image is valid""" - if value[0] != '.': - value = '.' + value - - if value not in decoded_extensions: - raise click.BadParameter(f'Invalid extension for decoded file. Valid extensions are:\n{decoded_extensions}') - - return value - - -decoded_extensions = get_decoded_extensions() -encoded_extensions = '.dds' diff --git a/quicktex/cli/common.py b/quicktex/cli/common.py new file mode 100644 index 0000000..09c7baf --- /dev/null +++ b/quicktex/cli/common.py @@ -0,0 +1,62 @@ +from PIL import Image +from typing import List +import pathlib +import click + + +def get_decoded_extensions(feature: str = 'open') -> List[str]: + """Gets a list of extensions for Pillow formats supporting a supplied feature""" + extensions = Image.registered_extensions() # using registered_extensions() triggers lazy loading of format data + formats = getattr(Image, feature.upper()).keys() + + return [ext for ext, fmt in extensions.items() if fmt in formats] + + +# noinspection PyUnusedLocal +def validate_decoded_extension(ctx, param, value) -> str: + """Check if an extension for a decoded image is valid""" + if value[0] != '.': + value = '.' + value + + if value not in decoded_extensions: + raise click.BadParameter(f'Invalid extension for decoded file. Valid extensions are:\n{decoded_extensions}') + + return value + + +decoded_extensions = get_decoded_extensions() +encoded_extensions = '.dds' + + +def path_pairs(inputs, output, suffix, extension): + """ + Generates pairs of (inpath, outpath) for the given parameters + :param inputs: A list of input paths to read from + :param output: output to write to. can be a file, directory, or None to convert in place + :param suffix: suffix to add to destinations + :param extension: extension to use for destinations + :return: A list of pairs of (inpath, outpath) + """ + + if len(inputs) < 1: + raise click.BadArgumentUsage('No input files were provided.') + + inpaths = [pathlib.Path(i) for i in inputs] + + if not output: + # decode in place + return [(inpath, inpath.with_name(inpath.stem + suffix + extension)) for inpath in inpaths] + + else: + outpath = pathlib.Path(output) + if outpath.is_file(): + # decode to a file + if len(inputs) > 1: + raise click.BadOptionUsage('output', 'Output is a single file, but multiple input files were provided.') + if outpath.suffix not in decoded_extensions: + raise click.BadOptionUsage('output', f'File has incorrect extension for decoded file. Valid extensions are:\n{decoded_extensions}') + + return [(inpath, outpath) for inpath in inpaths] + else: + # decode to directory + return [(inpath, outpath / (inpath.stem + suffix + extension)) for inpath in inpaths] diff --git a/quicktex/cli/decode.py b/quicktex/cli/decode.py index 189ee19..7674cc1 100644 --- a/quicktex/cli/decode.py +++ b/quicktex/cli/decode.py @@ -1,10 +1,8 @@ import click import os.path import quicktex.dds as dds -import quicktex.image_utils -import quicktex.cli +import quicktex.cli.common as common from PIL import Image -from pathlib import Path @click.command() @@ -12,7 +10,7 @@ from pathlib import Path @click.option('-r', '--remove', is_flag=True, help="Remove input images after converting.") @click.option('-s', '--suffix', type=str, default='', help="Suffix to append to output file(s). Ignored if output is a single file.") @click.option('-x', '--extension', - callback=quicktex.cli.validate_decoded_extension, + callback=common.validate_decoded_extension, type=str, default='.png', show_default=True, help="Extension to use for output. Ignored if output is a single file. Output filetype is deduced from this") @click.option('-o', '--output', @@ -22,45 +20,22 @@ from pathlib import Path def decode(flip, remove, suffix, extension, output, filenames): """Decode DDS files to images.""" - if len(filenames) < 1: - raise click.BadArgumentUsage('No input files were provided.') + path_pairs = common.path_pairs(filenames, output, suffix, extension) - # decode in place - def make_outpath(p): - return p.with_name(p.stem + suffix + extension) + with click.progressbar(path_pairs, show_eta=False, show_pos=True, item_show_func=lambda x: str(x[0]) if x else '') as bar: + for inpath, outpath in bar: + if inpath.suffix != '.dds': + raise click.BadArgumentUsage(f"Input file '{inpath}' is not a DDS file.") - if output: - outpath = Path(output) - if outpath.is_file(): - # decode to a file - if len(filenames) > 1: - raise click.BadOptionUsage('output', 'Output is a single file, but multiple input files were provided.') - if outpath.suffix not in quicktex.cli.decoded_extensions: - raise click.BadOptionUsage('output', f'File has incorrect extension for decoded file. Valid extensions are:\n{quicktex.cli.decoded_extensions}') - - # noinspection PyUnusedLocal - def make_outpath(p): - return outpath - else: - # decode to directory - def make_outpath(p): - return outpath / (p.stem + suffix + extension) - - with click.progressbar(filenames, show_eta=False, show_pos=True, item_show_func=lambda x: str(x) if x else '') as bar: - for filename in bar: - filepath = Path(filename) - if filepath.suffix != '.dds': - raise click.BadArgumentUsage(f"Input file '{filename}' is not a DDS file") - - image = dds.read(filepath).decode() + image = dds.read(inpath).decode() if flip: image = image.transpose(Image.FLIP_TOP_BOTTOM) - image.save(make_outpath(filepath)) + image.save(outpath) if remove: - os.remove(filepath) + os.remove(inpath) if __name__ == '__main__':