Added basic functionality to make the module executable
This commit is contained in:
parent
21a0a46a43
commit
a45cc806d8
116
docxtpl/__main__.py
Normal file
116
docxtpl/__main__.py
Normal file
@ -0,0 +1,116 @@
|
||||
from .template import DocxTemplate,TemplateError
|
||||
import argparse, json
|
||||
from pathlib import Path
|
||||
from argparse import ArgumentError
|
||||
|
||||
|
||||
def make_arg_parser() -> argparse.ArgumentParser:
|
||||
parser = argparse.ArgumentParser(
|
||||
usage='docxtpl template_path json_path output_filename',
|
||||
description='Make docx file from existing template docx and json data.',
|
||||
add_help=True)
|
||||
parser.add_argument('Template',
|
||||
metavar='template_path',
|
||||
type=str,
|
||||
help='The path to the template docx file.')
|
||||
parser.add_argument('Json',
|
||||
metavar='json_path',
|
||||
type=str,
|
||||
help='The path to the json file with the data.')
|
||||
parser.add_argument('Output',
|
||||
metavar='output_filename',
|
||||
type=str,
|
||||
help='The filename to save the generated docx.')
|
||||
return parser
|
||||
|
||||
|
||||
def get_args(parser: argparse.ArgumentParser) -> dict:
|
||||
try:
|
||||
parsed_args = vars(parser.parse_args())
|
||||
return parsed_args
|
||||
# There is a bug that prevents argparser from catching ArgumentError
|
||||
# manually. For more info: https://bugs.python.org/issue41255
|
||||
# I know bare exceptions are wrong, could not find another way to catch
|
||||
# wrong arguments.
|
||||
except:
|
||||
raise RuntimeError(f'Correct usage is:\n{parser.usage}')
|
||||
|
||||
|
||||
def is_argument_valid(arg_name: str, arg_value: str) -> bool:
|
||||
if arg_name == 'Template':
|
||||
return Path(arg_value).is_file() and arg_value.endswith('.docx')
|
||||
elif arg_name == 'Json':
|
||||
return Path(arg_value).is_file() and arg_value.endswith('.json')
|
||||
elif arg_name == 'Output':
|
||||
return arg_value.endswith('.docx') and check_exists_ask_overwrite(
|
||||
arg_value)
|
||||
|
||||
|
||||
def check_exists_ask_overwrite(arg_value) -> bool:
|
||||
if Path(arg_value).exists():
|
||||
try:
|
||||
if input(f'File {arg_value} already exists, would you like to overwrite the existing file? (y/n)').lower() == 'y':
|
||||
return True
|
||||
else:
|
||||
raise FileExistsError
|
||||
except FileExistsError as e:
|
||||
raise RuntimeError(f'File {arg_value} already exists, please choose a different name.') from e
|
||||
else:
|
||||
return True
|
||||
|
||||
|
||||
def validate_all_args(parsed_args) -> None:
|
||||
try:
|
||||
for arg_name, arg_value in parsed_args.items():
|
||||
if not is_argument_valid(arg_name, arg_value):
|
||||
raise AttributeError
|
||||
except ArgumentError as e:
|
||||
raise RuntimeError(
|
||||
f'The specified {arg_name} "{arg_value}" is not valid.')
|
||||
|
||||
|
||||
def get_json_data(json_path: Path) -> dict:
|
||||
with open(json_path) as file:
|
||||
try:
|
||||
json_data = json.load(file)
|
||||
return json_data
|
||||
except json.JSONDecodeError as e:
|
||||
print(
|
||||
f'There was an error on line {e.lineno}, column {e.colno} while trying to parse file {json_path}')
|
||||
raise RuntimeError('Failed to get json data.')
|
||||
|
||||
|
||||
def make_docxtemplate(template_path: Path) -> DocxTemplate:
|
||||
try:
|
||||
return DocxTemplate(template_path)
|
||||
except TemplateError as e:
|
||||
raise RuntimeError('Could not create docx template.') from e
|
||||
|
||||
|
||||
def save_file(doc: DocxTemplate, output_path: Path) -> None:
|
||||
try:
|
||||
doc.save(output_path)
|
||||
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
|
||||
|
||||
|
||||
def main() -> None:
|
||||
parser = make_arg_parser()
|
||||
try:
|
||||
parsed_args = get_args(parser)
|
||||
validate_all_args(parsed_args)
|
||||
json_data = get_json_data(Path(parsed_args['Json']).resolve())
|
||||
doc = make_docxtemplate(Path(parsed_args['Template']).resolve())
|
||||
doc.render(json_data)
|
||||
save_file(doc, Path(parsed_args['Output']).resolve())
|
||||
except RuntimeError as e:
|
||||
print(e)
|
||||
return
|
||||
finally:
|
||||
print('Exiting program!')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
Loading…
x
Reference in New Issue
Block a user