Skip to content
Open
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
2 changes: 1 addition & 1 deletion docs.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ the framework's own interrupt, and a framework with no such primitive does not n
## Where it stands

{/* generated from the suite, pyproject and the soak (mdx) — run the generator */}
- **Version 0.6.1**, on [PyPI](https://pypi.org/project/ctrlrun/), Python 3.11 and later.
- **Version 0.6.1**, on [PyPI](https://pypi.org/project/ctrlrun/), Python 3.11 and later, tested on 3.11 to 3.14.
- **4,408 tests**, every version specified before it was written and every requirement mutation-tested.
- **11 guarantees you can check in your own setup**, with `ctrlrun verify` against your policy, on your store's backend, in a scratch store it creates.
- **One host: a file.** SQLite, no server, no ops. **Many hosts: Postgres**, the same guarantees, graded by the same suite.
Expand Down
3 changes: 2 additions & 1 deletion docs/get-started/install.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ description: "pip install ctrlrun puts one package, pyyaml and click on your mac

`pip install ctrlrun` installs the kernel and exactly two dependencies, `pyyaml` and `click`. It
needs Python 3.11 or later and nothing running: no server, no database, no dashboard. State is a
SQLite file the library creates beside your policy.
SQLite file the library creates beside your policy. CI runs the full suite on Python 3.11, 3.12,
3.13 and 3.14.

```bash
pip install ctrlrun
Expand Down
2 changes: 1 addition & 1 deletion docs/production/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ need. `test_the_first_line_of_the_section_says_which_store_and_why` asserts the
## Where it stands

{/* generated from the suite, pyproject and the soak (full) — run the generator */}
- **Version 0.6.1**, on [PyPI](https://pypi.org/project/ctrlrun/), Python 3.11 and later.
- **Version 0.6.1**, on [PyPI](https://pypi.org/project/ctrlrun/), Python 3.11 and later, tested on 3.11 to 3.14.
- **4,408 tests**, every version specified before it was written and every requirement mutation-tested. [Read more](/docs/how-this-is-built).
- **11 guarantees you can check in your own setup**, with `ctrlrun verify` against your policy, on your store's backend, in a scratch store it creates. [Read more](/docs/security/verify-guarantees).
- **One host: a file.** SQLite, no server, no ops. **Many hosts: Postgres**, the same guarantees, graded by the same suite. [Read more](/docs/production/postgres).
Expand Down
2 changes: 1 addition & 1 deletion generated/readiness.full.mdx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{/* generated from the suite, pyproject and the soak (full) — run the generator */}
- **Version 0.6.1**, on [PyPI](https://pypi.org/project/ctrlrun/), Python 3.11 and later.
- **Version 0.6.1**, on [PyPI](https://pypi.org/project/ctrlrun/), Python 3.11 and later, tested on 3.11 to 3.14.
- **4,408 tests**, every version specified before it was written and every requirement mutation-tested. [Read more](/docs/how-this-is-built).
- **11 guarantees you can check in your own setup**, with `ctrlrun verify` against your policy, on your store's backend, in a scratch store it creates. [Read more](/docs/security/verify-guarantees).
- **One host: a file.** SQLite, no server, no ops. **Many hosts: Postgres**, the same guarantees, graded by the same suite. [Read more](/docs/production/postgres).
Expand Down
9 changes: 9 additions & 0 deletions generated/readiness.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
{
"guarantees": 11,
"python": {
"floor": "3.11",
"tested": [
"3.11",
"3.12",
"3.13",
"3.14"
]
},
"released": "0.6.1",
"soak": {
"actions": 889735,
Expand Down
2 changes: 1 addition & 1 deletion generated/readiness.mdx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{/* generated from the suite, pyproject and the soak (mdx) — run the generator */}
- **Version 0.6.1**, on [PyPI](https://pypi.org/project/ctrlrun/), Python 3.11 and later.
- **Version 0.6.1**, on [PyPI](https://pypi.org/project/ctrlrun/), Python 3.11 and later, tested on 3.11 to 3.14.
- **4,408 tests**, every version specified before it was written and every requirement mutation-tested.
- **11 guarantees you can check in your own setup**, with `ctrlrun verify` against your policy, on your store's backend, in a scratch store it creates.
- **One host: a file.** SQLite, no server, no ops. **Many hosts: Postgres**, the same guarantees, graded by the same suite.
Expand Down
2 changes: 1 addition & 1 deletion generated/readiness.readme.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<!-- generated from the suite, pyproject and the soak (readme) — run the generator -->
- **Version 0.6.1**, on [PyPI](https://pypi.org/project/ctrlrun/), Python 3.11 and later.
- **Version 0.6.1**, on [PyPI](https://pypi.org/project/ctrlrun/), Python 3.11 and later, tested on 3.11 to 3.14.
- **4,408 tests**, every version specified before it was written and every requirement mutation-tested.
- **11 guarantees you can check in your own setup**, with `ctrlrun verify` against your policy, on your store's backend, in a scratch store it creates.
- **One host: a file.** SQLite, no server, no ops. **Many hosts: Postgres**, the same guarantees, graded by the same suite.
Expand Down
42 changes: 39 additions & 3 deletions tools/docs_audit/render_readiness.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
every number in it comes from something that measures itself:

- the version and the dependency floor from `pyproject.toml`;
- the Python floor from `requires-python`, and the Pythons tested from CI's `check` matrix;
- the test count from `pytest --collect-only`, recorded in `generated/readiness.json`;
- the soak's duration, actions and unattributed count from `research/soak/results/*.json`;
- what `ctrlrun verify` checks from the guarantee catalogue itself.
Expand Down Expand Up @@ -32,6 +33,8 @@
import tomllib
from pathlib import Path

import yaml

from _core import CORE_ROOT
from _files import REPO_ROOT, relative

Expand All @@ -58,6 +61,37 @@ def _version() -> str:
return str(tomllib.load(handle)["project"]["version"])


def _python() -> dict:
"""The Python floor the package declares, and the Pythons CI's `check` job runs the suite on.

The block said *"Python 3.11 and later"* as a literal, which stays true when CI adds a
version and so never drifted into a failure. The tested list is read from the matrix rather
than the classifiers because the matrix is what runs the suite; a classifier is a label.
"""
with (CORE_ROOT / "pyproject.toml").open("rb") as handle:
requires = str(tomllib.load(handle)["project"]["requires-python"])
if not re.fullmatch(r">=3\.\d+", requires):
raise SystemExit(f"requires-python is {requires!r}; the block can only state a >=3.N floor")
workflow = CORE_ROOT / ".github" / "workflows" / "ci.yml"
matrix = yaml.safe_load(workflow.read_text(encoding="utf-8"))["jobs"]["check"]["strategy"]
tested = matrix["matrix"]["python-version"]
# Unquoted in YAML, `3.10` is the float 3.1. Refused rather than repaired.
if not all(isinstance(version, str) for version in tested):
raise SystemExit(f"CI's python-version matrix must be quoted strings, got {tested!r}")
floor = requires.removeprefix(">=")
if floor not in tested:
raise SystemExit(f"requires-python is {requires} and CI's check job does not test {floor}")
return {"floor": floor, "tested": sorted(tested, key=lambda v: tuple(map(int, v.split("."))))}


def _tested(versions: list[str]) -> str:
"""`3.11 to 3.14` for a contiguous run of minors, `3.11, 3.12 and 3.14` otherwise."""
minors = [int(version.split(".")[1]) for version in versions]
if len(versions) > 2 and minors == list(range(minors[0], minors[-1] + 1)):
return f"{versions[0]} to {versions[-1]}"
return versions[0] if len(versions) == 1 else f"{', '.join(versions[:-1])} and {versions[-1]}"


#: A changelog heading: `## [0.6.0] - unreleased — Durable runtime`, or with a date. The file
#: uses a hyphen and an em dash interchangeably as the separator, so both are accepted.
_HEADING = re.compile(r"^## \[(?P<version>[^\]]+)\]\s*[-—]\s*(?P<when>[^\s—]+)", re.M)
Expand Down Expand Up @@ -141,6 +175,7 @@ def measure() -> dict:
run = soak()
return {
"version": _version(),
"python": _python(),
"released": released(),
"tests": collected(),
"guarantees": _guarantees(),
Expand All @@ -167,6 +202,7 @@ def _lines(data: dict, *, full: bool) -> list[str]:
version, tests, guarantees = data["version"], data["tests"], data["guarantees"]
run, published = data["soak"], data.get("released")
link = "https://pypi.org/project/ctrlrun/"
python = f"Python {data['python']['floor']} and later, tested on {_tested(data['python']['tested'])}."

def where(text: str, page: str) -> str:
"""`full` adds a Read-more link; the other formats carry the sentence alone.
Expand All @@ -183,10 +219,10 @@ def where(text: str, page: str) -> str:

lines = [
(
f"- **Version {version}**, on [PyPI]({link}), Python 3.11 and later."
f"- **Version {version}**, on [PyPI]({link}), {python}"
if published == version
else f"- **Version {version} is in development**; [PyPI]({link}) has {published}. "
"Python 3.11 and later."
+ python
),
where(
f"- **{tests:,} tests**, every version specified before it was written and every "
Expand Down Expand Up @@ -278,7 +314,7 @@ def check(data: dict, pages: list[Path] | None = None) -> list[str]:
f"the block claims {recorded['tests']:,} tests and the suite collects {current:,}; "
"run --write"
)
for key in ("version", "released", "guarantees", "soak"):
for key in ("version", "python", "released", "guarantees", "soak"):
if recorded.get(key) != data.get(key):
drift.append(f"{key} changed since the block was generated; run --write")
for fmt in FORMATS:
Expand Down