Metadata-Version: 2.4
Name: vcti-measure-report
Version: 2.0.0
Summary: Reports from a vcti-measure artifact through Jinja2 templates — one projection, any output format.
Author: Visual Collaboration Technologies Inc.
License-Expression: LicenseRef-Proprietary
Project-URL: Repository, https://github.com/vcollab/vcti-python-measure-report
Project-URL: Changelog, https://github.com/vcollab/vcti-python-measure-report/blob/main/CHANGELOG.md
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Requires-Python: <3.15,>=3.12
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: vcti-measure<2,>=1.1
Requires-Dist: vcti-template<4,>=3
Requires-Dist: vcti-escapers<2,>=1
Requires-Dist: pydantic<3,>=2.7
Provides-Extra: test
Requires-Dist: pytest; extra == "test"
Requires-Dist: pytest-cov; extra == "test"
Provides-Extra: lint
Requires-Dist: ruff; extra == "lint"
Provides-Extra: typecheck
Requires-Dist: mypy; extra == "typecheck"
Dynamic: license-file

# vcti-measure-report

Reports from a vcti-measure artifact through Jinja2 templates — one
projection, any output format.

An artifact records one run completely. It is not a report. Turning it into
one means resolving axis labels, grouping by item, pairing each reading with
the target that applies to it, and accounting for the points that produced
nothing — and none of that changes when the output format does.

So this package does that work once, in Python, and leaves templates to do
only syntax. It **projects** an artifact into flat rows carrying everything a
report needs, and **renders** those rows through a template. Which is why one
package serves HTML, Markdown and CSV, and why a user can add a format by
writing a template rather than by waiting for a package.

## Installation

```bash
pip install vcti-measure-report
```

### In `requirements.txt`

```
vcti-measure-report>=2.0.0,<3
```

### In `pyproject.toml` dependencies

```toml
dependencies = [
    "vcti-measure-report>=2.0.0,<3",
]
```

---

## Quick Start

Read an artifact and render it:

```python
from vcti.measure.report import Report

report = Report.from_text(path.read_text(encoding="utf-8"), title="Week 36")
print(report.render("summary.md"))
print(report.render("long.csv"))
```

A `Report` validates the document through `vcti-measure` once, when it is
built, then renders as many formats as you like from that one pass. It never
writes anything — rendering returns text, so storage policy stays with you.

Add your own format by writing a template:

```python
print(report.render("our-house-style.html", template_dirs=["./templates"]))
```

Your template is an addition, not a replacement: the bundled names resolve
first, so `summary.md` and `long.csv` are reserved. Name yours something
else — including when it started life as a copy of one of ours.

A template receives flat `rows` — one per observation per metric, with the
axis label, the unit, the target and the status already resolved — so
grouping is Jinja's own `groupby` and `selectattr`, not an accumulator:

```jinja
{% for item, irows in rows | selectattr("role", "equalto", "subject") | groupby("item") %}
### {{ item }}
{% for r in irows %}
| {{ r.coordinate_label }} | {{ r.metric }} | {{ r.value | quantity(r.unit) }} |
{% endfor %}
{% endfor %}
```

---

## What this package does not do

- **Produce artifacts** — it reads them. Declaring measurements and running
  instruments belong to `vcti-measure` and to domain packages above it.
- **Define validity** — a `Report` *does* validate, by calling
  `vcti-measure`'s `validate_artifact`: it refuses to render what core would
  refuse to read. The rules themselves live in one place, and it is not
  here.
- **Write files** — rendering returns text.
- **Compare across runs** — a row is joinable across artifacts by
  construction, but accumulating them is somebody else's job.

Each of these is explained in [docs/design.md](docs/design.md).

---

## Dependencies

`vcti-measure` for the artifact and its validation, `vcti-template` for
template loading and strict rendering, `vcti-escapers` for the per-medium
escapers a template applies, and `pydantic` for the row model. Charting is
deferred, and no charting dependency is taken.

---

## Documentation

| If you want to… | Read |
|---|---|
| Solve a real reporting problem | [docs/patterns.md](docs/patterns.md) |
| Understand the architecture and design decisions | [docs/design.md](docs/design.md) |
| Navigate and change the code | [docs/source-guide.md](docs/source-guide.md) |
| Add a format, a filter or a field | [docs/extending.md](docs/extending.md) |
