from-markdown takes a hand-written summary such as SUMMARY.md and sets it in the full report's dress: the same cover, header, footers, table of contents, headings and grids. The shared macros move to macros.html.j2 so both templates draw from them, and layout.render_pdf takes the template and document title to use. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
119 lines
4.8 KiB
TOML
119 lines
4.8 KiB
TOML
# Packaging for report_generator as a repository of its own.
|
|
#
|
|
# The split out of the monorepo has happened: the package sits in `report_generator/` beside this
|
|
# file, which is what `packages.find` below looks for. In the monorepo the same sources live at
|
|
# `src/persistent_storage/report_generator/` and are built by the monorepo's own pyproject; this
|
|
# one is not read there.
|
|
#
|
|
# The dependency pins mirror the monorepo's, so that a tool split out of it does not silently start
|
|
# resolving different versions of the libraries it was tested against.
|
|
|
|
[build-system]
|
|
requires = ["setuptools>=77.0"]
|
|
build-backend = "setuptools.build_meta"
|
|
|
|
[project]
|
|
name = "report-generator"
|
|
version = "0.1.0"
|
|
description = "Builds the PDF report of a stored scan from the artifacts it produced."
|
|
readme = "README.md"
|
|
requires-python = ">=3.14"
|
|
# PEP 639: an SPDX expression. "Proprietary" is not one; a private licence is spelled LicenseRef-*.
|
|
license = "LicenseRef-Proprietary"
|
|
authors = [{ name = "CipherCell" }]
|
|
|
|
dependencies = [
|
|
# The CLI, its configuration files and the properties models every command is described by.
|
|
"typer>=0.24.1",
|
|
"typer-config>=1.5.1",
|
|
"pydantic>=2.13.4",
|
|
"python-dotenv>=1.2.2",
|
|
"rich>=15.0.0",
|
|
"pyyaml>=6.0.3",
|
|
|
|
# The store: scan and artifact rows out of Postgres, artifact files out of the bucket.
|
|
"SQLAlchemy>=2.0.49",
|
|
"psycopg2-binary>=2.9.9",
|
|
"boto3>=1.43.0",
|
|
|
|
# The report: the template, and the engine that turns it into a PDF. WeasyPrint additionally
|
|
# needs the native Pango and cairo libraries, which pip does not install -- see the README.
|
|
"jinja2>=3.1.6",
|
|
"weasyprint>=69.0",
|
|
# The summary report, which is written in Markdown and set in the same template.
|
|
"markdown-it-py>=4.0.0",
|
|
]
|
|
|
|
[project.optional-dependencies]
|
|
dev = [
|
|
"pytest>=9.0.0",
|
|
"mypy>=1.19.0",
|
|
"ruff>=0.15.16",
|
|
"mypy-boto3-s3>=1.43.31",
|
|
# Reads the rendered PDF back, so the tests can check what actually came out.
|
|
"pymupdf>=1.24.0",
|
|
]
|
|
|
|
[project.scripts]
|
|
report_generator = "report_generator.__main__:run"
|
|
|
|
[tool.setuptools.packages.find]
|
|
# `vendor` is deliberately included: outside the monorepo it is what supplies cc_common,
|
|
# persistent_storage and the two summarisers, and `vendor/__init__.py` puts it on the path.
|
|
include = ["report_generator*"]
|
|
|
|
[tool.setuptools.package-data]
|
|
# Loaded at runtime by __file__, so it has to be installed beside the module: the Jinja template,
|
|
# the print stylesheet, the mark, and the font files the stylesheet references by relative URL.
|
|
"report_generator" = ["template/**/*"]
|
|
# The copies are data as far as packaging is concerned -- they are put on the path, not imported
|
|
# as submodules of this package.
|
|
"report_generator.vendor" = ["**/*.py", "**/py.typed"]
|
|
|
|
[tool.ruff]
|
|
line-length = 120
|
|
target-version = "py314"
|
|
# The copies are checked where they are written, not where they are copied to. Left in, every class
|
|
# they define is read twice under two import paths.
|
|
exclude = ["report_generator/vendor"]
|
|
|
|
[tool.ruff.lint]
|
|
select = ["E", "W", "F", "I", "N", "D", "ANN", "B", "C4", "SIM", "RUF"]
|
|
# RUF100: the sources carry `# noqa` for rules the monorepo's own ruff config does not select
|
|
# either -- they are stale there too, just invisible, because the monorepo does not select RUF.
|
|
# Flagging them here would mean editing the copies, and the copies have to stay copies.
|
|
ignore = ["D203", "D213", "RUF100"]
|
|
|
|
[tool.ruff.lint.pydocstyle]
|
|
convention = "google"
|
|
|
|
[tool.ruff.lint.isort]
|
|
# What the monorepo sorts these as: it lints from a root where all three live under `src/`, which
|
|
# ruff's default `src = [".", "src"]` makes first-party. Here they arrive through `vendor/` and
|
|
# would be sorted as third-party instead. Declared so that this repository reports the same import
|
|
# findings the monorepo does -- no more and no fewer -- and the copies can stay copies.
|
|
known-first-party = ["cc_common", "persistent_storage", "cipherverifier"]
|
|
|
|
[tool.mypy]
|
|
strict = true
|
|
python_version = "3.14"
|
|
# The copies are on the path at runtime only because `vendor/__init__.py` puts them there, which
|
|
# mypy does not execute. Named here so the borrowed modules resolve while still being excluded
|
|
# from being checked themselves.
|
|
mypy_path = ["report_generator/vendor"]
|
|
exclude = ["(^|/)report_generator/vendor/"]
|
|
|
|
[[tool.mypy.overrides]]
|
|
module = ["weasyprint.*", "pymupdf.*"]
|
|
ignore_missing_imports = true
|
|
|
|
# `exclude` keeps mypy from crawling into the copies; it does not stop it following an import into
|
|
# them. They are checked where they are written, so their own errors are not this repository's to
|
|
# report -- their types still are, which is why they are followed at all rather than ignored.
|
|
[[tool.mypy.overrides]]
|
|
module = ["cc_common.*", "persistent_storage.*", "cipherverifier.*"]
|
|
follow_imports = "silent"
|
|
|
|
[tool.pytest.ini_options]
|
|
testpaths = ["tests"]
|