|
7 | 7 |
|
8 | 8 | from __future__ import annotations |
9 | 9 |
|
10 | | -# Re-export dataclasses for backward compatibility |
11 | | -from entsoe._models import Category, Endpoint |
12 | | -from entsoe.catalog_manager import ENTSOECatalogManager as _Manager |
| 10 | +from dataclasses import dataclass, field |
13 | 11 |
|
14 | | -__all__ = ["Category", "Endpoint", "CATEGORIES", "get_category", "summary"] |
15 | 12 |
|
16 | | -# ── Load categories from YAML ────────────────────────────────────────── |
| 13 | +@dataclass(frozen=True) |
| 14 | +class Endpoint: |
| 15 | + """A queryable data endpoint.""" |
17 | 16 |
|
18 | | -_mgr = _Manager() |
19 | | -_cats = {c.key: c for c in _mgr._load_categories()} |
| 17 | + name: str |
| 18 | + description: str |
| 19 | + method: str # Python client method name |
| 20 | + cli: str # CLI command |
| 21 | + resolution: str # e.g. "15min", "hourly", "daily" |
| 22 | + columns: tuple[str, ...] # key columns returned |
| 23 | + units: str |
| 24 | + notes: str = "" |
20 | 25 |
|
21 | | -CATEGORIES: dict[str, Category] = _cats |
22 | 26 |
|
23 | | -# Individual constants for backward compatibility |
24 | | -PRICES = CATEGORIES["prices"] |
25 | | -LOAD = CATEGORIES["load"] |
26 | | -GENERATION = CATEGORIES["generation"] |
27 | | -TRANSMISSION = CATEGORIES["transmission"] |
28 | | -BALANCING = CATEGORIES["balancing"] |
| 27 | +@dataclass(frozen=True) |
| 28 | +class Category: |
| 29 | + """A top-level data category grouping related endpoints.""" |
| 30 | + |
| 31 | + name: str |
| 32 | + description: str |
| 33 | + namespace: str # Python client namespace (e.g. "prices") |
| 34 | + endpoints: tuple[Endpoint, ...] |
| 35 | + |
| 36 | + |
| 37 | +# ── Prices ────────────────────────────────────────────────────────────── |
| 38 | + |
| 39 | +PRICES = Category( |
| 40 | + name="Prices", |
| 41 | + description="Day-ahead electricity market prices", |
| 42 | + namespace="prices", |
| 43 | + endpoints=( |
| 44 | + Endpoint( |
| 45 | + name="Day-Ahead Prices", |
| 46 | + description="Hourly day-ahead market clearing prices per bidding zone", |
| 47 | + method="client.prices.day_ahead(start, end, country='FR')", |
| 48 | + cli="entsoe prices day-ahead -s 2024-06-01 -e 2024-06-08 -c FR", |
| 49 | + resolution="hourly", |
| 50 | + columns=("timestamp", "country", "value", "currency", "quantity_unit"), |
| 51 | + units="EUR/MWh", |
| 52 | + ), |
| 53 | + ), |
| 54 | +) |
| 55 | + |
| 56 | +# ── Load ──────────────────────────────────────────────────────────────── |
| 57 | + |
| 58 | +LOAD = Category( |
| 59 | + name="Load", |
| 60 | + description="Actual system load and day-ahead load forecasts", |
| 61 | + namespace="load", |
| 62 | + endpoints=( |
| 63 | + Endpoint( |
| 64 | + name="Actual Total Load", |
| 65 | + description="Actual total electricity consumption per control area", |
| 66 | + method="client.load.actual(start, end, country='FR')", |
| 67 | + cli="entsoe load actual -s 2024-06-01 -e 2024-06-08 -c FR", |
| 68 | + resolution="15min or hourly (varies by country)", |
| 69 | + columns=("timestamp", "country", "value", "quantity_unit"), |
| 70 | + units="MW", |
| 71 | + ), |
| 72 | + Endpoint( |
| 73 | + name="Day-Ahead Load Forecast", |
| 74 | + description="Day-ahead forecast of total electricity consumption", |
| 75 | + method="client.load.forecast(start, end, country='FR')", |
| 76 | + cli="entsoe load forecast -s 2024-06-01 -e 2024-06-08 -c FR", |
| 77 | + resolution="15min or hourly (varies by country)", |
| 78 | + columns=("timestamp", "country", "value", "quantity_unit"), |
| 79 | + units="MW", |
| 80 | + ), |
| 81 | + ), |
| 82 | +) |
| 83 | + |
| 84 | +# ── Generation ────────────────────────────────────────────────────────── |
| 85 | + |
| 86 | +GENERATION = Category( |
| 87 | + name="Generation", |
| 88 | + description="Actual generation, forecasts, installed capacity, and per-plant output", |
| 89 | + namespace="generation", |
| 90 | + endpoints=( |
| 91 | + Endpoint( |
| 92 | + name="Actual Generation per Type", |
| 93 | + description="Actual electricity generation broken down by fuel/technology type (PSR)", |
| 94 | + method="client.generation.actual(start, end, country='FR')", |
| 95 | + cli="entsoe generation actual -s 2024-06-01 -e 2024-06-08 -c FR", |
| 96 | + resolution="15min or hourly", |
| 97 | + columns=("timestamp", "country", "psr_type", "value", "quantity_unit"), |
| 98 | + units="MW", |
| 99 | + notes="Filter by PSR type: --psr solar --psr wind_onshore", |
| 100 | + ), |
| 101 | + Endpoint( |
| 102 | + name="Generation Forecast (Wind/Solar)", |
| 103 | + description="Day-ahead forecast for wind and solar generation", |
| 104 | + method="client.generation.forecast(start, end, country='FR')", |
| 105 | + cli="entsoe generation forecast -s 2024-06-01 -e 2024-06-08 -c FR", |
| 106 | + resolution="15min or hourly", |
| 107 | + columns=("timestamp", "country", "psr_type", "value", "quantity_unit"), |
| 108 | + units="MW", |
| 109 | + ), |
| 110 | + Endpoint( |
| 111 | + name="Installed Generation Capacity", |
| 112 | + description="Installed generation capacity per type (updated annually or on change)", |
| 113 | + method="client.generation.installed_capacity(start, end, country='FR')", |
| 114 | + cli="entsoe generation capacity -s 2024-06-01 -e 2024-06-08 -c FR", |
| 115 | + resolution="yearly (point-in-time)", |
| 116 | + columns=("timestamp", "country", "psr_type", "value", "quantity_unit"), |
| 117 | + units="MW", |
| 118 | + ), |
| 119 | + Endpoint( |
| 120 | + name="Actual Generation per Plant", |
| 121 | + description="Generation output per individual production unit (>= 100 MW)", |
| 122 | + method="client.generation.per_plant(start, end, country='FR')", |
| 123 | + cli="entsoe generation per-plant -s 2024-06-01 -e 2024-06-08 -c FR", |
| 124 | + resolution="15min or hourly", |
| 125 | + columns=("timestamp", "country", "unit_name", "psr_type", "value", "quantity_unit"), |
| 126 | + units="MW", |
| 127 | + ), |
| 128 | + ), |
| 129 | +) |
| 130 | + |
| 131 | +# ── Transmission ──────────────────────────────────────────────────────── |
| 132 | + |
| 133 | +TRANSMISSION = Category( |
| 134 | + name="Transmission", |
| 135 | + description="Cross-border physical flows, scheduled exchanges, and transfer capacity", |
| 136 | + namespace="transmission", |
| 137 | + endpoints=( |
| 138 | + Endpoint( |
| 139 | + name="Physical Cross-Border Flows", |
| 140 | + description="Actual measured electricity flows between bidding zones", |
| 141 | + method="client.transmission.crossborder_flows(start, end, country_from='FR', country_to='DE_LU')", |
| 142 | + cli="entsoe transmission flows -s 2024-06-01 -e 2024-06-08 --from FR --to DE_LU", |
| 143 | + resolution="15min or hourly", |
| 144 | + columns=("timestamp", "in_domain", "value", "quantity_unit"), |
| 145 | + units="MW", |
| 146 | + notes="Use --border for multi-border queries: --border FR-*, --border iberian", |
| 147 | + ), |
| 148 | + Endpoint( |
| 149 | + name="Scheduled Commercial Exchanges", |
| 150 | + description="Day-ahead scheduled commercial power exchanges between zones", |
| 151 | + method="client.transmission.scheduled_exchanges(start, end, country_from='FR', country_to='ES')", |
| 152 | + cli="entsoe transmission exchanges -s 2024-06-01 -e 2024-06-08 --from FR --to ES", |
| 153 | + resolution="hourly", |
| 154 | + columns=("timestamp", "in_domain", "value", "quantity_unit"), |
| 155 | + units="MW", |
| 156 | + ), |
| 157 | + Endpoint( |
| 158 | + name="Net Transfer Capacity", |
| 159 | + description="Available transfer capacity (NTC) between bidding zones", |
| 160 | + method="client.transmission.net_transfer_capacity(start, end, country_from='FR', country_to='ES')", |
| 161 | + cli="entsoe transmission capacity -s 2024-06-01 -e 2024-06-08 --from FR --to ES", |
| 162 | + resolution="hourly", |
| 163 | + columns=("timestamp", "in_domain", "value", "quantity_unit"), |
| 164 | + units="MW", |
| 165 | + ), |
| 166 | + ), |
| 167 | +) |
| 168 | + |
| 169 | +# ── Balancing ─────────────────────────────────────────────────────────── |
| 170 | + |
| 171 | +BALANCING = Category( |
| 172 | + name="Balancing", |
| 173 | + description="System imbalance prices and volumes", |
| 174 | + namespace="balancing", |
| 175 | + endpoints=( |
| 176 | + Endpoint( |
| 177 | + name="Imbalance Prices", |
| 178 | + description="System imbalance settlement prices", |
| 179 | + method="client.balancing.imbalance_prices(start, end, country='FR')", |
| 180 | + cli="entsoe balancing prices -s 2024-06-01 -e 2024-06-08 -c FR", |
| 181 | + resolution="15min or hourly (varies by country)", |
| 182 | + columns=("timestamp", "country", "value", "quantity_unit"), |
| 183 | + units="EUR/MWh", |
| 184 | + ), |
| 185 | + Endpoint( |
| 186 | + name="Imbalance Volumes", |
| 187 | + description="Net system imbalance volumes", |
| 188 | + method="client.balancing.imbalance_volumes(start, end, country='FR')", |
| 189 | + cli="entsoe balancing volumes -s 2024-06-01 -e 2024-06-08 -c FR", |
| 190 | + resolution="15min or hourly (varies by country)", |
| 191 | + columns=("timestamp", "country", "value", "quantity_unit"), |
| 192 | + units="MW", |
| 193 | + ), |
| 194 | + ), |
| 195 | +) |
| 196 | + |
| 197 | +# ── Full catalog ──────────────────────────────────────────────────────── |
| 198 | + |
| 199 | +CATEGORIES: dict[str, Category] = { |
| 200 | + "prices": PRICES, |
| 201 | + "load": LOAD, |
| 202 | + "generation": GENERATION, |
| 203 | + "transmission": TRANSMISSION, |
| 204 | + "balancing": BALANCING, |
| 205 | +} |
29 | 206 |
|
30 | 207 |
|
31 | 208 | def get_category(name: str) -> Category: |
|
0 commit comments