Metadata-Version: 2.5
Name: eb-contracts
Version: 0.2.3
Summary: Electric Barometer data contracts and validation utilities.
Project-URL: Homepage, https://github.com/Economistician/eb-contracts
Project-URL: Repository, https://github.com/Economistician/eb-contracts
Project-URL: Issues, https://github.com/Economistician/eb-contracts/issues
Author-email: "Kyle Corrie (Economistician)" <kcorrie@economistician.com>
License: BSD-3-Clause
License-File: LICENSE
Keywords: data-contracts,electric-barometer,forecasting,validation
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Science/Research
Classifier: License :: OSI Approved :: BSD License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Requires-Python: >=3.11
Requires-Dist: pandas>=2.0
Provides-Extra: all
Requires-Dist: mkdocs-material>=9.5; extra == 'all'
Requires-Dist: mkdocs>=1.6; extra == 'all'
Requires-Dist: pre-commit>=3.7; extra == 'all'
Requires-Dist: pyright>=1.1.380; extra == 'all'
Requires-Dist: pytest>=8; extra == 'all'
Requires-Dist: ruff>=0.6; extra == 'all'
Provides-Extra: dev
Requires-Dist: pre-commit>=3.7; extra == 'dev'
Requires-Dist: pyright>=1.1.380; extra == 'dev'
Requires-Dist: pytest>=8; extra == 'dev'
Requires-Dist: ruff>=0.6; extra == 'dev'
Provides-Extra: docs
Requires-Dist: mkdocs-material>=9.5; extra == 'docs'
Requires-Dist: mkdocs>=1.6; extra == 'docs'
Provides-Extra: test
Requires-Dist: pytest>=8; extra == 'test'
Description-Content-Type: text/markdown

# Electric Barometer · Contracts (`eb-contracts`)

![License: BSD-3-Clause](https://img.shields.io/badge/License-BSD_3--Clause-blue.svg)

Data contract and validation layer for the Electric Barometer ecosystem, defining canonical schemas, semantics, and enforcement for forecasts, costs, results, and run context.

---

## Overview

`eb-contracts` defines versioned schemas and validators for demand panels, forecasts, costs, and run context. It enforces shared structure and semantics; it does not compute metrics or train models.

---

## Installation

`eb-contracts` is distributed as a standard Python package.

```bash
pip install eb-contracts
```

---

## Core Concepts

- **Canonical data contracts** — Core data artifacts (forecasts, cost specifications, results, and context) are represented using explicit, versioned schemas rather than implicit conventions or ad-hoc DataFrame shapes.

- **Semantic consistency** — Column names, units, grain, and meaning are standardized and enforced so that downstream systems can rely on shared interpretation rather than contextual knowledge or undocumented assumptions.

- **Validation as a boundary** — Contract validation establishes a clear boundary between “valid” and “invalid” data, preventing silent failures and making structural issues visible at ingestion time rather than during downstream computation.

- **Versioned evolution** — Contracts are versioned to allow schemas and semantics to evolve over time without breaking existing consumers, enabling forward progress while preserving backward compatibility.

- **Explicit migration** — Adaptation from external or legacy data formats into contract-compliant artifacts is performed through explicit migration utilities, avoiding implicit coercion or guesswork.

- **Separation of structure from logic** — Data shape and meaning are defined independently of metric computation, optimization, or execution logic, ensuring that structural correctness is not entangled with algorithmic behavior.

---

## Minimal Example

The example below illustrates a typical contract workflow using `eb-contracts`: adapting an external forecast frame into a canonical contract artifact and validating it at the system boundary.

```python
import pandas as pd

from eb_contracts import set_validation_mode
from eb_contracts.api import PanelPointColumns, to_panel_point_v1

raw = pd.DataFrame(
    {
        "store": ["A", "A"],
        "timestamp": [
            pd.Timestamp("2025-01-01 00:00:00"),
            pd.Timestamp("2025-01-01 00:30:00"),
        ],
        "actual": [10.0, 12.0],
        "forecast": [11.0, 13.0],
    }
)

columns = PanelPointColumns(
    entity_id="store",
    interval_start="timestamp",
    y_true="actual",
    y_pred="forecast",
)

with set_validation_mode("strict"):
    forecast = to_panel_point_v1(raw, columns=columns)

print(type(forecast))
```

---

## License

BSD 3-Clause License.
© 2026 Kyle Corrie.
