neuropose/docs/development.md

168 lines
5.6 KiB
Markdown

# Development
This page is for contributors working on NeuroPose itself.
## Environment setup
NeuroPose uses [`uv`](https://github.com/astral-sh/uv) for dependency
management and Python 3.11. After cloning the repository:
```bash
uv venv --python 3.11
source .venv/bin/activate
uv sync --group dev
uv run pre-commit install
```
`uv sync --group dev` installs the project in editable mode alongside
the full dev dependency set (pytest, ruff, pyright, pre-commit,
mkdocs-material, and mkdocstrings).
`pre-commit install` wires the git hooks declared in
`.pre-commit-config.yaml` into your local repo so every commit is
linted, formatted, and scanned for secrets before it lands.
## Running tests
Unit tests are fast and do not require the MeTRAbs model or TensorFlow
inference:
```bash
uv run pytest
```
Integration tests that require a downloaded model are marked with
`@pytest.mark.slow` and are skipped by default. Run them with:
```bash
uv run pytest -m slow
```
Run a specific test file or test class:
```bash
uv run pytest tests/unit/test_estimator.py
uv run pytest tests/unit/test_estimator.py::TestProcessVideo
uv run pytest -k "frame_count"
```
The autouse `_isolate_environment` fixture in `tests/conftest.py` points
`$HOME` and `$XDG_DATA_HOME` at a per-test temp directory, so no test
can accidentally write to your real home directory. It also clears any
`NEUROPOSE_*` variables from your shell so test outcomes do not depend
on who is running them.
## Linting and formatting
NeuroPose uses [`ruff`](https://docs.astral.sh/ruff/) for both lint and
format. Configuration lives in `pyproject.toml` under `[tool.ruff]`.
```bash
uv run ruff check . # Lint
uv run ruff check --fix . # Lint + auto-fix
uv run ruff format . # Format (equivalent to black)
uv run ruff format --check . # Verify formatted
```
The selected lint rules are deliberately broad — pycodestyle, pyflakes,
isort, bugbear, pyupgrade, simplify, ruff-specific, pep8-naming,
comprehensions, pathlib, pytest-style, tidy-imports, numpy-specific,
and pydocstyle (numpy convention). The rationale is "lint noise early
rather than cruft late": we would rather annoy a contributor with a
style fix than let a real bug slip through because the linter was lax.
## Type checking
NeuroPose uses [`pyright`](https://github.com/microsoft/pyright) in
`standard` mode (not `strict` — the TensorFlow / OpenCV / scikit-learn
stubs would generate thousands of false positives under strict). The
plan is to tighten toward strict after the MeTRAbs stack is pinned in
commit 11.
```bash
uv run pyright
```
## Documentation
Documentation is built with [MkDocs](https://www.mkdocs.org/) and the
[Material theme](https://squidfunk.github.io/mkdocs-material/). API
reference pages are auto-generated from the source docstrings by
[mkdocstrings](https://mkdocstrings.github.io/).
Live preview at `http://localhost:8000`:
```bash
uv run mkdocs serve
```
Strict build (the same one CI runs):
```bash
uv run mkdocs build --strict
```
`--strict` promotes every warning (broken internal link, missing nav
entry, unparseable docstring) to an error, so broken docs fail the
build instead of silently producing a broken site.
Adding a new module means:
1. Write it with numpy-style docstrings (the plugin's
`docstring_style: numpy` setting).
2. Add a stub page under `docs/api/` containing a single `:::` directive:
```markdown
::: neuropose.your_module
```
3. Add a nav entry in `mkdocs.yml` under `API Reference`.
## Project structure
```text
neuropose/
├── src/neuropose/ # The package itself
│ ├── config.py # pydantic-settings Settings class
│ ├── estimator.py # per-video MeTRAbs worker
│ ├── interfacer.py # filesystem-polling daemon
│ ├── visualize.py # matplotlib overlay rendering
│ ├── io.py # prediction schema + atomic save/load
│ ├── cli.py # typer CLI entrypoint
│ ├── _model.py # MeTRAbs loader (stub pending commit 11)
│ └── analyzer/ # post-processing (pending commit 10)
├── tests/
│ ├── conftest.py # isolated env + synthetic video fixtures
│ ├── unit/ # fast, no model download
│ └── integration/ # marked slow, downloads the model
├── docs/ # this documentation
├── .github/workflows/ # CI + docs workflows
├── pyproject.toml # package metadata, deps, tool configs
└── mkdocs.yml # docs site configuration
```
## Commit hygiene
- **Small commits.** Each commit should do one thing and leave the repo
in a green-CI state.
- **Descriptive commit messages.** The body should explain *why*, not
restate the diff. References to audit sections or issue numbers are
welcome.
- **No force-push on `main`.** Use a feature branch and open a merge
request on the primary forge. `main` is protected; the CI checks
must pass before merging.
- **No `git commit --no-verify`.** If a pre-commit hook fails, fix the
underlying issue rather than skipping the hook. The hooks exist
because the previous prototype was the poster child for what happens
when hygiene slips.
## Release process
*To be documented when the first tagged release is cut.* The short
version of the plan:
1. Bump `version` in `pyproject.toml` and `__version__` in
`src/neuropose/__init__.py`.
2. Update `CHANGELOG.md`.
3. Tag the commit (`git tag v0.1.0`).
4. Push the tag. A release workflow builds the wheel + sdist and
uploads to PyPI once we claim the name.