Development guidelines

This is intended to serve as a living document. If something looks out of date, please submit a PR to update it.

For topics or details not specified, refer to the development guidelines of the OpenFF Toolkit.

Supported Python versions

Generally, follow NEP 29. This means that currently Python 3.8-3.9 are supported as of the last update of this document (January 2022). No effort needs to be made to support older versions (Python 2 or 3.7 or earlier) or newer versions that are not well-supported by the PyData stack.

The last release with support for Python 3.7 wass v0.1.3.


Style is enforced with automated linters that run in CI. See .github/workflows/lint.yaml for the checks that take place, each of which can be run locally. Your favorite IDE probably includes good support for most of these linters.


  • black: Automated, deterministic, and consistent code formatting.

  • isort: Sorts imports.

  • flake8: Catches many iffy practices before they can grow into bugs. Check the action to see what plugins are used.

  • pyupgrade: Automatically update code for features and syntax of newer Python versions.


Type hints are optional but encouraged. Many optional flags are passed to mypy; check the action for a recommended invocation. Check setup.cfg for some configuration, mostly ignoring libraries that do not have support for type-checking.


The pre-commit tool can be used to automate some or all of the style checks. It automatically runs other programs (“hooks”) when you run git commit. It errors out and aborts the commit if any hooks fail.

Note that tests (too slow) and type-checking (weird reasons) are not run by pre-commit. You should still manually run tests before commiting code.

This project uses pre-commit ci, a free service that enforces style on GitHub using the pre-commit framework.

The configuration file (.pre-commit-config.yaml) is commited to the repo. This file speicies the configuration that bots will use and also any local installations. Note that because this file is checked out in the repo, all developers therefore use the same pre-commit hooks (as will the bots).

First, install pre-commit

$ mamba install pre-commit -c conda-forge


$ pip install pre-commit

Then, install the pre-commit hooks (note that it installs the linters into an isolated virtual environment, not the current conda environment):

$ pre-commit install
pre-commit installed at .git/hooks/pre-commit

Optionally update the hooks:

$ pre-commit autoupdate.
Updating ... already up to date.
Updating ... already up to date.
Updating ... already up to date.
Updating ... already up to date.
Updating ... already up to date.
Updating ... already up to date.
Updating ... already up to date.
Updating ... already up to date.
Updating ... already up to date.
Updating ... updating 2.1.6 -> 3.0.0.
Updating ... already up to date.
Updating ... already up to date.

Hooks will now run automatically before commits. Once installed, it should run in a few seconds.

If hooks are installed locally, all linting checks in CI should pass. If hooks are not installed locally or are significatnly out of date, a bot may commit directly to a PR to make these fixes.


Interchange is documented with Sphinx and hosted by ReadTheDocs at The documentation is built and served by ReadTheDocs automatically for every pull request — please check that your changes are documented appropriately!

Interchange uses Autosummary to automatically document the entire public API from the code’s docstrings. Docstrings should be written according to the NumPy docstring convention. By default, all modules and members except those beginning with an underscore are included in the API reference. Additional modules such as tests can be excluded from the reference by listing them in the autosummary_context["exclude_modules"] variable in docs/

This is implemented by including a :recursive: Autosummary directive in docs/ and a customised module template docs/_templates/autosummary/module.rst. This template produces neatly segmented, complete documentation with a coherent navigation structure.

The remaining parts of the documentation are written in MyST Markdown.

Building the docs locally

Dependencies for building the documentation can be found in docs/environment.yml. This is the Conda environment used by ReadTheDocs to build the docs. To build the docs locally, first create the environment, then invoke Sphinx via the makefile:

# Create the environment
mamba env create --file devtools/conda-envs/docs_env.yaml
# Prepare the current shell session
mamba activate interchange-docs
cd docs
# Build the docs
make html