From 1f3ef9b2368e59f83341f3089d44106b213d466d Mon Sep 17 00:00:00 2001 From: Eric Lapouyade Date: Thu, 30 Sep 2021 17:08:05 +0200 Subject: [PATCH] Add quiet option, update doc, modify test --- CHANGES.rst | 6 +++++ docs/index.rst | 24 ++++++++++++++++++ docxtpl/__init__.py | 2 +- docxtpl/__main__.py | 21 ++++++++++----- tests/main.py | 21 --------------- tests/module_execute.py | 22 ++++++++++++++++ ...for_main_test.json => module_execute.json} | 0 ...main_test.docx => module_execute_tpl.docx} | Bin 8 files changed, 67 insertions(+), 29 deletions(-) delete mode 100644 tests/main.py create mode 100644 tests/module_execute.py rename tests/templates/{json_for_main_test.json => module_execute.json} (100%) rename tests/templates/{template_for_main_test.docx => module_execute_tpl.docx} (100%) diff --git a/CHANGES.rst b/CHANGES.rst index 8e69e64..513eddb 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -1,3 +1,9 @@ +0.14.0 (2021-09-30) +------------------- +- One can now use python -m docxtpl on command line + to generate a docx from a template and a json file as a context + Thanks to Lcrs123@github + 0.12.0 (2021-08-15) ------------------- - Code has be split into many files for better readability diff --git a/docs/index.rst b/docs/index.rst index 0c328c3..900c460 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -387,6 +387,30 @@ Then in your template, you will be able to use:: Euros price : {{ price_dollars|multiply_by(0.88) }} + +Command-line execution +---------------------- + +One can use `docxtpl` module directly on command line to generate a docx from a template and a json file as a context:: + + usage: python -m docxtpl [-h] [-o] [-q] template_path json_path output_filename + + Make docx file from existing template docx and json data. + + positional arguments: + template_path The path to the template docx file. + json_path The path to the json file with the data. + output_filename The filename to save the generated docx. + + optional arguments: + -h, --help show this help message and exit + -o, --overwrite If output file already exists, overwrites without asking + for confirmation + -q, --quiet Do not display unnecessary messages + + +See tests/module_execute.py for an example. + Examples -------- diff --git a/docxtpl/__init__.py b/docxtpl/__init__.py index 280de22..563b398 100644 --- a/docxtpl/__init__.py +++ b/docxtpl/__init__.py @@ -4,7 +4,7 @@ Created : 2015-03-12 @author: Eric Lapouyade """ -__version__ = '0.12.0' +__version__ = '0.14.0' # flake8: noqa from .inline_image import InlineImage diff --git a/docxtpl/__main__.py b/docxtpl/__main__.py index 2cf5427..0bc685c 100644 --- a/docxtpl/__main__.py +++ b/docxtpl/__main__.py @@ -7,11 +7,12 @@ TEMPLATE_ARG = 'template_path' JSON_ARG = 'json_path' OUTPUT_ARG = 'output_filename' OVERWRITE_ARG = 'overwrite' +QUIET_ARG = 'quiet' def make_arg_parser() -> argparse.ArgumentParser: parser = argparse.ArgumentParser( - usage=f'docxtpl [-h] [-o] {TEMPLATE_ARG} {JSON_ARG} {OUTPUT_ARG}', + usage=f'python -m docxtpl [-h] [-o] [-q] {TEMPLATE_ARG} {JSON_ARG} {OUTPUT_ARG}', description='Make docx file from existing template docx and json data.') parser.add_argument(TEMPLATE_ARG, type=str, @@ -25,6 +26,9 @@ def make_arg_parser() -> argparse.ArgumentParser: parser.add_argument('-' + OVERWRITE_ARG[0], '--' + OVERWRITE_ARG, action='store_true', help='If output file already exists, overwrites without asking for confirmation') + parser.add_argument('-' + QUIET_ARG[0], '--' + QUIET_ARG, + action='store_true', + help='Do not display unnecessary messages') return parser @@ -50,7 +54,7 @@ def is_argument_valid(arg_name: str, arg_value: str,overwrite: bool) -> bool: elif arg_name == OUTPUT_ARG: return arg_value.endswith('.docx') and check_exists_ask_overwrite( arg_value, overwrite) - elif arg_name == OVERWRITE_ARG: + elif arg_name in [OVERWRITE_ARG, QUIET_ARG]: return arg_value in [True, False] @@ -108,10 +112,12 @@ def render_docx(doc:DocxTemplate, json_data: dict) -> DocxTemplate: raise RuntimeError(f'An error ocurred while trying to render the docx') from e -def save_file(doc: DocxTemplate, output_path: Path) -> None: +def save_file(doc: DocxTemplate, parsed_args: dict) -> None: try: + output_path = parsed_args[OUTPUT_ARG] doc.save(output_path) - print(f'Document successfully generated and saved at {output_path}') + if not parsed_args[QUIET_ARG]: + print(f'Document successfully generated and saved at {output_path}') except PermissionError as e: print(f'{e.strerror}. Could not save file {e.filename}.') raise RuntimeError('Failed to save file.') from e @@ -122,18 +128,19 @@ def main() -> None: # Everything is in a try-except block that cacthes a RuntimeError that is # raised if any of the individual functions called cause an error # themselves, terminating the main function. + parsed_args = get_args(parser) try: - parsed_args = get_args(parser) validate_all_args(parsed_args) json_data = get_json_data(Path(parsed_args[JSON_ARG]).resolve()) doc = make_docxtemplate(Path(parsed_args[TEMPLATE_ARG]).resolve()) doc = render_docx(doc,json_data) - save_file(doc, Path(parsed_args[OUTPUT_ARG]).resolve()) + save_file(doc, parsed_args) except RuntimeError as e: print('Error: '+e.__str__()) return finally: - print('Exiting program!') + if not parsed_args[QUIET_ARG]: + print('Exiting program!') if __name__ == '__main__': diff --git a/tests/main.py b/tests/main.py deleted file mode 100644 index adae5ee..0000000 --- a/tests/main.py +++ /dev/null @@ -1,21 +0,0 @@ -from docxtpl.__main__ import main -import sys -from pathlib import Path - -TEMPLATE_PATH = 'templates/template_for_main_test.docx' -JSON_PATH = 'templates/json_for_main_test.json' -OUTPUT_FILENAME = 'output/output_for_main_test.docx' -OVERWRITE = '-o' - - -# Simulate command line arguments, running with overwrite flag so test can be -# run repeatedly without need for confirmation: -sys.argv[1:] = [TEMPLATE_PATH, JSON_PATH, OUTPUT_FILENAME, OVERWRITE] - -main() - -output_path = Path(OUTPUT_FILENAME) - -if output_path.exists(): - print(f'File {output_path.resolve()} exists.') - diff --git a/tests/module_execute.py b/tests/module_execute.py new file mode 100644 index 0000000..f33f611 --- /dev/null +++ b/tests/module_execute.py @@ -0,0 +1,22 @@ +import sys, os +from pathlib import Path + +TEMPLATE_PATH = 'templates/module_execute_tpl.docx' +JSON_PATH = 'templates/module_execute.json' +OUTPUT_FILENAME = 'output/module_execute.docx' +OVERWRITE = '-o' +QUIET = '-q' + + +output_path = Path(OUTPUT_FILENAME) +if output_path.exists(): + output_path.unlink() + +os.chdir(Path(__file__).parent) +cmd = f'python -m docxtpl {TEMPLATE_PATH} {JSON_PATH} {OUTPUT_FILENAME} {OVERWRITE} {QUIET}' +print(f'Executing "{cmd}" ...') +os.system(cmd) + +if output_path.exists(): + print(f' --> File {output_path.resolve()} has been generated.') + diff --git a/tests/templates/json_for_main_test.json b/tests/templates/module_execute.json similarity index 100% rename from tests/templates/json_for_main_test.json rename to tests/templates/module_execute.json diff --git a/tests/templates/template_for_main_test.docx b/tests/templates/module_execute_tpl.docx similarity index 100% rename from tests/templates/template_for_main_test.docx rename to tests/templates/module_execute_tpl.docx