Contributing¶
Setup¶
Optional with uv:
Running tests¶
# Fast offline tests (~4 seconds)
pytest tests/ -m "not slow"
# All tests including network (hits NVE/Høydedata APIs)
pytest tests/
# Single test
pytest tests/test_retrogression.py::TestRetrogressionOffline::test_run_retrogression_basic
Code quality¶
Conventions¶
- Python ≥ 3.12 with modern type annotations (
list[...],X | None) - Google-style docstrings for all public functions
- Trailing commas in function signatures (ruff format handles expansion)
- Logging instead of
print()— uselogger = logging.getLogger(__name__) - CRS: Always EPSG:25833
- Bounds order: All modules use standard GIS
(xmin, ymin, xmax, ymax).
Project structure¶
src/losneomrade/
├── config.py # Settings dataclass
├── hoydedata.py # DEM fetching from Høydedata.no
├── masks.py # MSML/AR5 mask fetching from NVE
├── retrogression.py # Step-wise retrogression
├── terrain_criteria.py # Pixel-based slope verification
├── profile_retrogression.py # Profile-based retrogression
├── utils.py # Shared utilities
└── types.py # Type aliases
Commit messages¶
Use Conventional Commits from this release line onward:
feat:for user-facing featuresfix:for bug fixesdocs:for documentation-only changesrefactor:for internal code restructuring without behavior changetest:for test-only changesci:for workflow/automation changeschore:for maintenance tasks
Mark breaking changes with either:
feat!: ...- or a
BREAKING CHANGE:footer in the commit body
Examples:
feat: add release workflow for version tags
fix: preserve mask clipping in retrogression output
feat!: normalize bounds to standard GIS order
Versioning¶
This project now follows Semantic Versioning:
- patch for backwards-compatible fixes
- minor for backwards-compatible features
- major for breaking API changes
The pre-modernization baseline is v1.1.3. The current breaking-change
upgrade line is intended to become v2.0.0.
Architecture decisions¶
- Masks are external: The package doesn't fetch masks automatically.
Users call
masks.get_msml_mask()and pass the result to the analysis functions. - DEM fetching is optional: All functions accept
custom_rasterto work offline. - Config is a singleton:
from losneomrade.config import settingsgives you the global instance.