Development¶
The repository¶
| path | holds |
|---|---|
src/wend/ |
the package. Public modules (wend, wend.fs, wend.infer, wend.schema, ...) re-export from private ones (_expr.py, _match.py, _fs.py, ...) |
tests/ |
the tests, one file per area, named *_test.py |
examples/ |
runnable scripts, each run by tests/examples_test.py |
bench/bench.py |
the benchmarks |
docs/SEMANTICS.md |
the contract: what every operation must compute |
docs/MIGRATING.md |
the changes from 0.1 |
docs/journal/ |
the development journal (Project history) |
docs/site/, zensical.toml |
this site (Documentation) |
Setting up¶
wend needs Python 3.14 or later. uv installs the package
with its test dependency group, which is the default group:
uv sync
uv run pytest
just test runs the same tests with the project's Python. The test group includes
the optional integrations (Pydantic, fsspec, Polars), so their tests run too.
The hooks in .pre-commit-config.yaml (ruff, ruff format, file checks and a
conventional-commit check on the message) run with prek
or pre-commit:
prek install
just pc-fix # run every hook on every file
CI runs the tests on every CPython version from 3.14 that uv provides, including pre-releases.
The contract and its tests¶
docs/SEMANTICS.md states
what wend computes, independently of how. Two kinds of test check the code against it:
tests/contract_test.pyholds a reference evaluator written from the contract alone. It evaluates terms strictly with pathlib and imports only wend's parameter declarations, never its expressions, matcher or compiler. Hypothesis generates random terms and checks that wend agrees with it.tests/oracle_test.pybuilds each random expression twice, once with wend and once as the eager pathlib computation on the formatted strings. If wend renders a value, the oracle renders the same one; if the oracle raises, so does wend.
A change to the contract comes with the matching change to the reference evaluator, in the same pull request, and the reverse. SEMANTICS.md ยง8 says which guarantees hold by construction and which are only tested.
Benchmarks¶
uv run python bench/bench.py --quick
uv run python bench/bench.py matching discovery
Each timing is the median of several repeats, in nanoseconds per item, next to baselines such as eager pathlib joins and hand-written regular expressions. Absolute numbers depend on the machine, so compare rows within one run.
Conventions¶
- Commits follow Conventional Commits
(
feat(union): ...,fix(core): ...,docs: ...), checked by a commit-message hook.just commit "message"runs the fixers first and stages what they change. - Journal entries. A piece of work with decisions worth keeping gets an entry in
docs/journal/, namedYYYY-MM-DD-topic-<number>.mdafter its issue or pull request, in the format ofdocs/JOURNAL.md. - Documentation. A change to public behaviour updates the README, SEMANTICS.md where the contract changes, and the pages of this site that describe it. Their examples are tests, so a stale example fails CI.