Skip to content

New release for PyPI #586

@monocongo

Description

@monocongo

Release Plan: climate_indices v2.3.0

Date: December 31, 2025
Status: Draft
Target Version: 2.3.0


1. Release Summary

This release introduces multi-dimensional xarray support for the SPI accessor, enabling users to compute climate indices directly on gridded NetCDF datasets without manual reshaping.

Key Changes

  • Priority 1 Complete: Refactored accessors.py to support N-dimensional DataArrays (time, lat, lon)
  • Accessor now delegates to spi_xarray() with dask='parallelized' for multi-dimensional data
  • Added time dimension auto-detection and Dask chunk validation
  • CF-compliant metadata attributes on output DataArrays
  • Updated quickstart notebook to demonstrate new accessor capabilities

Files Changed

  • src/climate_indices/accessors.py - Major refactor
  • tests/test_accessors.py - New tests for 2D/3D support
  • notebooks/00_quickstart_indices_demo.ipynb - Updated examples

2. Pre-Release Checklist

2.1 Code Quality Verification

# Run full test suite
uv run pytest tests/ -v

# Run linting
ruff check --fix src/
ruff format src/

# Run pre-commit hooks
uv run pre-commit run --all-files

2.2 Version Bump

Update version in pyproject.toml:

# Before
version = '2.2.0'

# After
version = '2.3.0'

Note: The version is read dynamically in __init__.py via importlib.metadata, so only pyproject.toml needs updating.

2.3 Changelog Update

Create or update CHANGELOG.md with:

## [2.3.0] - 2025-12-31

