Skip to content

Developer Guide


This project requires Python and R. To simplify installation of the (indirect) R depencencies we recommend creating a conda environment using Mamba forge with:

# Clone the repo
git clone
cd springtime

# Create and activate environment
mamba env create --file environment.yml
conda activate springtime

# Install R requirements
Rscript -e 'devtools::install_github("bluegreen-labs/phenor", upgrade="never")'
Rscript -e 'devtools::install_github("ropensci/rppo", upgrade="never")'
Rscript -e 'install.packages(c("daymetr", "MODISTools", "phenocamr", "rnpn"), repos = "")'

If you already have a conda environment you can update the springtime dependencies with

mamba env update --file environment.yml --name <name of conda environment>

Development setup

This package is built with hatch.

# Create development environment for springtime
hatch env create

# Enter/activate development environment
hatch shell
springtime --help
exit  # get out/deactivate

# Alternatively, use hatch run to execute command in default env
hatch run springtime --help

Linting and formatting

We use ruff for linting and black for formatting. Mypy is used for type checking.

# Apply black automatic formatting to both src/ and tests/
hatch run black src tests

# See what ruff can do for you
hatch run ruff help

# Lint all files in src/ and tests/ with all linters
hatch run ruff check src tests

# Try to automatically fix issues
hatch run ruff check src tests --fix

# Run static type checking
hatch run mypy --install-types  # say yes
hatch run mypy --ignore-missing-imports src tests


In principle, we like to publish our code under a permissive Apache-2.0 license. However, some of our dependencies are released under different licenses. Therefore, we use multi-licensing where each file specifies its own licensing conditions. We follow the REUSE specification, where every file should have license information in its header or, if this is not possible, as a separate file.ext.license file. Notebooks are by default licensed under AGPL via the .reuse/dep5 file.

When adding new code, you should verify that it is appropriately licensed. For more info, see the REUSE FAQ. The reuse tool can be used for checking compliance with the REUSE specification.

# Check licenses
hatch run reuse lint

Hatch run quality-checks

For convenience, we configured hatch to perform all the checks above with a single command:

hatch run quality-checks


Pytest is used for running tests.

# Run all tests in tests/
hatch run pytest

# Run all tests from one file
hatch run pytest tests/

# Run a single test
hatch run pytest tests/

To test examples in docstrings use:

hatch run doctest <file to test>
# For example
hatch run doctest src/springtime/


Documentation is build with mkdocs

# Get help for mkdocs
hatch run mkdocs --help
hatch run mkdocs serve --help

# Start a development server with auto reloads
hatch run mkdocs serve

# Build the documentation for deployment
hatch run mkdocs build --clean --strict

Docker build

The docker image is hosted on GitHub Container Registry (GHCR).

You need to setup a personal access token following the instructions here.

Then build and push the image to GHCR:

# In the root of the repository
docker build -t .
docker push

Contributing guidelines

We welcome contributions from everyone. Please use our GitHub issue tracker for questions, ideas, bug reports, or feature requests.

If you want to make a pull request:

  1. discuss your idea first, before putting in a lot of effort
  2. refer to the developer documentation
  3. if needed, fork the repository to your own Github profile
  4. work on your own feature branch
  5. make sure the existing tests still work and add new tests (if necessary)
  6. update or expand the documentation;
  7. make sure your code follows the style guidelines
  8. don't be afraid to ask help with any of the above steps. We're happy to help!

By participating in this project, you agree to abide by the code of conduct.

Code of conduct

We as members, contributors, and leaders pledge to make participation in our community a harassment-free experience for everyone. We pledge to act and interact in ways that contribute to an open, welcoming, diverse, inclusive, and healthy community. For more information, see the contributor-covenant.