pytest-rhiza
The rhiza repository checks, installed as a pytest
plugin instead of synced into every consumer repository as .rhiza/tests/.
Why
The seven modules the template syncs into .rhiza/tests/ are parameterised by exactly two
things: the repository root, and SOURCE_FOLDER from .rhiza/.env. Nothing else about
them varies per project. Distributing them by file copy costs every consumer repo:
- seven template-owned files in the tree, plus a
conftest.pynobody may edit pythonpath = .rhiza/testsinpytest.ini, so the synced suite can import itself.rhiza/testsappended tomake docs-coverage's interrogate paths, holding template code to the project's 100% docstring bar--with pytest-timeout --with python-dotenv --with packagingspelled out in therhiza-testrecipe, because a copied file carries no dependency metadata- the template's own
TestSkipFlagmeta-tests re-running in every project, testing rhiza against itself
All five go away when the checks are a dependency. The dependency list is deliberately
four small packages — folding them into rhiza would pull jinja2, typer, rich and
loguru into every test environment, and into rhiza-tools would add pandas and
plotly.
Install
uv add --dev pytest-rhiza
Or, the way make rhiza-test does it, without touching the project's dependencies:
uv run --with pytest-rhiza pytest --pyargs pytest_rhiza.checks.test_readme
How it is put together
Two halves, because pytest treats them differently.
The fixtures arrive through the pytest11 entry point and are available to any test
in the session without a conftest.py:
| fixture | what it gives you |
|---|---|
root |
the repository under test, as a Path |
logger |
a session-scoped logger |
latest_tag |
the newest vX.Y.Z tag, skipping when the repo has none |
The checks are tests, which an entry point cannot contribute, so they are named
explicitly with --pyargs. One module per file the template used to sync, names unchanged:
| module | named by | replaces |
|---|---|---|
test_readme |
core |
.rhiza/tests/test_readme.py |
test_release_tags |
core |
.rhiza/tests/test_release_tags.py |
test_pyproject |
python-core |
.rhiza/tests/test_pyproject.py |
test_docstrings |
python-core |
.rhiza/tests/test_docstrings.py |
test_readme_validation |
tests |
.rhiza/tests/test_readme_validation.py |
test_cargo_toml |
rust-core |
.rhiza/tests/test_cargo_toml.py |
test_go_module |
go-core |
.rhiza/tests/test_go_module.py |
Which repository is "root"
The one deliberate behaviour change from the synced suite. .rhiza/tests/conftest.py
resolved the root by counting directories up from __file__ — sound while the code lived
in the repository, wrong once it is installed. Resolution is now:
--rhiza-root, when given- the directory holding the config file (
pytest.ini,pyproject.toml, …) - the directory pytest was invoked from
Step 3 rather than config.rootpath on purpose: with no config file, pytest derives its
rootdir from the arguments, and under --pyargs those are paths inside site-packages.
The make wiring this expects
Selection stays exactly where the template already has it — with the bundle that owns the assertion, resolved at sync time — because each bundle's make fragment names its own check modules. No runtime manifest sniffing decides what applies, so a misconfigured repo still goes red instead of quietly skipping.
core's quality.mk:
RHIZA_CHECKS ?= pytest_rhiza.checks.test_readme pytest_rhiza.checks.test_release_tags
rhiza-test: install ## run the rhiza repository checks
@${UV_BIN} run --with 'pytest-rhiza==0.1.0' pytest --pyargs ${RHIZA_CHECKS}
python-core's python.mk appends its own, and rust-core / go-core / tests do the
same with theirs:
RHIZA_CHECKS += pytest_rhiza.checks.test_pyproject pytest_rhiza.checks.test_docstrings
That is one += line per bundle, replacing one synced file per bundle.
Two things still to decide
Version pinning. Today the checks and the template move as one — template.lock pins
a ref and the files come with it. A separate distribution adds a second version axis. The
recipe above pins an exact version so there is still one number to reason about, but the
sync has to generate that pin from the template release. The alternative is aligning
this package's major.minor with template releases and pinning ~=.
Removing the old folder. A consumer on the current template has .rhiza/tests/ on
disk. The sync ceasing to deliver it does not delete it, and a leftover copy would run
twice as long as pythonpath still finds it. The migration PR needs an explicit removal
step.
Development
uv sync
uv run pytest
The checks run against this repository too — it is a Python project with a README, a
pyproject.toml and a release config, so it is a valid subject for its own assertions:
uv run pytest --pyargs pytest_rhiza.checks.test_readme pytest_rhiza.checks.test_pyproject
License
MIT — see LICENSE.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pytest_rhiza-0.2.1.tar.gz.
File metadata
- Download URL: pytest_rhiza-0.2.1.tar.gz
- Upload date:
- Size: 57.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0779461645455c63eab0bd6e81126deb3cd11fa1894b21a8b01ff5104c520e2e
|
|
| MD5 |
13aee36fc341e9dbbf020db7760be6be
|
|
| BLAKE2b-256 |
d7bdf2c9fda6f17b4cfc27e5eb9062aef43263fb5188d39e71e3dea51f4935d0
|
Provenance
The following attestation bundles were made for pytest_rhiza-0.2.1.tar.gz:
Publisher:
rhiza_release.yml on Jebel-Quant/pytest-rhiza
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pytest_rhiza-0.2.1.tar.gz -
Subject digest:
0779461645455c63eab0bd6e81126deb3cd11fa1894b21a8b01ff5104c520e2e - Sigstore transparency entry: 2501331648
- Sigstore integration time:
-
Permalink:
Jebel-Quant/pytest-rhiza@ce547643b3562af5fb5cacb5c0388b1011908ff8 -
Branch / Tag:
refs/tags/v0.2.1 - Owner: https://github.com/Jebel-Quant
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
rhiza_release.yml@ce547643b3562af5fb5cacb5c0388b1011908ff8 -
Trigger Event:
push
-
Statement type:
File details
Details for the file pytest_rhiza-0.2.1-py3-none-any.whl.
File metadata
- Download URL: pytest_rhiza-0.2.1-py3-none-any.whl
- Upload date:
- Size: 33.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
020e22dd85888c1c26ee0aec86ade056af4fe4d72b1a4c70176bce7399100e72
|
|
| MD5 |
e61f6515890498895b1f1d4d052c91ac
|
|
| BLAKE2b-256 |
26a81c63faee63f1270901f55b34509bc63a0c1633f6b54a166df96bc1f2deb5
|
Provenance
The following attestation bundles were made for pytest_rhiza-0.2.1-py3-none-any.whl:
Publisher:
rhiza_release.yml on Jebel-Quant/pytest-rhiza
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pytest_rhiza-0.2.1-py3-none-any.whl -
Subject digest:
020e22dd85888c1c26ee0aec86ade056af4fe4d72b1a4c70176bce7399100e72 - Sigstore transparency entry: 2501331655
- Sigstore integration time:
-
Permalink:
Jebel-Quant/pytest-rhiza@ce547643b3562af5fb5cacb5c0388b1011908ff8 -
Branch / Tag:
refs/tags/v0.2.1 - Owner: https://github.com/Jebel-Quant
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
rhiza_release.yml@ce547643b3562af5fb5cacb5c0388b1011908ff8 -
Trigger Event:
push
-
Statement type: