Goal
pip install climate-api installs a working Climate API instance. The package name is available on PyPI (confirmed available as of May 2026).
Versioning
Use PEP 440 pre-release identifiers throughout the alpha phase:
| Stage |
Version examples |
pip install behaviour |
| Active alpha |
0.1.0a1, 0.1.0a2 |
Skipped unless --pre or an explicit pin |
| Wider testing |
0.1.0b1, 0.1.0rc1 |
Same — opt-in only |
| First stable |
0.1.0 |
Installed by default |
| API-stable |
1.0.0 |
Signals no more breaking changes |
The 0.x prefix communicates instability per SemVer; the aN suffix keeps pre-releases invisible to users not explicitly opting in. Tag convention: v0.1.0a1 → 0.1.0a1 on PyPI.
Blocker: git-sourced dependencies
PyPI rejects packages that declare git+https:// URLs anywhere in their metadata. Two runtime dependencies are currently pinned this way:
"dhis2eo @ git+https://github.com/dhis2/dhis2eo.git@v1.2.0"
"dhis2-client @ git+https://github.com/dhis2/dhis2-python-client.git@V0.3.0"
Neither package is on PyPI yet.
Resolution
Both packages are loaded lazily — dhis2eo only via _get_dynamic_function() at download time, dhis2-client only in shared/dhis2_adapter.py for DHIS2 org unit lookups. The core API (serving, STAC, OGC API) works without them.
Steps to unblock the PyPI release:
- Remove
dhis2eo and dhis2-client from dependencies in pyproject.toml — core API remains fully functional.
- Add lazy-import guards in
downloader.py and dhis2_adapter.py that raise a clear ImportError with install instructions if those packages are missing at call time.
- Document the manual install for download provider support in the README:
pip install "dhis2eo @ git+https://github.com/dhis2/dhis2eo.git@v1.2.0"
pip install "dhis2-client @ git+https://github.com/dhis2/dhis2-python-client.git@V0.3.0"
- Long-term: coordinate with the owners of those repos to publish them to PyPI, then add them back as proper
dependencies.
Steps to first PyPI release
1. Resolve the git-sourced dependencies (see above)
2. Bundle the built-in dataset YAMLs as package data
Already done in PR #59: data/datasets/ moved to src/climate_api/data/datasets/ and loaded via importlib.resources.
3. Bundle the pygeoapi base config
Already done in PR #59: config/pygeoapi/base.yml moved to src/climate_api/data/pygeoapi/base.yml and loaded via importlib.resources.
4. Complete package metadata
Add to pyproject.toml:
[project]
license = { text = "BSD-2-Clause" }
authors = [{ name = "DHIS2", email = "post@dhis2.org" }]
readme = "README.md"
keywords = ["dhis2", "climate", "zarr", "stac", "geospatial"]
classifiers = [
"Development Status :: 3 - Alpha",
"Programming Language :: Python :: 3",
"Intended Audience :: Science/Research",
"Topic :: Scientific/Engineering :: GIS",
]
[project.urls]
Repository = "https://github.com/dhis2/climate-api"
Documentation = "https://github.com/dhis2/climate-api/tree/main/docs"
5. Publish workflow
Add a GitHub Actions workflow that builds and publishes to PyPI on tagged releases using Trusted Publishing (no API token needed):
# .github/workflows/publish.yml
on:
push:
tags: ["v*"]
jobs:
publish:
runs-on: ubuntu-latest
environment: pypi
permissions:
id-token: write
steps:
- uses: actions/checkout@v4
- uses: astral-sh/setup-uv@v5
- run: uv build
- uses: pypa/gh-action-pypi-publish@release/v1
Configure the pypi environment in repo settings and register the project on PyPI under Trusted Publishing.
6. Verify install in a clean environment
uv venv /tmp/test-install && source /tmp/test-install/bin/activate
pip install .
climate-api # should start the server
Out of scope
Goal
pip install climate-apiinstalls a working Climate API instance. The package name is available on PyPI (confirmed available as of May 2026).Versioning
Use PEP 440 pre-release identifiers throughout the alpha phase:
pip installbehaviour0.1.0a1,0.1.0a2--preor an explicit pin0.1.0b1,0.1.0rc10.1.01.0.0The
0.xprefix communicates instability per SemVer; theaNsuffix keeps pre-releases invisible to users not explicitly opting in. Tag convention:v0.1.0a1→0.1.0a1on PyPI.Blocker: git-sourced dependencies
PyPI rejects packages that declare
git+https://URLs anywhere in their metadata. Two runtime dependencies are currently pinned this way:Neither package is on PyPI yet.
Resolution
Both packages are loaded lazily —
dhis2eoonly via_get_dynamic_function()at download time,dhis2-clientonly inshared/dhis2_adapter.pyfor DHIS2 org unit lookups. The core API (serving, STAC, OGC API) works without them.Steps to unblock the PyPI release:
dhis2eoanddhis2-clientfromdependenciesinpyproject.toml— core API remains fully functional.downloader.pyanddhis2_adapter.pythat raise a clearImportErrorwith install instructions if those packages are missing at call time.dependencies.Steps to first PyPI release
1. Resolve the git-sourced dependencies (see above)
2. Bundle the built-in dataset YAMLs as package data
Already done in PR #59:
data/datasets/moved tosrc/climate_api/data/datasets/and loaded viaimportlib.resources.3. Bundle the pygeoapi base config
Already done in PR #59:
config/pygeoapi/base.ymlmoved tosrc/climate_api/data/pygeoapi/base.ymland loaded viaimportlib.resources.4. Complete package metadata
Add to
pyproject.toml:5. Publish workflow
Add a GitHub Actions workflow that builds and publishes to PyPI on tagged releases using Trusted Publishing (no API token needed):
Configure the
pypienvironment in repo settings and register the project on PyPI under Trusted Publishing.6. Verify install in a clean environment
Out of scope
downloads/,pygeoapi/) — already handled via XDG paths andCACHE_OVERRIDE(PR Installable package foundation, Python client, and User-facing docs #59).climate-api.yamlinstance config — installed users create their own (PR Installable package foundation, Python client, and User-facing docs #59 renamed toclimate-api.yaml.example).