Development
Environment
Use Python 3.10 or newer.
python -m pip install -e ".[dev,docs]"
The package uses Hatchling with VCS-based dynamic versioning.
Runtime dependencies
The runtime dependencies include:
typerrichpydantic>=2tomli-wtomlion Python older than 3.11beautifulsoup4markdown-it-pyphrasplitepub2text>=0.2.4text2epub
ebooklib and mypy are included in the dev extra so the documented test/type-check commands run after a single editable install. docs/conf.py (Sphinx, MyST, Read the Docs theme) is covered by the docs extra. To install everything at once:
Docs dependencies
The docs extra installs the packages used by docs/conf.py (Sphinx, MyST, Read the Docs theme):
[project.optional-dependencies]
docs = [
"sphinx",
"myst-parser",
"sphinx-rtd-theme",
]
Test commands
pytest -q
ruff check .
pytest -q
ruff check .
mypy booktx
Canonical quality gate
Before a checkout is installed into a translation environment, run the repository quality gate from a clean project-root checkout:
python scripts/quality_gate.py --require-clean --artifact-dir dist \
--evidence-file /tmp/booktx-quality-gate.json
The gate runs compilation, the static command-catalog check, focused CLI import tests, the full test suite, Ruff, mypy, package building, and help smoke tests against the wheel installed in a temporary virtual environment. It stops at the first failed stage and prints the failed command. The evidence records the checked-out commit SHA, Python version, wheel filename and SHA-256, quality result, and installation target. Do not install an untested dirty checkout.
The release workflow uses the same command and publishes the exact dist/
artifacts produced by that successful run. Pull requests and main, master,
and release/* branches run the gate on Python 3.10 and 3.13.
For documentation changes, install the docs extra and run the repository’s
warnings-as-errors check:
python -m pytest tests/test_docs_consistency.py -q
sphinx-build -W -b html docs docs/_build/check
bash -n docs/build.sh
git diff --check
The same Sphinx check is available as make -C docs check. For a local HTML
and optional PDF build after dependencies are installed, run ./docs/build.sh;
the script uses the same -W warnings-as-errors policy. Generated files stay
under docs/_build/ and should not be committed.
Current test clusters
Test file |
Area |
|---|---|
|
Markdown/EPUB build behavior |
|
Chapter detection |
|
Segmentation and packing |
|
End-to-end CLI behavior |
|
Chapter CLI workflows |
|
Context CLI commands |
|
Project config and source discovery |
|
Context IO/rendering |
|
Context model contracts |
|
EPUB extraction/rebuild |
|
XHTML helpers |
|
Markdown extraction/rebuild |
|
Pydantic contract models |
|
Placeholder protection/restoration |
|
Record-level acceptance gates |
|
Translate/insert CLI workflows |
|
Legacy -> profile migration |
|
Profile create/list/show/select |
|
Progress snapshots |
|
Status bundles and overviews |
|
Task paths and submission parsing |
|
Translation version ledgers |
|
Translation contract validation |
|
Glossary/context validation |
Coding standards
Keep changes deterministic and local.
Do not add network calls to the CLI.
Preserve idempotent extraction.
Preserve translated files across extraction.
Add tests for every behavior change.
Keep user-facing errors clear and actionable.
Prefer small format-specific adapters over cross-format special cases.
Versioning
Version data is generated by Hatch VCS into booktx/_version.py. Do not hand-edit generated version output.
Fresh-process CLI tests
Some CLI bugs only manifest when each command runs in a fresh Python process.
The CliRunner used by most tests runs all commands in the same interpreter,
which can mask import-order issues (e.g. Pydantic forward-reference rebuilds).
When a bug involves cross-command state or module initialization, add a test
that uses subprocess.run to invoke booktx in separate processes. See
tests/test_cli_translate_todo.py::test_todo_commands_work_across_fresh_python_processes
for an example.
Durable model import contracts
Persisted JSON boundary models (TranslationTask, TranslationTodo, the
materialized translation-store model / compatibility alias TranslationStoreV2,
TranslationVersionLedger, context JSON models, manifest/config models) must
validate without hidden import-order requirements.
Rules:
Never use
TYPE_CHECKING-gated imports for types referenced in model fields.Never depend on late
model_rebuild()side effects for persisted models.If a model references a type from another module, that type must be directly importable at module load time.
Add a test in
tests/test_models.pythat validates minimal payloads for each durable model without importing command-specific modules.