Skip to content

Developer Guide

Quick start

Thanks for contributing! 🙏 Below you can find an overview of the commands to get you up and running quickly.

First clone the repository from GitHub

git clone <GITHUB-REPO>

and install the package locally in editable mode (-e):

cd dough
pip install -e .

Note

We support various tools for developers. Select your preferred one from the tabs below. If you don't know uv or Hatch, stick with the default for now.

The "default" approach to developing is to install the development extras in your current environment:

pip install -e .[pre-commit,tests,docs]

🔧 Pre-commit

To make sure your changes adhere to our formatting/linting preferences, install the pre-commit hooks:

pre-commit install

They will then run on every git commit. You can also run them on e.g. all files using:

pre-commit run -a

Drop the -a option in case you only want to run on staged files.

🧪 Tests

You can run all tests in the tests directory with pytest:

pytest

Or select the test module:

pytest tests/parsers/test_pw.py

See the pytest documentation for more information.

📚 Documentation

We use Material for MkDocs as our documentation framework. Start the documentation server with:

mkdocs serve

and open the documentation in your browser via the link shown. Every time you save a file, the corresponding documentation page is updated automatically!

A GitHub action is set up to automatically deploy the documentation to GitHub Pages. See the corresponding GitHub Pages documentation for the steps required.

uv is a Python package and project manager. See the documentation on how to install uv.

🔧 Pre-commit

To make sure your changes adhere to our formatting/linting preferences, install the pre-commit hooks:

uvx pre-commit install

They will then run on every git commit. You can also run them on e.g. all files using:

uvx pre-commit run -a

Drop the -a option in case you only want to run on staged files.

Note

Here we use the uvx command to run the pre-commit tool without installing it. Alternatively you can also install pre-commit as a tool and omit uvx.

🧪 Tests

You can run all tests in the tests directory with pytest:

uv run pytest

Or select the test module:

uv run pytest tests/parsers/test_pw.py

See the pytest documentation for more information.

📚 Documentation

We use Material for MkDocs as our documentation framework. Start the documentation server with:

mkdocs serve

and open the documentation in your browser via the link shown. Every time you save a file, the corresponding documentation page is updated automatically!

A GitHub action is set up to automatically deploy the documentation to GitHub Pages. See the corresponding GitHub Pages documentation for the steps required.

You can use Hatch to run development tools in isolated environments. To see a table of the available environments and their scripts, run:

hatch env show

🔧 Pre-commit

To make sure your changes adhere to our formatting/linting preferences, install the pre-commit hooks:

hatch run pre-commit:install

They will then run on every git commit. You can also run them on e.g. all files using:

hatch run pre-commit:run -a

Drop the -a option in case you only want to run on staged files.

🧪 Tests

You can run all tests in the tests directory using:

hatch test

Or select the test module:

hatch test tests/parsers/test_pw.py

You can also run the tests for a specific Python version with the -py option:

hatch test -py 3.11

Or all supported Python versions with --all:

hatch test --all

See the Hatch documentation for more information.

📚 Documentation

We use Material for MkDocs as our documentation framework. Start the documentation server with:

hatch run docs:serve

and open the documentation in your browser via the link shown. Every time you save a file, the corresponding documentation page is updated automatically!

A GitHub action is set up to automatically deploy the documentation to GitHub Pages. See the corresponding GitHub Pages documentation for the steps required.

Pre-commit rules

From the extensive Ruff ruleset, we ignore the following globally:

Code Rule Rationale / Note
TRY003 raise-vanilla-args Formatting warning/exception messages beforehand makes the code less readable, for a minor benefit in readability of the exception.
EM101 raw-string-in-exception Same as TRY003
EM102 f-string-in-exception Same as TRY003
PLR2004 magic-value-comparison We have a lot of “magic values” to compare with in scientific code; naming them all would reduce readability for little benefit.
FBT002 boolean-default-value-positional-argument We understand the concept, but adhering to this rule is not a small change in syntax; disable for now.
TID252 relative-imports We don’t mind relative imports; as long as you don’t go up a level, they’re more readable (less verbose).

And the following rules for the files in the tests directory:

Code Rule Rationale / Note
INP001 implicit-namespace-package When tests are not part of the package, there is no need for __init__.py files.
S101 assert Asserts should not be used in production environments, but are fine for tests.

And the following rules for the files in the dev directory:

Code Rule Rationale / Note
INP001 implicit-namespace-package Dev scripts are not part of the package, so there is no need for __init__.py files.
T201 print Dev scripts use print() for user-facing output, which is fine outside of library code.

Release

Important

Before the first release works, the repository has to be registered as a PyPI Trusted Publisher and a pypi GitHub environment has to exist. See the python-copier first-publication guide for that one-time setup — you only do it once per project.

Releases of dough are cut by pushing a vX.Y.Z tag to GitHub. The cd workflow under .github/workflows/cd.yaml then builds an sdist and wheel with Hatch and publishes them to PyPI.

  1. Bump the version and generate the changelog draft:

    hatch run bump <new-version>
    

    This runs hatch version to update src/dough/__about__.py, then runs dev/update_changelog.py to prepend a new section to CHANGELOG.md with commits sorted by type. Review the generated changelog, make any edits, and commit the bump on main (typically via a PR).

  2. Tag the bump commit and push the tag:

    git tag -a v<new-version> -m '🚀 Release v<new-version>'
    git push origin v<new-version>
    
  3. The cd.yaml workflow picks up the tag, builds the distributions, and publishes them to PyPI.

The git tag and the version in __about__.py must agree. PyPI only sees the version baked into the built distribution, so a mismatch will silently publish under the wrong version (or be rejected as a duplicate of an existing release), and re-tagging after the fact is awkward.

Commit messages

We use a leading emoji to indicate the type of change in each commit. The changelog script (dev/update_changelog.py) uses these emojis to automatically sort commits into the right sections. This means that the sorting in types happens at commit time, when the changes are still fresh in memory.

For the full specification and emoji table, see the commit message conventions.