Skip to content

Commit 93242da

Browse files
committed
Merge branch 'feat-uv-pdm' of github.com:waketzheng/python-docx-template into feat-uv-pdm
2 parents 2782c47 + 9305bca commit 93242da

28 files changed

Lines changed: 442 additions & 1848 deletions

.github/workflows/codestyle.yml

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,20 @@ jobs:
1515
with:
1616
python-version: ${{ matrix.python-version }}
1717
allow-prereleases: true
18-
- uses: astral-sh/setup-uv@v6
1918
- name: Install dependencies
20-
run: uv sync --all-extras --all-groups
19+
run: |
20+
python -m pip install --upgrade pip
21+
pip install -r requirements.txt
2122
- name: Lint with flake8
2223
run: |
24+
pip install flake8
2325
# stop the build if there are code styling problems. The GitHub editor is 127 chars wide.
24-
uv run --no-sync flake8 . --count --max-line-length=127 --show-source --statistics --exclude .venv,__pycache__
26+
flake8 . --count --max-line-length=127 --show-source --statistics
2527
- name: Check type hints
26-
run: uv run --no-sync mypy .
28+
run: |
29+
pip install mypy lxml-stubs
30+
mypy .
31+
- name: Ensure library work without docxcompose
32+
run: |
33+
pip uninstall -y docxcompose
34+
python -c "from docxtpl import *"

.github/workflows/test.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ jobs:
2727
allow-prereleases: true
2828
- uses: astral-sh/setup-uv@v6
2929
- name: Install dependencies
30-
run: uv sync --all-extras
30+
run: uv sync --all-extras --all-groups
3131
- name: Test
3232
run: uv run python tests/runtests.py
3333
- name: Build
@@ -37,11 +37,11 @@ jobs:
3737
runs-on: ubuntu-latest
3838
container: python:3.7-slim
3939
steps:
40-
- uses: actions/checkout@v4
41-
- uses: actions/setup-python@v5
40+
- uses: actions/checkout@v5
41+
- uses: actions/setup-python@v6
4242
- uses: astral-sh/setup-uv@v6
4343
- name: Install dependencies
44-
run: uv sync --all-extras --python=python3.7
44+
run: uv sync --all-extras --all-groups --python=python3.7
4545
- name: Test
4646
run: |
4747
uv run python tests/runtests.py

.gitignore

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,4 +63,10 @@ target/
6363

6464
#Pycharm
6565
.idea
66+
67+
# Uv/Pdm
6668
.pdm-python
69+
.python-version
70+
71+
# In Project Virtual Environment
72+
.venv/

CHANGES.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
0.20.2 *(Unreleased)*
2+
-------------------
3+
- Move docxcompose to optional dependency (Thanks to Waket Zheng)
4+
15
0.20.1 (2025-07-15)
26
-------------------
37
- Fix and improve get_undeclared_template_variables() method (Thanks to Pablo Esteban)

Pipfile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ name = "pypi"
88
[dev-packages]
99
docxtpl = {editable = true, path = "."}
1010
flake8 = "*"
11+
mypy = "*"
12+
lxml-stubs = "*"
1113

1214
[requires]
1315
python_version = "3"

Pipfile.lock

Lines changed: 303 additions & 330 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docxtpl/__main__.py

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
from __future__ import annotations
2+
13
import argparse
24
import json
35
import os
@@ -11,7 +13,7 @@
1113
QUIET_ARG = "quiet"
1214

1315

14-
def make_arg_parser():
16+
def make_arg_parser() -> argparse.ArgumentParser:
1517
parser = argparse.ArgumentParser(
1618
usage="python -m docxtpl [-h] [-o] [-q] {} {} {}".format(
1719
TEMPLATE_ARG, JSON_ARG, OUTPUT_ARG
@@ -42,7 +44,7 @@ def make_arg_parser():
4244
return parser
4345

4446

45-
def get_args(parser):
47+
def get_args(parser) -> dict:
4648
try:
4749
parsed_args = vars(parser.parse_args())
4850
return parsed_args
@@ -57,7 +59,7 @@ def get_args(parser):
5759
)
5860

5961

60-
def is_argument_valid(arg_name, arg_value, overwrite):
62+
def is_argument_valid(arg_name: str, arg_value: str, overwrite: bool) -> bool | None:
6163
# Basic checks for the arguments
6264
if arg_name == TEMPLATE_ARG:
6365
return os.path.isfile(arg_value) and arg_value.endswith(".docx")
@@ -69,9 +71,10 @@ def is_argument_valid(arg_name, arg_value, overwrite):
6971
)
7072
elif arg_name in [OVERWRITE_ARG, QUIET_ARG]:
7173
return arg_value in [True, False]
74+
return None
7275

