Contributing Guide#
Source Files
pyproject.toml.pre-commit-config.yaml.github/workflows/check_pullrequest.yaml
This guide covers how to set up a development environment, the project structure, code style conventions, and contribution workflow for Twiga.
Development Setup#
Prerequisites#
Python 3.12 (required:
>=3.12,<3.13)uv - fast Python package manager
Git with pre-commit hook support
Installation#
# Clone the repository
git clone https://github.com/your-org/twiga-forecast.git
cd twiga-forecast
# Install all development dependencies
uv sync --all-extras --dev
# Install pre-commit hooks
uv run pre-commit install --hook-type commit-msg --hook-type pre-commit --hook-type pre-push
This installs all optional dependency groups needed for development: PyTorch, gradient boosting libraries, plotting backends, dev tools, and test frameworks.
Optional: GPU Support#
The default uv sync --all-extras installs the CPU-only PyTorch wheel. To replace it with a CUDA build you must use uv pip install --reinstall — plain pip install targets the system Python, not the uv-managed .venv, and uv pip install without --reinstall skips packages that already satisfy the version constraint.
# 1. Sync everything (installs CPU torch into .venv)
uv sync --all-extras --dev
# 2. Force-reinstall torch from the CUDA index into the same .venv
# --index-strategy unsafe-best-match lets uv fall back to PyPI for packages
# like torchmetrics and numpy whose CUDA-index builds are outdated.
uv pip install --reinstall torch \
--index-url https://download.pytorch.org/whl/cu124 \
--index-strategy unsafe-best-match
Note:
uv syncwill revert torch to the CPU wheel fromuv.lock. Re-run step 2 after anyuv sync.
Check your CUDA version with nvidia-smi. Common suffixes:
CUDA |
Suffix |
|---|---|
11.8 |
|
12.1 |
|
12.4 |
|
12.6 |
|
Verify the GPU build was installed:
import torch
print(torch.cuda.is_available()) # True
print(torch.cuda.get_device_name()) # e.g. NVIDIA A100
The pytorch-cu124 index is registered in pyproject.toml under [tool.uv.index] with explicit = true, so uv will not automatically pull from it — you must request it explicitly as shown above.
Project Structure#
twiga-forecast/
├── twiga/ # Main package
│ ├── __init__.py
│ ├── core/ # Core infrastructure
│ │ ├── config/ # Pydantic configuration models
│ │ ├── data/ # Data pipeline & feature engineering
│ │ ├── metrics/ # Evaluation metrics (point, interval, probabilistic)
│ │ ├── plot/ # Visualization utilities
│ │ ├── stats/ # Statistical analysis
│ │ └── backtester.py # Time-based cross-validation
│ ├── distributions/ # Probabilistic distributions
│ │ ├── conformal/ # Conformal prediction methods
│ │ ├── ml/ # ML distribution utilities
│ │ └── nn/ # NN distribution heads (Gaussian, Quantile)
│ ├── forecaster/ # Forecaster orchestration
│ │ ├── abstract.py # Abstract forecaster interface
│ │ ├── base.py # Base forecaster with CV
│ │ ├── core.py # TwigaForecaster (main entry point)
│ │ ├── ensemble.py # Ensemble strategies
│ │ └── registry.py # Model registry
│ ├── models/ # Model implementations
│ │ ├── ml/ # Machine learning models
│ │ │ ├── core/ # BaseRegressor
│ │ │ ├── prob/ # BaseQuantileRegressor
│ │ │ ├── catboost_model.py
│ │ │ ├── xgboost_model.py
│ │ │ ├── lightgbm_model.py
│ │ │ └── ...
│ │ └── nn/ # Neural network models
│ │ ├── core/ # BaseNeuralForecast, BaseNeuralModel, BaseArchitecture
│ │ ├── mlpf_model.py
│ │ ├── mlpgam_model.py
│ │ ├── nhits_model.py
│ │ └── ...
│ └── utils/ # Shared utilities
├── tests/ # Test suite
│ └── unit/ # Unit tests (mirrors source structure)
├── examples/ # Example notebooks and scripts
├── docs/ # Documentation (MkDocs)
├── pyproject.toml # Project configuration
├── .pre-commit-config.yaml # Pre-commit hooks
└── .github/workflows/ # CI/CD pipelines
Code Style#
Ruff (Linter & Formatter)#
Twiga uses Ruff for both linting and formatting:
Setting |
Value |
|---|---|
Target version |
Python 3.11 |
Line length |
120 characters |
Docstring convention |
Google style |
Import sorting |
isort-compatible ( |
Enabled rule sets: B (bugbear), C4 (comprehensions), D (docstrings), E/F/W (pycodestyle/pyflakes), UP (pyupgrade), I (isort), TID (tidy imports), N (naming), PGH (pygrep), PTH (pathlib), Q (quotes), S (bandit security), SIM (simplify), TRY (tryceratops), YTT (year 2020)
Run manually:
# Check for issues
uv run ruff check .
# Auto-fix issues
uv run ruff check . --fix
# Check formatting
uv run ruff format --check .
# Apply formatting
uv run ruff format .
ty (Type Checking)#
Twiga uses ty - Astral’s fast Python type checker - instead of mypy.
uv run ty check twiga
Setting |
Value |
|---|---|
Python version |
3.12 |
Scope |
|
Configuration |
|
Docstring Coverage (Interrogate)#
Interrogate checks docstring coverage with a minimum threshold of 25%:
uv run interrogate twiga/ --fail-under=25
Pre-Commit Hooks#
All hooks are defined in .pre-commit-config.yaml and run automatically on commit/push:
Hook |
Stage |
Description |
|---|---|---|
commitizen |
|
Validates commit message format (conventional commits) |
uv-lock |
|
Ensures |
check-yaml |
|
Validates YAML syntax |
check-added-large-files |
|
Blocks files > 1200 KB |
check-merge-conflict |
|
Detects unresolved merge markers |
check-json |
|
Validates JSON syntax |
check-toml |
|
Validates TOML syntax |
detect-private-key |
|
Prevents accidental key commits |
end-of-file-fixer |
|
Ensures files end with newline |
trailing-whitespace |
|
Removes trailing whitespace |
codespell |
|
Spell-checks code and comments |
ruff-check |
|
Linting with auto-fix |
ruff-format |
|
Code formatting |
nb-clean |
|
Strips notebook metadata from |
interrogate |
|
Docstring coverage check (≥25%) |
commitizen-branch |
|
Validates branch naming conventions |
Install Hooks#
uv run pre-commit install --hook-type commit-msg --hook-type pre-commit --hook-type pre-push
Run All Hooks Manually#
uv run pre-commit run --all-files
Commit Conventions#
Twiga uses Commitizen for standardized commit messages following the Conventional Commits specification.
Format#
<type>(<scope>): <subject>
<body>
<footer>
Common Types#
Type |
Description |
|---|---|
|
New feature |
|
Bug fix |
|
Documentation changes |
|
Code refactoring (no feature/fix) |
|
Adding or updating tests |
|
CI/CD configuration |
|
Maintenance tasks |
|
Version bump (auto-generated) |
Examples#
git commit -m "feat(models): add GANF neural network model"
git commit -m "fix(conformal): correct signed residual calculation"
git commit -m "docs(api): update forecaster method signatures"
Branch Naming#
Branches must match one of the allowed patterns (enforced by commitizen on push):
Pattern |
Purpose |
|---|---|
|
New features |
|
Bug fixes |
|
Documentation updates |
|
Release preparation |
Adding a New Model#
See Creating Custom Models for a step-by-step guide. The key points:
Create the model file at
twiga/models/{domain}/{name}_model.pyDefine a config class extending
BaseModelConfigorNeuralModelConfigImplement the model extending
BaseRegressor(ML) orBaseNeuralModel(NN)Add tests in
tests/unit/models/{domain}/The model registry auto-discovers models by naming convention
Documentation#
Documentation is built with MkDocs Material and uses mkdocstrings for API reference generation.
Build Locally#
# Install docs dependencies
uv sync --extra docs
# Serve with live reload
uv run mkdocs serve
# Build static site
uv run mkdocs build
Writing Docs#
Place new pages in the appropriate
docs/subdirectoryUse MkDocs Material admonitions (
!!! note,!!! tip,!!! warning)Use Mermaid diagrams for architecture and flow visualizations
Use
:::directives for auto-generated API docs from docstrings:
```{eval-rst}
.. autoclass:: twiga.core.config.DataPipelineConfig
:members:
:show-inheritance:
- Cross-link between pages using relative markdown links:
```markdown
See [TwigaForecaster](../core/forecaster.md) for details.