Development Setup¶
Prerequisites¶
| Tool | Requirement |
|---|---|
| Python | ≥ 3.8 to run; 3.11+ recommended for development so mypy and the async test suite behave predictably. |
| Git | Any recent version. |
| Make | Optional; the Makefile targets are conveniences over plain commands. |
Setup¶
Dependency extras¶
| Extra | Contents |
|---|---|
dev | pytest, pytest-cov, pytest-asyncio, pytest-mock, pytest-httpx, mypy, types-setuptools, pre-commit |
test | the pytest stack only |
docs | mkdocs, mkdocs-material, mkdocstrings[python], pymdown-extensions, mkdocs-minify-plugin |
Install the docs extra when touching anything under docs/:
Verification commands¶
These four commands are the contract. Run all of them before opening a pull request.
# 1. Tests — fast, no coverage instrumentation
python -m pytest tests -q --no-cov
# 2. Types — pin the analysis version; pyproject declares 3.8, which modern mypy rejects
python -m mypy depkeeper --python-version 3.13
# 3. Syntax — catches edits that silently join two source lines
python -m compileall -q depkeeper
# 4. Hooks — formatting and file hygiene
pre-commit run --all-files
Why --python-version 3.13
pyproject.toml sets python_version = "3.8" for mypy, which current mypy releases refuse to analyse. Pass the flag explicitly. The project's baseline is a single known error (data_store.py, no-any-return); anything beyond that is yours.
Why --no-cov
addopts in pyproject.toml enables coverage with term, HTML and XML reports on every run. That is what CI wants and what a fast edit-test loop does not. --no-cov skips it.
Coverage when you do want it:
python -m pytest --cov=depkeeper --cov-report=term-missing
make test # term + html + xml, as CI runs it
Change workflow¶
1. Branch¶
| Type | Prefix | Example |
|---|---|---|
| Feature | feature/ | feature/private-index-support |
| Fix | fix/ | fix/parser-line-continuations |
| Docs | docs/ | docs/json-schema |
| Refactor | refactor/ | refactor/extract-resolution-loop |
| Tests | test/ | test/analyzer-stall-cases |
2. Write a failing test first¶
For a bug fix this is mandatory. The test must fail before the fix and pass after it; that is the only evidence that the fix addresses the reported behaviour.
3. Implement¶
- Respect the layering rules:
modelsperform no I/O,coreprints nothing,commandsown all user interaction. - Do not weaken a system invariant without an explicit argument in the pull request.
- Add new tunables to
constants.py, never inline.
4. Verify¶
Run all four verification commands above.
5. Update documentation¶
Behavioural changes require documentation changes in the same pull request. The pages most often affected:
| Change | Pages |
|---|---|
| New or changed flag | CLI commands, the relevant guide |
| Changed recommendation logic | Version recommendation |
| Changed resolver behaviour | Conflict resolution |
| New error or warning message | Error reference |
| Fixed a documented limitation | Known limitations |
| New JSON field | JSON output |
6. Commit and open a pull request¶
git commit -m "fix(parser): join backslash line continuations
pip-compile --generate-hashes wraps hashes onto continuation lines, which
the line-based parser treated as separate requirements.
Closes #123"
git push origin fix/parser-line-continuations
Makefile targets¶
| Target | Command it runs |
|---|---|
make install | pip install -e . |
make install-dev | pip install -e ".[dev]" + pre-commit install |
make test | pytest with term, HTML and XML coverage |
make typecheck | mypy depkeeper |
make all | typecheck then test |
make docs | mkdocs build |
make docs-serve | mkdocs serve |
make clean | Removes build, cache and coverage artefacts |
The Makefile targets assume a POSIX shell. On Windows, run the underlying commands directly.
Working on the documentation¶
pip install -e ".[docs]"
mkdocs serve # http://127.0.0.1:8000, live reload
mkdocs build --strict # what CI runs
mkdocs.yml sets strict: true, so a broken internal link, a missing snippet or an unresolved mkdocstrings reference fails the build. Always run --strict before pushing.
Documentation conventions:
- Every behavioural claim must be verifiable against the implementation. Run the command and paste the real output rather than composing an illustrative one.
- Cross-link rather than duplicate. Concepts live in
concepts/, exhaustive lists inreference/, tasks inguides/. - Prefer tables to prose for enumerable facts.
- API documentation is generated from docstrings via
mkdocstrings; fix the docstring, not the page.
Repository layout¶
depkeeper/ Package source (see the architecture module map)
tests/ Test suite, mirroring the package layout
support/ Shared factories, fake PyPI, dataset builders
integration/ Multi-component workflow tests
docs/ This documentation site
scripts/ Developer setup scripts
mkdocs.yml Documentation site configuration
pyproject.toml Packaging, mypy, pytest and coverage configuration
Makefile Development shortcuts
.pre-commit-config.yaml
Pre-commit hooks¶
Pinned so a local run applies exactly the checks CI applies:
trailing-whitespace,end-of-file-fixermixed-line-ending --fix=lf— the repository itself is LF-only, so diffs stay meaningful (this is independent of depkeeper's runtime behaviour, which preserves whatever a target file uses)check-yaml(excludingmkdocs.yml, which uses!!python/name:tags a safe loader rejects)check-json,check-toml,check-astcheck-added-large-files --maxkb=1000check-case-conflict,check-merge-conflict
Troubleshooting the environment¶
| Symptom | Fix |
|---|---|
mypy: Python 3.8 is not supported | Pass --python-version 3.13. |
| Tests are slow | Use --no-cov; coverage reporting is on by default. |
caplog captures nothing in a new test module | setup_logging sets propagate = False process-wide. See Testing → Logging isolation. |
mkdocs build fails on a link | strict: true treats broken links as errors. Fix the link. |
| Console colour leaks between tests | Use the _isolate_console fixture; reconfigure_console() clears the memoised consoles. |