7376

74-
def check_exists_ask_overwrite(arg_value, overwrite):
77+
def check_exists_ask_overwrite(arg_value: str, overwrite: bool) -> bool:
7578
# If output file does not exist or command was run with overwrite option,
7679
# returns True, else asks for overwrite confirmation. If overwrite is
7780
# confirmed returns True, else raises OSError.
@@ -93,7 +96,7 @@ def check_exists_ask_overwrite(arg_value, overwrite):
9396
return True
9497

9598

96-
def validate_all_args(parsed_args):
99+
def validate_all_args(parsed_args: dict) -> None:
97100
overwrite = parsed_args[OVERWRITE_ARG]
98101
# Raises AssertionError if any of the arguments is not validated
99102
try:
@@ -108,7 +111,7 @@ def validate_all_args(parsed_args):
108111
)
109112

110113

111-
def get_json_data(json_path):
114+
def get_json_data(json_path) -> dict:
112115
with open(json_path) as file:
113116
try:
114117
json_data = json.load(file)
@@ -121,22 +124,22 @@ def get_json_data(json_path):
121124
raise RuntimeError("Failed to get json data.")
122125

123126

124-
def make_docxtemplate(template_path):
127+
def make_docxtemplate(template_path: str) -> DocxTemplate:
125128
try:
126129
return DocxTemplate(template_path)
127130
except TemplateError:
128131
raise RuntimeError("Could not create docx template.")
129132

130133

131-
def render_docx(doc, json_data):
134+
def render_docx(doc: DocxTemplate, json_data: dict) -> DocxTemplate:
132135
try:
133136
doc.render(json_data)
134137
return doc
135138
except TemplateError:
136139
raise RuntimeError("An error ocurred while trying to render the docx")
137140

138141

139-
def save_file(doc, parsed_args):
142+
def save_file(doc: DocxTemplate, parsed_args: dict) -> None:
140143
try:
141144
output_path = parsed_args[OUTPUT_ARG]
142145
doc.save(output_path)
@@ -151,7 +154,7 @@ def save_file(doc, parsed_args):
151154
raise RuntimeError("Failed to save file.")
152155

153156

154-
def main():
157+
def main() -> None:
155158
parser = make_arg_parser()
156159
# Everything is in a try-except block that catches a RuntimeError that is
157160
# raised if any of the individual functions called cause an error

docxtpl/_compat.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# -*- coding: utf-8 -*-
2+
try:
3+
from html import escape
4+
except ImportError:
5+
# cgi.escape is deprecated in python 3.7
6+
from cgi import escape # type:ignore[attr-defined,no-redef]
7+
8+
9+
__all__ = ("escape",)

docxtpl/inline_image.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,14 @@
77

88
from __future__ import annotations
99

10-
from typing import IO
10+
from typing import IO, TYPE_CHECKING
1111

1212
from docx.oxml import OxmlElement, parse_xml
1313
from docx.oxml.ns import qn
14-
from docx.shared import Length
1514

16-
from .template import DocxTemplate
15+
if TYPE_CHECKING:
16+
from docx.shared import Length
17+
from .template import DocxTemplate
1718

1819

1920
class InlineImage(object):

docxtpl/listing.py

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,7 @@
55
@author: Eric Lapouyade
66
"""
77

8-
try:
9-
from html import escape
10-
except ImportError:
11-
# cgi.escape is deprecated in python 3.7
12-
from cgi import escape # type:ignore[attr-defined,no-redef]
8+
from ._compat import escape
139

1410

1511
class Listing(object):

0 commit comments

Comments
 (0)