diff --git a/utils/mapping_generator.py b/utils/mapping_generator.py index bc3983ed1eacd4da4953f907dfd68dc04bceec66..3449f47bb54efa6377dc792ee61e31b324ab3c54 100755 --- a/utils/mapping_generator.py +++ b/utils/mapping_generator.py @@ -18,6 +18,7 @@ import shutil import math import os +import subprocess import click import yaml @@ -77,6 +78,31 @@ def display_mappables_as_yaml(mappables): click.echo(yaml.dump(document, width=4096)) +def validate_output_height(ctx, param, value): + """ + Validates the output height value, ensuring it is within the correct range. + + :param ctx: Click context. + :type ctx: click.Context + + :param param: Click option that is being validated. + :type param: click.Option + + :param value: Option value. + :type value: any + + :raises click.BadParameter: If the passed-in value is out of bounds. + + :returns: Validated value. + :rtype: int + """ + + if value < 0 or value > 2147483647: + raise click.BadParameter('must be a non-negative integer between 0 and 2147483647') + + return value + + # Allow use of short option for showing help. CONTEXT_SETTINGS = dict(help_option_names=['-h', '--help']) @@ -150,9 +176,14 @@ def info(template, search, output_format): @click.argument('parameters', type=click.File('r')) @click.argument('output', type=click.Path(dir_okay=False, writable=True, allow_dash=True)) @click.option('--force-overwrite', '-f', is_flag=True, help='force overwriting output file') -def apply(template, parameters, output, force_overwrite): +@click.option('--output-height', '-H', default=0, callback=validate_output_height, help='output image height for png') +def apply(template, parameters, output, force_overwrite, output_height): """ - Applies user-provided parameters against the template, and outputs the result. + Applies user-provided PARAMETERS against the TEMPLATE, and places the result into OUTPUT file. The output file + can be either a filename or '-' for stdout. + + Output format is based on passed-in file extension. Currently supported file extensions/formats are: svg. When + output is '-' (stdout), the output format is always svg. """ template_tree = ElementTree.fromstring(template.read()) @@ -178,8 +209,17 @@ def apply(template, parameters, output, force_overwrite): if os.path.isdir(output): raise click.FileError(output, 'output must be a file path') - with click.open_file(output, 'wb') as output_file: - output_file.write(ElementTree.tostring(template_tree)) + if output.endswith('.svg') or output == '-': + with click.open_file(output, 'wb') as output_file: + output_file.write(ElementTree.tostring(template_tree)) + elif output.endswith('.png'): + command = ['inkscape', '--pipe', '--export-filename', output] + command += ['--export-height', str(output_height)] + subprocess.run(command, input=ElementTree.tostring(template_tree), check=True) + else: + raise click.BadParameter( + f'unsupported extension/output format ({ os.path.splitext(output)[-1] or "none specified" })', + param=output, param_hint='output') if __name__ == '__main__':