Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions .github/workflows/codestyle.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,12 @@ jobs:
matrix:
python-version: ['3.9', '3.10', '3.11', '3.12', '3.13']
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v5
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v1
uses: actions/setup-python@v6
with:
python-version: ${{ matrix.python-version }}
allow-prereleases: true
- name: Install dependencies
run: |
python -m pip install --upgrade pip
Expand All @@ -23,3 +24,11 @@ jobs:
pip install flake8
# stop the build if there are code styling problems. The GitHub editor is 127 chars wide.
flake8 . --count --max-line-length=127 --show-source --statistics
- name: Check type hints
run: |
pip install mypy lxml-stubs
mypy .
- name: Ensure library work without docxcompose
run: |
pip uninstall docxcompose
python -c "from docxtpl import *"
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -61,4 +61,7 @@ target/
.project

#Pycharm
.idea
.idea

# In Project Virtual Environment
.venv/
23 changes: 13 additions & 10 deletions docxtpl/__main__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from __future__ import annotations

import argparse
import json
import os
Expand All @@ -11,7 +13,7 @@
QUIET_ARG = "quiet"


def make_arg_parser():
def make_arg_parser() -> argparse.ArgumentParser:
parser = argparse.ArgumentParser(
usage="python -m docxtpl [-h] [-o] [-q] {} {} {}".format(
TEMPLATE_ARG, JSON_ARG, OUTPUT_ARG
Expand Down Expand Up @@ -42,7 +44,7 @@ def make_arg_parser():
return parser


def get_args(parser):
def get_args(parser) -> dict:
try:
parsed_args = vars(parser.parse_args())
return parsed_args
Expand All @@ -57,7 +59,7 @@ def get_args(parser):
)


def is_argument_valid(arg_name, arg_value, overwrite):
def is_argument_valid(arg_name: str, arg_value: str, overwrite: bool) -> bool | None:
# Basic checks for the arguments
if arg_name == TEMPLATE_ARG:
return os.path.isfile(arg_value) and arg_value.endswith(".docx")
Expand All @@ -69,9 +71,10 @@ def is_argument_valid(arg_name, arg_value, overwrite):
)
elif arg_name in [OVERWRITE_ARG, QUIET_ARG]:
return arg_value in [True, False]
return None


def check_exists_ask_overwrite(arg_value, overwrite):
def check_exists_ask_overwrite(arg_value: str, overwrite: bool) -> bool:
# 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.
Expand All @@ -93,7 +96,7 @@ def check_exists_ask_overwrite(arg_value, overwrite):
return True


def validate_all_args(parsed_args):
def validate_all_args(parsed_args: dict) -> None:
overwrite = parsed_args[OVERWRITE_ARG]
# Raises AssertionError if any of the arguments is not validated
try:
Expand All @@ -108,7 +111,7 @@ def validate_all_args(parsed_args):
)


def get_json_data(json_path):
def get_json_data(json_path) -> dict:
with open(json_path) as file:
try:
json_data = json.load(file)
Expand All @@ -121,22 +124,22 @@ def get_json_data(json_path):
raise RuntimeError("Failed to get json data.")


def make_docxtemplate(template_path):
def make_docxtemplate(template_path: str) -> DocxTemplate:
try:
return DocxTemplate(template_path)
except TemplateError:
raise RuntimeError("Could not create docx template.")


def render_docx(doc, json_data):
def render_docx(doc: DocxTemplate, json_data: dict) -> DocxTemplate:
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):
def save_file(doc: DocxTemplate, parsed_args: dict) -> None:
try:
output_path = parsed_args[OUTPUT_ARG]
doc.save(output_path)
Expand All @@ -151,7 +154,7 @@ def save_file(doc, parsed_args):
raise RuntimeError("Failed to save file.")


def main():
def main() -> None:
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
Expand Down
9 changes: 9 additions & 0 deletions docxtpl/_compat.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# -*- coding: utf-8 -*-
try:
from html import escape
except ImportError:
# cgi.escape is deprecated in python 3.7
from cgi import escape # type:ignore[attr-defined,no-redef]


__all__ = ("escape",)
28 changes: 22 additions & 6 deletions docxtpl/inline_image.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,39 @@

@author: Eric Lapouyade
"""

from __future__ import annotations

from typing import IO, TYPE_CHECKING

from docx.oxml import OxmlElement, parse_xml
from docx.oxml.ns import qn

if TYPE_CHECKING:
from docx.shared import Length
from .template import DocxTemplate


class InlineImage(object):
"""Class to generate an inline image

This is much faster than using Subdoc class.
"""

tpl = None
image_descriptor = None
width = None
height = None
tpl: DocxTemplate = None # type:ignore[assignment]
image_descriptor: str | IO[bytes] = None # type:ignore[assignment]
width: int | Length | None = None
height: int | Length | None = None
anchor = None

def __init__(self, tpl, image_descriptor, width=None, height=None, anchor=None):
def __init__(
self,
tpl: DocxTemplate,
image_descriptor: str | IO[bytes],
width: int | Length | None = None,
height: int | Length | None = None,
anchor=None,
) -> None:
self.tpl, self.image_descriptor = tpl, image_descriptor
self.width, self.height = width, height
self.anchor = anchor
Expand Down Expand Up @@ -49,7 +65,7 @@ def _add_hyperlink(self, run, url, part):

return run

def _insert_image(self):
def _insert_image(self) -> str:
pic = self.tpl.current_rendering_part.new_pic_inline(
self.image_descriptor,
self.width,
Expand Down
7 changes: 2 additions & 5 deletions docxtpl/listing.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,8 @@

@author: Eric Lapouyade
"""
try:
from html import escape
except ImportError:
# cgi.escape is deprecated in python 3.7
from cgi import escape

from ._compat import escape


class Listing(object):
Expand Down
Empty file added docxtpl/py.typed
Empty file.
7 changes: 2 additions & 5 deletions docxtpl/richtext.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,8 @@

@author: Eric Lapouyade
"""
try:
from html import escape
except ImportError:
# cgi.escape is deprecated in python 3.7
from cgi import escape

from ._compat import escape


class RichText(object):
Expand Down
Loading
Loading