Contributing Guide

This is the place to start as a new ESPEI contributor. This guide assumes you have installed a development version of ESPEI.

The next sections lay out the basics of getting an ESPEI development set up and the development standards. Then the Software design sections walk through the key parts of the codebase.

Tests

Even though much of ESPEI is devoted to being a multi-core, stochastic user tool, we strive to test all logic and functionality. We are continuously maintaining tests and writing tests for previously untested code. As a general rule, any time you write a new function or modify an existing function you should write or maintain a test for that function.

Some tips for testing:

  • Ideally you would practicing test driven development by writing tests of your intended results before you write the function.
  • If possible, keep the tests small and fast.
  • See the NumPy/SciPy testing guidelines for more tips.

Running Tests

ESPEI uses pytest as a test runner. The tests can be run from the root directory of the cloned repository:

pytest

Style

Code style

For most naming and style, follow PEP8. One exception to PEP8 is regarding the line length, which we suggest a 120 character maximum, but may be longer within reason.

Code documentation

ESPEI uses the NumPy documentation style. All functions and classes should be documented with at least a description, parameters, and return values, if applicable.

Using Examples in the documentation is especially encouraged for utilities that are likely to be run by users. See espei.analysis.truncate_arrays for an example.

Web documentation

Documentation on ESPEI is split into user tutorials, reference and developer documentation.

  • Tutorials are resources for users new to ESPEI or new to certain features of ESPEI to be guided through typical actions.
  • Reference pages should be concise articles that explain how to complete specific goals for users who know what they want to accomplish.
  • Developer documentation should describe what should be considered when contributing source code back to ESPEI.

The documentation lives in the docs/ directory of the repository and is built with Quarto. Tutorials and recipes are executed when the site is rendered, so their code is checked against the installed version of ESPEI on every build.

Building the documentation

  1. Install Quarto.
  2. Install ESPEI with the development dependencies from the root of the repository. Using uv, uv sync --dev creates a virtual environment with ESPEI, quartodoc and jupyter.
  3. From the docs/ directory, build the API reference and preview the site:
cd docs
uv run quartodoc build
uv run quarto preview

quartodoc build generates the API reference pages in reference/api/ and the site sidebar in _sidebar.yml from the quartodoc section of _quarto.yml. Rerun it after changing docstrings or the list of documented objects. quarto preview renders the site, opens it in a browser and re-renders pages as you edit them. Use quarto render for a one-off build into _site/.

A pre-render script (_scripts/pre_render.py) records the installed ESPEI version in _variables.yml, which the sidebar title and pages reference through {{< var version >}}. There is no version number to update by hand.

Fix any warnings that come up if you are adding documentation.

Data used by tutorials

The MCMC results plotted in the Cu-Mg tutorial and the MCMC recipes are stored as float32 compressed .npz archives (mcmc-results.npz) rather than the trace.npy and lnprob.npy files ESPEI writes, to keep the repository small. If a tutorial run is regenerated, convert the arrays with numpy.savez_compressed and replace the archive in place.

Release notes

CHANGES.md in the root of the repository is the single source for the release notes and is included in the Release Notes page. Add entries there as part of a pull request.

Deployment

The Docs GitHub Actions workflow renders the site on every push and pull request. Pushes to master are deployed to the dev/ directory of the gh-pages branch and published releases are deployed under their version number, e.g. 0.9.1/. The root of the site redirects to the latest release, and every page gets a version selector fed by switcher.json. The deployment step is docs/_scripts/deploy_version.py, which can also be run locally against a checkout of gh-pages.

Logging

Since ESPEI is intended to be run by users, we must provide useful feedback on how their runs are progressing. ESPEI uses the logging module to allow control over verbosity of the output.

There are 5 different logging levels provided by Python. They should be used as follows:

Critical or Error (logging.critical or logging.error)

Never use these. These log levels would only be used when there is an unrecoverable error that requires the run to be stopped. In that case, it is better to raise an appropriate error instead.

Warning (logging.warning)

Warnings are best used when we are able to recover from something bad that has happened. The warning should inform the user about potentially incorrect results or let them know about something they have the potential to fix. Again, anything unrecoverable should not be logged and should instead be raised with a good error message.

Info (logging.info)

Info logging should report on the progress of the program. Usually info should give feedback on milestones of a run or on actions that were taken as a result of a user setting. An example of a milestone is starting and finishing parameter generation. An example of an action taken as a result of a user setting is the logging of the number of chains in an mcmc run.

Debug (logging.debug)

Debugging is the lowest level of logging we provide in ESPEI. Debug messages should consist of possibly useful information that is beyond the user's direct control. Examples are the values of initial parameters, progress of checking datasets and building phase models, and the acceptance ratios of MCMC iterations.

Back to top