### Added
- Multi-dimensional xarray support for SPI accessor (#XXX)
  - `da.indices.spi()` now works with 2D/3D DataArrays (time, lat, lon)
  - Automatic Dask parallelization via `xr.apply_ufunc`
  - Time dimension auto-detection (supports `time`, `t`, `Time`, etc.)
  - CF-compliant output attributes (`standard_name`, `long_name`, `units`, `valid_min`, `valid_max`)

### Changed
- Accessor validates that time dimension is not chunked across multiple pieces
- Output dimension order preserved to match input

### Fixed
- N/A

2.4 Documentation Review

  • README.md updated with new accessor examples
  • Docstrings complete and accurate
  • Notebook runs without errors

3. Release Process

3.1 Merge to Master

# Ensure on feature branch with all changes
git checkout boy_scouting

# Rebase on latest master
git fetch origin
git rebase origin/master

# Run final verification
uv run pytest tests/ -v
ruff check src/

# Push branch and create PR
git push origin boy_scouting
gh pr create --title "feat: Multi-dimensional xarray support for SPI accessor" \
  --body "Implements Priority 1 from the upgrade plan..."

After PR review and approval:

# Merge PR (prefer squash merge for clean history)
gh pr merge --squash

3.2 Create Git Tag

# Fetch latest master
git checkout master
git pull origin master

# Create annotated tag
git tag -a v2.3.0 -m "Release v2.3.0: Multi-dimensional xarray support for SPI accessor"

# Verify tag
git show v2.3.0

3.3 Push Tag to GitHub

# Push the tag (this triggers the release workflow)
git push origin v2.3.0

3.4 Create GitHub Release

Option A: Via GitHub CLI

gh release create v2.3.0 \
  --title "v2.3.0: Multi-dimensional xarray support" \
  --notes "## What's New

### Multi-dimensional xarray support for SPI accessor

The \`.indices.spi()\` accessor now works directly on N-dimensional DataArrays:

\`\`\`python
import xarray as xr
from climate_indices.compute import Periodicity

# Load a 3-D precipitation dataset
ds = xr.open_dataset('precip.nc', chunks={'time': -1})

# Compute SPI directly on the grid - no manual reshaping needed!
spi = ds.precip.indices.spi(
    scale=6,
    distribution='gamma',
    data_start_year=1981,
    calibration_year_initial=1981,
    calibration_year_final=2010,
    periodicity=Periodicity.monthly
)
\`\`\`

### Key Features
- Automatic Dask parallelization for large datasets
- Time dimension auto-detection
- CF-compliant output metadata
- Dimension order preservation

See the [full changelog](CHANGELOG.md) for details.
"

Option B: Via GitHub Web UI

  1. Navigate to https://github.com/monocongo/climate_indices/releases
  2. Click "Draft a new release"
  3. Select tag v2.3.0
  4. Title: v2.3.0: Multi-dimensional xarray support
  5. Add release notes
  6. Click "Publish release"

4. PyPI Publication

4.1 Automated Release (Recommended)

The repository has a GitHub Actions workflow (.github/workflows/release.yml) that automatically:

  1. Triggers on push of v* tags
  2. Runs tests across Python 3.10, 3.11, 3.12, 3.13
  3. Builds the package using python -m build
  4. Validates with twine check
  5. Publishes to PyPI using trusted publishing

Requirements:

  • GitHub environment release must be configured with:
    • Protection rules (optional: required reviewers)
    • PyPI trusted publisher configured for the repository

4.2 PyPI Trusted Publishing Setup

If not already configured, set up trusted publishing on PyPI:

  1. Go to https://pypi.org/manage/project/climate-indices/settings/publishing/
  2. Add a new publisher:
    • Owner: monocongo
    • Repository: climate_indices
    • Workflow name: release.yml
    • Environment name: release

4.3 Monitor Release

After pushing the tag:

# Watch the workflow
gh run watch

# Or view in browser
gh run view --web

The workflow will:

  1. Run tests (must pass on all Python versions)
  2. Wait for environment approval (if configured)
  3. Build and publish to PyPI

4.4 Manual Release (Fallback)

If automated release fails:

# Build the package
uv build

# Check the build
twine check dist/*

# Upload to PyPI (requires API token)
twine upload dist/*

5. Post-Release Verification

5.1 Verify PyPI Package

# Wait a few minutes for PyPI to index the new version
pip index versions climate-indices

# Test installation in a fresh environment
python -m venv /tmp/test-release
source /tmp/test-release/bin/activate
pip install climate-indices==2.3.0

# Verify version
python -c "import climate_indices; print(climate_indices.__version__)"

5.2 Test Multi-dimensional Support

import numpy as np
import xarray as xr
from climate_indices.compute import Periodicity

# Create test data
precip = xr.DataArray(
    np.random.rand(24, 3, 4) * 50,
    dims=('time', 'lat', 'lon'),
    coords={
        'time': np.arange(24),
        'lat': [30, 35, 40],
        'lon': [-100, -95, -90, -85]
    }
)

# Test accessor on 3-D data
spi = precip.indices.spi(
    scale=3,
    distribution='gamma',
    data_start_year=2000,
    calibration_year_initial=2000,
    calibration_year_final=2001,
    periodicity=Periodicity.monthly
)

print(f"Input shape: {precip.shape}")
print(f"Output shape: {spi.shape}")
assert spi.shape == precip.shape
print("Success!")

5.3 Announce Release

  • Update GitHub Discussions/Announcements
  • Post to relevant mailing lists/forums
  • Update any external documentation

6. Rollback Plan

If critical issues are discovered post-release:

6.1 Yank from PyPI

# Yank the release (prevents new installs but doesn't delete)
# Must be done via PyPI web interface:
# https://pypi.org/manage/project/climate-indices/releases/

6.2 Create Patch Release

# Fix the issue on master
git checkout master
git checkout -b hotfix/v2.3.1

# Make fixes, update version to 2.3.1
# ... edit pyproject.toml ...

# Merge and tag
git checkout master
git merge hotfix/v2.3.1
git tag -a v2.3.1 -m "Hotfix release v2.3.1"
git push origin master --tags

7. Timeline

Step Owner ETA
Final testing Developer Day 0
Version bump + changelog Developer Day 0
PR review Maintainer Day 0-1
Merge to master Maintainer Day 1
Create tag + release Maintainer Day 1
PyPI publication Automated Day 1
Post-release verification Developer Day 1

8. Quick Reference Commands

# Full release sequence (after PR merged)
git checkout master && git pull origin master
git tag -a v2.3.0 -m "Release v2.3.0: Multi-dimensional xarray support for SPI accessor"
git push origin v2.3.0

# Monitor release workflow
gh run watch

# Verify on PyPI
pip install climate-indices==2.3.0 --upgrade
python -c "import climate_indices; print(climate_indices.__version__)"

Metadata

Metadata

Assignees

Labels

No labels
No labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions