Skip to content

Commit

Permalink
Add link checker. Update quality tools.
Browse files Browse the repository at this point in the history
  • Loading branch information
fniessink committed Nov 8, 2024
1 parent ecf99d1 commit 2ad8071
Show file tree
Hide file tree
Showing 21 changed files with 344 additions and 111 deletions.
21 changes: 21 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
---
name: Test and quality

on: [push]

jobs:
build:
runs-on: ubuntu-latest

steps:
- uses: actions/[email protected]
- name: Install uv
uses: astral-sh/setup-uv@v3
with:
version: "0.4.22"
- name: Install dependencies, run unit tests and check quality
run: |
uv venv
uv pip install -r requirements.txt
ci/unittest.sh
ci/quality.sh
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ The Kwaliteitsaanpak consists of a main document containing the Kwaliteitsaanpak
- Clone this repository
- Run `docker compose up`
- Run `open html/index.html` to view the latest release and the work in progress (wip)
- Run `uvx md-dead-link-check Content` to check for dead links

## Releasing a new version of the documentation

Expand Down
9 changes: 5 additions & 4 deletions ci/quality.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@

set -e

black --quiet --line-length 118 src tests
mypy --no-error-summary src tests
pylint src tests
uvx ruff check
uvx ruff format --check
uvx mypy --python-executable=.venv/bin/python src tests
NAMES_TO_IGNORE=''
vulture --min-confidence 0 --ignore-names $NAMES_TO_IGNORE src tests .vulture_white_list.py
uvx vulture --min-confidence 0 --ignore-names $NAMES_TO_IGNORE src tests .vulture_white_list.py
uvx md-dead-link-check .
8 changes: 4 additions & 4 deletions ci/unittest.sh
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/bin/sh

export PYTHONPATH=src:$PYTHONPATH
coverage run --omit=*venv/* --branch -m unittest --quiet
coverage xml -o build/unittest-coverage.xml
coverage html --directory build/unittest-coverage
coverage report --fail-under=100 --skip-covered
.venv/bin/coverage run --omit=*venv/* --branch -m unittest --quiet
.venv/bin/coverage xml -o build/unittest-coverage.xml
.venv/bin/coverage html --directory build/unittest-coverage
.venv/bin/coverage report --fail-under=100 --skip-covered
70 changes: 47 additions & 23 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,29 +3,18 @@ name = "ictu-kwaliteitsaanpak"
version = "4.0.0"
requires-python = ">=3.12"
classifiers = [
"Programming Language :: Python :: 3 :: Only",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3 :: Only",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
]
dependencies = [
"python-docx==1.1.2",
"python-pptx==1.0.2",
"xlsxwriter==3.2.0",
"coverage==7.6.4",
"lxml-stubs==0.5.1",
"python-docx==1.1.2",
"python-pptx==1.0.2",
"vulture==2.13",
"xlsxwriter==3.2",
]
optional-dependencies.dev = [
"black==24.10.0",
"coverage==7.6.4",
"lxml-stubs==0.5.1",
"mypy==1.13.0",
"pip-tools==7.4.1",
"pylint==3.3.1",
"vulture==2.13",
]

[tool.black]
line-length = 120

[tool.pylint]
max-line-length=120

[tool.mypy]
ignore_missing_imports = false
Expand All @@ -37,8 +26,43 @@ warn_unused_ignores = true

[[tool.mypy.overrides]]
module = [
"pptx",
"pptx.util",
"xlsxwriter",
"pptx",
"pptx.util",
"xlsxwriter",
]
ignore_missing_imports = true

[tool.md_dead_link_check]
exclude_links = [
"#m01",
"#m02",
"#m04",
"#m05",
"#m07",
"#m08",
"#m10",
"#m14",
"#m16",
"#m18",
"#m19",
"#m26",
"#m27",
"#m28",
"#m29",
"#m30",
"#m31",
"#m32",
"#m33",
"#m34",
"#relatie-met-nen-npr-5326",
"#terminologie-en-afkortingen",
"relaties-tussen-producten.png",
"relaties-testproducten-agile.png",
]

[tool.ruff]
target-version = "py312"
line-length = 120
src = [
"src",
]
72 changes: 72 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,69 @@
# This file was autogenerated by uv via the following command:
# uv pip compile pyproject.toml --generate-hashes
coverage==7.6.4 \
--hash=sha256:00a1d69c112ff5149cabe60d2e2ee948752c975d95f1e1096742e6077affd376 \
--hash=sha256:023bf8ee3ec6d35af9c1c6ccc1d18fa69afa1cb29eaac57cb064dbb262a517f9 \
--hash=sha256:0294ca37f1ba500667b1aef631e48d875ced93ad5e06fa665a3295bdd1d95111 \
--hash=sha256:06babbb8f4e74b063dbaeb74ad68dfce9186c595a15f11f5d5683f748fa1d172 \
--hash=sha256:0809082ee480bb8f7416507538243c8863ac74fd8a5d2485c46f0f7499f2b491 \
--hash=sha256:0b3fb02fe73bed561fa12d279a417b432e5b50fe03e8d663d61b3d5990f29546 \
--hash=sha256:0b58c672d14f16ed92a48db984612f5ce3836ae7d72cdd161001cc54512571f2 \
--hash=sha256:0bcd1069e710600e8e4cf27f65c90c7843fa8edfb4520fb0ccb88894cad08b11 \
--hash=sha256:1032e178b76a4e2b5b32e19d0fd0abbce4b58e77a1ca695820d10e491fa32b08 \
--hash=sha256:11a223a14e91a4693d2d0755c7a043db43d96a7450b4f356d506c2562c48642c \
--hash=sha256:12394842a3a8affa3ba62b0d4ab7e9e210c5e366fbac3e8b2a68636fb19892c2 \
--hash=sha256:182e6cd5c040cec0a1c8d415a87b67ed01193ed9ad458ee427741c7d8513d963 \
--hash=sha256:1d5b8007f81b88696d06f7df0cb9af0d3b835fe0c8dbf489bad70b45f0e45613 \
--hash=sha256:1f76846299ba5c54d12c91d776d9605ae33f8ae2b9d1d3c3703cf2db1a67f2c0 \
--hash=sha256:27fb4a050aaf18772db513091c9c13f6cb94ed40eacdef8dad8411d92d9992db \
--hash=sha256:29155cd511ee058e260db648b6182c419422a0d2e9a4fa44501898cf918866cf \
--hash=sha256:29fc0f17b1d3fea332f8001d4558f8214af7f1d87a345f3a133c901d60347c73 \
--hash=sha256:2b6b4c83d8e8ea79f27ab80778c19bc037759aea298da4b56621f4474ffeb117 \
--hash=sha256:2fdef0d83a2d08d69b1f2210a93c416d54e14d9eb398f6ab2f0a209433db19e1 \
--hash=sha256:3c65d37f3a9ebb703e710befdc489a38683a5b152242664b973a7b7b22348a4e \
--hash=sha256:4f704f0998911abf728a7783799444fcbbe8261c4a6c166f667937ae6a8aa522 \
--hash=sha256:51b44306032045b383a7a8a2c13878de375117946d68dcb54308111f39775a25 \
--hash=sha256:53d202fd109416ce011578f321460795abfe10bb901b883cafd9b3ef851bacfc \
--hash=sha256:58809e238a8a12a625c70450b48e8767cff9eb67c62e6154a642b21ddf79baea \
--hash=sha256:5915fcdec0e54ee229926868e9b08586376cae1f5faa9bbaf8faf3561b393d52 \
--hash=sha256:5beb1ee382ad32afe424097de57134175fea3faf847b9af002cc7895be4e2a5a \
--hash=sha256:5f8ae553cba74085db385d489c7a792ad66f7f9ba2ee85bfa508aeb84cf0ba07 \
--hash=sha256:5fbd612f8a091954a0c8dd4c0b571b973487277d26476f8480bfa4b2a65b5d06 \
--hash=sha256:6bd818b7ea14bc6e1f06e241e8234508b21edf1b242d49831831a9450e2f35fa \
--hash=sha256:6f01ba56b1c0e9d149f9ac85a2f999724895229eb36bd997b61e62999e9b0901 \
--hash=sha256:73d2b73584446e66ee633eaad1a56aad577c077f46c35ca3283cd687b7715b0b \
--hash=sha256:7bb92c539a624cf86296dd0c68cd5cc286c9eef2d0c3b8b192b604ce9de20a17 \
--hash=sha256:8165b796df0bd42e10527a3f493c592ba494f16ef3c8b531288e3d0d72c1f6f0 \
--hash=sha256:862264b12ebb65ad8d863d51f17758b1684560b66ab02770d4f0baf2ff75da21 \
--hash=sha256:8902dd6a30173d4ef09954bfcb24b5d7b5190cf14a43170e386979651e09ba19 \
--hash=sha256:8cf717ee42012be8c0cb205dbbf18ffa9003c4cbf4ad078db47b95e10748eec5 \
--hash=sha256:8ed9281d1b52628e81393f5eaee24a45cbd64965f41857559c2b7ff19385df51 \
--hash=sha256:99b41d18e6b2a48ba949418db48159d7a2e81c5cc290fc934b7d2380515bd0e3 \
--hash=sha256:9cb7fa111d21a6b55cbf633039f7bc2749e74932e3aa7cb7333f675a58a58bf3 \
--hash=sha256:a181e99301a0ae128493a24cfe5cfb5b488c4e0bf2f8702091473d033494d04f \
--hash=sha256:a413a096c4cbac202433c850ee43fa326d2e871b24554da8327b01632673a076 \
--hash=sha256:a6b1e54712ba3474f34b7ef7a41e65bd9037ad47916ccb1cc78769bae324c01a \
--hash=sha256:ade3ca1e5f0ff46b678b66201f7ff477e8fa11fb537f3b55c3f0568fbfe6e718 \
--hash=sha256:b0ac3d42cb51c4b12df9c5f0dd2f13a4f24f01943627120ec4d293c9181219ba \
--hash=sha256:b369ead6527d025a0fe7bd3864e46dbee3aa8f652d48df6174f8d0bac9e26e0e \
--hash=sha256:b57b768feb866f44eeed9f46975f3d6406380275c5ddfe22f531a2bf187eda27 \
--hash=sha256:b8d3a03d9bfcaf5b0141d07a88456bb6a4c3ce55c080712fec8418ef3610230e \
--hash=sha256:bc66f0bf1d7730a17430a50163bb264ba9ded56739112368ba985ddaa9c3bd09 \
--hash=sha256:bf20494da9653f6410213424f5f8ad0ed885e01f7e8e59811f572bdb20b8972e \
--hash=sha256:c48167910a8f644671de9f2083a23630fbf7a1cb70ce939440cd3328e0919f70 \
--hash=sha256:c481b47f6b5845064c65a7bc78bc0860e635a9b055af0df46fdf1c58cebf8e8f \
--hash=sha256:c7c8b95bf47db6d19096a5e052ffca0a05f335bc63cef281a6e8fe864d450a72 \
--hash=sha256:c9b8e184898ed014884ca84c70562b4a82cbc63b044d366fedc68bc2b2f3394a \
--hash=sha256:cc8ff50b50ce532de2fa7a7daae9dd12f0a699bfcd47f20945364e5c31799fef \
--hash=sha256:d541423cdd416b78626b55f123412fcf979d22a2c39fce251b350de38c15c15b \
--hash=sha256:dab4d16dfef34b185032580e2f2f89253d302facba093d5fa9dbe04f569c4f4b \
--hash=sha256:dacbc52de979f2823a819571f2e3a350a7e36b8cb7484cdb1e289bceaf35305f \
--hash=sha256:df57bdbeffe694e7842092c5e2e0bc80fff7f43379d465f932ef36f027179806 \
--hash=sha256:ed8fe9189d2beb6edc14d3ad19800626e1d9f2d975e436f84e19efb7fa19469b \
--hash=sha256:f3ddf056d3ebcf6ce47bdaf56142af51bb7fad09e4af310241e9db7a3a8022e1 \
--hash=sha256:f8fe4984b431f8621ca53d9380901f62bfb54ff759a1348cd140490ada7b693c \
--hash=sha256:fe439416eb6380de434886b00c859304338f8b19f6f54811984f3420a2e03858
# via ictu-kwaliteitsaanpak (pyproject.toml)
lxml==5.3.0 \
--hash=sha256:01220dca0d066d1349bd6a1726856a78f7929f3878f7e2ee83c296c69495309e \
--hash=sha256:02ced472497b8362c8e902ade23e3300479f4f43e45f4105c85ef43b8db85229 \
Expand Down Expand Up @@ -142,6 +206,10 @@ lxml==5.3.0 \
# via
# python-docx
# python-pptx
lxml-stubs==0.5.1 \
--hash=sha256:1f689e5dbc4b9247cb09ae820c7d34daeb1fdbd1db06123814b856dae7787272 \
--hash=sha256:e0ec2aa1ce92d91278b719091ce4515c12adc1d564359dfaf81efa7d4feab79d
# via ictu-kwaliteitsaanpak (pyproject.toml)
pillow==11.0.0 \
--hash=sha256:00177a63030d612148e659b55ba99527803288cea7c75fb05766ab7981a8c1b7 \
--hash=sha256:006bcdd307cc47ba43e924099a038cbf9591062e6c50e570819743f5607404f5 \
Expand Down Expand Up @@ -233,6 +301,10 @@ typing-extensions==4.12.2 \
# via
# python-docx
# python-pptx
vulture==2.13 \
--hash=sha256:34793ba60488e7cccbecdef3a7fe151656372ef94fdac9fe004c52a4000a6d44 \
--hash=sha256:78248bf58f5eaffcc2ade306141ead73f437339950f80045dce7f8b078e5a1aa
# via ictu-kwaliteitsaanpak (pyproject.toml)
xlsxwriter==3.2.0 \
--hash=sha256:9977d0c661a72866a61f9f7a809e25ebbb0fb7036baa3b9fe74afcfca6b3cb8c \
--hash=sha256:ecfd5405b3e0e228219bcaf24c2ca0915e012ca9464a14048021d21a995d490e
Expand Down
6 changes: 0 additions & 6 deletions src/builder/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1 @@
"""Builder package."""

from .builder import Builder
from .docx_builder import DocxBuilder
from .html_builder import HTMLBuilder
from .pptx_builder import PptxBuilder
from .xlsx_builder import XlsxBuilder
2 changes: 0 additions & 2 deletions src/builder/builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@
class Builder:
"""Abstract builder."""

# pylint: disable=unused-argument

def __init__(self, filename: pathlib.Path) -> None:
self.filename = filename
self._stack: list[tuple[str, TreeBuilderAttributes]] = []
Expand Down
23 changes: 12 additions & 11 deletions src/builder/docx_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
from .table_of_contents import add_table_of_contents


class DocxBuilder(Builder): # pylint: disable=too-many-instance-attributes
class DocxBuilder(Builder):
"""Docx builder."""

SCHEMA = "{http://schemas.openxmlformats.org/wordprocessingml/2006/main}"
Expand All @@ -37,7 +37,10 @@ class DocxBuilder(Builder): # pylint: disable=too-many-instance-attributes
)

def __init__(
self, filename: pathlib.Path, docx_reference_filename: pathlib.Path, images_folder: pathlib.Path
self,
filename: pathlib.Path,
docx_reference_filename: pathlib.Path,
images_folder: pathlib.Path,
) -> None:
super().__init__(filename)
filename.unlink(missing_ok=True)
Expand All @@ -51,8 +54,7 @@ def __init__(
self.row: Row | None = None
self.column_index = 0

def start_element(self, tag: str, attributes: TreeBuilderAttributes) -> None: # pylint:disable=too-many-branches
# pylint: disable=protected-access
def start_element(self, tag: str, attributes: TreeBuilderAttributes) -> None:
super().start_element(tag, attributes)
if tag == xmltags.PARAGRAPH:
self.paragraph = self.doc.add_paragraph(style="Maatregel" if self.in_element(xmltags.MEASURE) else None)
Expand Down Expand Up @@ -87,18 +89,20 @@ def start_element(self, tag: str, attributes: TreeBuilderAttributes) -> None: #
self._add_table_cell(attributes)
elif tag == xmltags.HEADER:
self.paragraph = cast(Paragraph, self.doc.sections[0].header.paragraphs[0])
self.paragraph.paragraph_format.alignment = WD_PARAGRAPH_ALIGNMENT.RIGHT # pylint: disable=no-member
self.paragraph.paragraph_format.alignment = WD_PARAGRAPH_ALIGNMENT.RIGHT
elif tag == xmltags.TITLE:
self.paragraph = self.doc.add_paragraph(style="Title")
elif tag == xmltags.TABLE_OF_CONTENTS:
self.doc.add_paragraph(attributes[xmltags.TABLE_OF_CONTENTS_HEADING], style="TOC Heading")
add_table_of_contents(self.doc.add_paragraph())
elif tag == xmltags.IMAGE:
self.doc.add_picture(str(self.images_folder / str(attributes["src"])), width=Cm(int(attributes["width"])))
self.doc.add_picture(
str(self.images_folder / str(attributes["src"])),
width=Cm(int(attributes["width"])),
)

def _add_list_item(self) -> None:
"""Add a list item."""
# pylint: disable=protected-access
self.paragraph = self.doc.add_paragraph(style=self.current_list_style[-1])
level = len(self.current_list_style) - 1
self.paragraph_number(self.paragraph).get_or_add_ilvl().val = level
Expand All @@ -119,18 +123,15 @@ def _add_list_item(self) -> None:
@staticmethod
def paragraph_number(paragraph: Paragraph):
"""Return the current paragraph number ."""
# pylint: disable=protected-access
return paragraph._p.get_or_add_pPr().get_or_add_numPr() # type: ignore[attr-defined]

def _add_table_cell(self, attributes: TreeBuilderAttributes) -> None:
"""Add a table cell."""
# pylint: disable=protected-access
assert self.row
cell = self.row.cells[self.column_index]
cell._tc.tcPr.tcW.type = "auto" # type: ignore[union-attr]
self.paragraph = cast(Paragraph, cell.paragraphs[0])
if alignment_attr := attributes.get(xmltags.TABLE_CELL_ALIGNMENT):
# pylint: disable=no-member
alignment = {
"left": WD_PARAGRAPH_ALIGNMENT.LEFT,
"right": WD_PARAGRAPH_ALIGNMENT.RIGHT,
Expand All @@ -146,7 +147,7 @@ def text(self, tag: str, text: str, attributes: TreeBuilderAttributes) -> None:
if self.in_element(xmltags.BOLD):
run.font.bold = True
if self.in_element(xmltags.INSTRUCTION):
run.font.highlight_color = WD_COLOR_INDEX.YELLOW # pylint: disable=no-member
run.font.highlight_color = WD_COLOR_INDEX.YELLOW
if self.in_element(xmltags.ITALIC):
run.font.italic = True
if self.in_element(xmltags.STRIKETHROUGH):
Expand Down
12 changes: 9 additions & 3 deletions src/builder/html_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ def __init__(self, filename: pathlib.Path, stylesheet_path: pathlib.Path) -> Non
self.in_keep_together_div = False
self.in_measure = False

def start_element(self, tag: str, attributes: TreeBuilderAttributes) -> None: # pylint:disable=too-many-branches
def start_element(self, tag: str, attributes: TreeBuilderAttributes) -> None:
match tag:
case xmltags.DOCUMENT:
self.builder.start(html_tags.HTML, {html_tags.LANGUAGE: "nl"})
Expand All @@ -48,7 +48,10 @@ def start_element(self, tag: str, attributes: TreeBuilderAttributes) -> None: #
self.builder.end(html_tags.TITLE)
self.builder.start(
html_tags.LINK,
{html_tags.LINK_REL: "stylesheet", html_tags.LINK_HREF: self.STYLESHEET},
{
html_tags.LINK_REL: "stylesheet",
html_tags.LINK_HREF: self.STYLESHEET,
},
)
self.builder.end(html_tags.LINK)
self.builder.end(html_tags.HEAD)
Expand All @@ -74,7 +77,10 @@ def start_element(self, tag: str, attributes: TreeBuilderAttributes) -> None: #
self.builder.start(html_tags.TABLE_ROW, {})
case xmltags.TABLE_CELL:
alignment = str(attributes[xmltags.TABLE_CELL_ALIGNMENT])
self.builder.start(self.table_cell_html_tag, {html_tags.STYLE: f"text-align:{alignment}"})
self.builder.start(
self.table_cell_html_tag,
{html_tags.STYLE: f"text-align:{alignment}"},
)
case xmltags.ANCHOR:
self.builder.start(
html_tags.ANCHOR,
Expand Down
2 changes: 1 addition & 1 deletion src/builder/hyperlink.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,6 @@ def add_hyperlink(paragraph, url, text, style="Hyperlink"):
new_run.style = style
hyperlink.append(new_run)

paragraph._p.append(hyperlink) # pylint: disable=protected-access
paragraph._p.append(hyperlink)

return hyperlink
Loading

0 comments on commit 2ad8071

Please sign in to comment.