Tim Gates 2fd2140caf
docs: Fix a few typos
There are small typos in:
- docs/index.rst
- docxtpl/__main__.py
- docxtpl/template.py
- tests/embedded.py

Fixes:
- Should read `surrounding` rather than `surronding`.
- Should read `rendering` rather than `rendring`.
- Should read `providing` rather than `provinding`.
- Should read `optionally` rather than `optionnally`.
- Should read `optional` rather than `optionnal`.
- Should read `necessary` rather than `neccessary`.
- Should read `existing` rather than `exsting`.
- Should read `embedded` rather than `embdded`.
- Should read `dictionaries` rather than `dictionnaries`.
- Should read `cleaning` rather than `cleanning`.
- Should read `catches` rather than `cacthes`.

Signed-off-by: Tim Gates <tim.gates@iress.com>
2022-07-21 08:16:56 +10:00

154 lines
5.4 KiB
Python

import argparse
import json
import os
from .template import DocxTemplate, TemplateError
TEMPLATE_ARG = 'template_path'
JSON_ARG = 'json_path'
OUTPUT_ARG = 'output_filename'
OVERWRITE_ARG = 'overwrite'
QUIET_ARG = 'quiet'
def make_arg_parser():
parser = argparse.ArgumentParser(
usage='python -m docxtpl [-h] [-o] [-q] {} {} {}'.format(TEMPLATE_ARG, JSON_ARG, OUTPUT_ARG),
description='Make docx file from existing template docx and json data.')
parser.add_argument(TEMPLATE_ARG,
type=str,
help='The path to the template docx file.')
parser.add_argument(JSON_ARG,
type=str,
help='The path to the json file with the data.')
parser.add_argument(OUTPUT_ARG,
type=str,
help='The filename to save the generated docx.')
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
def get_args(parser):
try:
parsed_args = vars(parser.parse_args())
return parsed_args
# Argument errors raise a SystemExit with code 2. Normal usage of the
# --help or -h flag raises a SystemExit with code 0.
except SystemExit as e:
if e.code == 0:
raise SystemExit
else:
raise RuntimeError('Correct usage is:\n{parser.usage}'.format(parser=parser))
def is_argument_valid(arg_name, arg_value, overwrite):
# Basic checks for the arguments
if arg_name == TEMPLATE_ARG:
return os.path.isfile(arg_value) and arg_value.endswith('.docx')
elif arg_name == JSON_ARG:
return os.path.isfile(arg_value) and arg_value.endswith('.json')
elif arg_name == OUTPUT_ARG:
return arg_value.endswith('.docx') and check_exists_ask_overwrite(
arg_value, overwrite)
elif arg_name in [OVERWRITE_ARG, QUIET_ARG]:
return arg_value in [True, False]
def check_exists_ask_overwrite(arg_value, overwrite):
# If output file does not exist or command was run with overwrite option,
# returns True, else asks for overwrite confirmation. If overwrite is
# confirmed returns True, else raises OSError.
if os.path.exists(arg_value) and not overwrite:
try:
msg = 'File %s already exists, would you like to overwrite the existing file? (y/n)' % arg_value
if input(msg).lower() == 'y':
return True
else:
raise OSError
except OSError:
raise RuntimeError('File %s already exists, please choose a different name.' % arg_value)
else:
return True
def validate_all_args(parsed_args):
overwrite = parsed_args[OVERWRITE_ARG]
# Raises AssertionError if any of the arguments is not validated
try:
for arg_name, arg_value in parsed_args.items():
if not is_argument_valid(arg_name, arg_value, overwrite):
raise AssertionError
except AssertionError:
raise RuntimeError(
'The specified {arg_name} "{arg_value}" is not valid.'.format(
arg_name=arg_name, arg_value=arg_value
))
def get_json_data(json_path):
with open(json_path) as file:
try:
json_data = json.load(file)
return json_data
except json.JSONDecodeError as e:
print(
'There was an error on line {e.lineno}, column {e.colno} while trying to parse file {json_path}'.format(
e=e, json_path=json_path
))
raise RuntimeError('Failed to get json data.')
def make_docxtemplate(template_path):
try:
return DocxTemplate(template_path)
except TemplateError:
raise RuntimeError('Could not create docx template.')
def render_docx(doc, json_data):
try:
doc.render(json_data)
return doc
except TemplateError:
raise RuntimeError('An error ocurred while trying to render the docx')
def save_file(doc, parsed_args):
try:
output_path = parsed_args[OUTPUT_ARG]
doc.save(output_path)
if not parsed_args[QUIET_ARG]:
print('Document successfully generated and saved at {output_path}'.format(output_path=output_path))
except OSError as e:
print('{e.strerror}. Could not save file {e.filename}.'.format(e=e))
raise RuntimeError('Failed to save file.')
def main():
parser = make_arg_parser()
# Everything is in a try-except block that catches 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:
validate_all_args(parsed_args)
json_data = get_json_data(os.path.abspath(parsed_args[JSON_ARG]))
doc = make_docxtemplate(os.path.abspath(parsed_args[TEMPLATE_ARG]))
doc = render_docx(doc, json_data)
save_file(doc, parsed_args)
except RuntimeError as e:
print('Error: '+e.__str__())
return
finally:
if not parsed_args[QUIET_ARG]:
print('Exiting program!')
if __name__ == '__main__':
main()