Contributing to GerryChain¶
Thanks for your interest in contributing to GerryChain! Contributions of all sizes are welcome, including bug reports, documentation improvements, tests, examples, and new features.
If you are planning anything larger than a small bug fix or documentation change, please contact
code@mggg.org before you start coding. The maintainers can help you align the work with the
current roadmap and target branch.
Ways to contribute¶
Report bugs or confusing behavior.
Improve or expand documentation and tutorials.
Add tests for uncovered behavior or regressions.
Fix bugs, performance problems, or edge cases.
Propose or implement new proposals, constraints, updaters, metrics, or graph features.
Please search the issue tracker before opening a new issue. A useful bug report explains what you did, what you expected, what happened instead, and includes a minimal example when possible.
Development setup¶
GerryChain uses:
uv for Python and dependency management
Make for common development commands
Ruff for formatting and linting
pytest for tests
pre-commit for local quality checks
Recommended setup:
Install
uv.Fork and clone the repository.
From the repository root, run
make setup.
make setup installs a managed Python 3.11 environment, syncs every dependency group, and
installs the pre-commit hooks.
If you already have uv installed and prefer to run the steps directly, the equivalent setup is:
uv python install 3.11
UV_MANAGED_PYTHON=1 uv sync --python 3.11 --all-groups
uv run pre-commit install
Contributor workflow¶
Fork the repository and clone your fork locally.
Create a descriptive branch from the current target branch.
Keep the change focused. Do not bundle unrelated refactors into the same pull request.
Add or update tests for behavior changes.
Update public documentation when behavior or APIs change.
Run the relevant checks locally.
Open a pull request that explains the problem, your approach, and how you tested it.
If you are unsure which branch to target, ask the maintainers before opening the pull request.
Branch naming¶
Use descriptive branch names such as:
fix/recom-region-reselectionfeat/add-compactness-updaterdocs/update-contributing-guide
Running checks locally¶
The preferred Make targets are:
make format
make lint
make type-check
make test
make test-all
make precommit
make lint runs Ruff and both type checkers, so a separate make type-check is only needed when
you want to run the type checkers by themselves. make test-all includes tests marked as slow.
To run a specific test file through Make:
make test TEST_PATHS=tests/test_tree.py
You can also pass pytest options directly:
uv run pytest tests/test_tree.py -k bipartition
uv run pytest tests --runslow
uv run pytest tests --cov=gerrychain --cov-report=term-missing
Before opening a pull request, also verify that the lockfile is current:
uv lock --check
Pull request expectations¶
Before opening a pull request, make sure that:
the change is scoped to a single topic;
code, tests, and docs are updated together when needed;
new behavior and regressions are covered by tests;
formatting, linting, and type checks pass locally;
slow tests relevant to the change pass; and
the description explains the user-facing impact and notable tradeoffs.
Small, focused pull requests are much easier to review and merge than large mixed changes.
Code style guidelines¶
GerryChain requires Python 3.11 or later. Follow the current conventions below and avoid style-only churn in files unrelated to your change.
Follow the repository tooling first. Ruff defines formatting and baseline lint rules.
Keep lines at or below 100 characters.
Add type annotations for function parameters and return values.
Prefer modern type syntax, such as
str | Noneinstead ofOptional[str].Match the import style and structure of the surrounding module.
Use descriptive
snake_casenames for variables and functions,PascalCasefor classes, andUPPER_SNAKE_CASEfor module-level constants.Keep functions focused and put validation or obvious guard clauses near the top.
Prefer straightforward control flow and targeted helpers over unnecessary abstraction.
Preserve useful docstrings and comments when editing older code.
Use comments sparingly and reserve them for invariants, non-obvious reasoning, or domain context.
Docstrings¶
Public classes, functions, and methods should use the repository’s Google-style docstrings. Keep docstrings at or below 100 characters per line and document contracts, defaults, and failure modes.
def population_deviation(population: int, ideal: int) -> float:
"""Return a district's relative population deviation from the ideal.
Args:
population (int): District population.
ideal (int): Ideal district population.
Returns:
float: Relative deviation from the ideal population.
Raises:
ValueError: If the ideal population is not positive.
"""
if ideal <= 0:
raise ValueError("ideal must be positive")
return (population - ideal) / ideal
Use Args, Returns, and Raises when they add information. Add examples when they clarify
non-obvious behavior, not simply to repeat the signature.
Testing guidelines¶
Tests are required for behavior changes.
Add tests under
tests/near the existing tests for the same module or feature.Cover successful behavior, expected failures, and natural edge cases.
When checking exceptions, verify useful error text with
pytest.raises(..., match=...).Mark tests that take longer than about ten seconds with
@pytest.mark.slow.Pass an explicit seed or
random.Randominstance in tests involving randomness.Do not rely on
PYTHONHASHSEEDor unordered container iteration for reproducibility.When changing shared graph behavior, exercise both NetworkX and RustworkX backends when relevant.
The test suite enables GerryChain’s runtime integrity checks automatically. Production code should not assume that those optional checks are enabled.
Documentation guidelines¶
If your change affects public behavior, update the relevant documentation with the code. This may include:
docstrings under
gerrychain/;narrative Markdown under
docs/;tutorial notebooks under
docs/user/;API reference pages under
docs/api/; orexamples and links in
README.md.
Notebook-first workflow¶
Tutorial notebooks under docs/user/ are the source of truth. Commit them without outputs so
reviews contain only source changes. The pre-commit hook clears outputs and execution counts from
changed notebooks automatically.
The docs build reuses outputs when the notebook source matches the ignored MyST-NB cache under
docs/_build/. New or changed notebooks execute in temporary directories with the example
datasets staged. To populate that cache for one notebook without building the site, run:
make docs-cache-notebooks NOTEBOOKS=docs/user/recom.ipynb
Omit NOTEBOOKS to execute every tutorial:
make docs-cache-notebooks
Building and previewing docs¶
Build the complete site with warnings treated as errors:
make docs
The generated site is written to docs/_build/. To serve it locally with automatic rebuilding:
make docs-serve
To force notebook re-execution before a build or preview, set FRESH=1. This also works with
docs and docs-cache-notebooks:
make docs-serve FRESH=1
Testing docs¶
Execute Python snippets from Markdown, RST, and README.md:
make docs-test
Blocks that cannot run independently must provide a reason:
<!-- docs-test: skip -- fragment; objects are defined earlier in the tutorial -->
Shared setup blocks use:
<!-- docs-test: setup -->
A page whose blocks are all illustrative fragments can opt out wholesale, with the marker placed just under the title:
<!-- docs-test: skip-page -- placeholder names and signature-only stubs -->
Snippet failures report the original documentation filename and line number. The docs build fails if a notebook cannot execute, and the test suite rejects notebooks containing committed outputs.
Check external links manually with:
make docs-linkcheck
Pull requests and pushes to main execute the notebooks, build the site, run snippet checks, and
upload the built site as a workflow artifact. Read the Docs publishes the site. External link
checking is temporarily manual while the reorganized pages are unpublished.
Documentation dependencies are split into docs for building and serving the site and
docs-exec for executing notebooks and snippets. The Make targets select the appropriate group.
Community guidelines¶
This project follows the Contributor Covenant Code of Conduct. By participating, you agree to follow the expectations in the Code of Conduct.
Questions¶
If anything in the contribution process is unclear, contact code@mggg.org. Thanks for helping
make GerryChain better!