python-entsoe 0.5.0__tar.gz → 0.6.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. python_entsoe-0.6.0/.release-please-manifest.json +3 -0
  2. {python_entsoe-0.5.0 → python_entsoe-0.6.0}/CHANGELOG.md +13 -0
  3. {python_entsoe-0.5.0 → python_entsoe-0.6.0}/PKG-INFO +2 -1
  4. {python_entsoe-0.5.0 → python_entsoe-0.6.0}/pyproject.toml +5 -1
  5. {python_entsoe-0.5.0 → python_entsoe-0.6.0/src/entsoe/.agents}/skills/entsoe/SKILL.md +91 -117
  6. {python_entsoe-0.5.0 → python_entsoe-0.6.0}/src/entsoe/__init__.py +2 -0
  7. {python_entsoe-0.5.0 → python_entsoe-0.6.0}/src/entsoe/_mappings.py +1 -0
  8. python_entsoe-0.6.0/src/entsoe/catalog.py +51 -0
  9. {python_entsoe-0.5.0 → python_entsoe-0.6.0}/src/entsoe/cli/app.py +2 -0
  10. python_entsoe-0.6.0/src/entsoe/cli/catalog_cmd.py +148 -0
  11. {python_entsoe-0.5.0 → python_entsoe-0.6.0}/src/entsoe/client.py +3 -0
  12. {python_entsoe-0.5.0 → python_entsoe-0.6.0}/uv.lock +3 -1
  13. python_entsoe-0.5.0/.release-please-manifest.json +0 -3
  14. python_entsoe-0.5.0/src/entsoe/.agents/skills/entsoe/SKILL.md +0 -202
  15. {python_entsoe-0.5.0 → python_entsoe-0.6.0}/.github/workflows/publish.yml +0 -0
  16. {python_entsoe-0.5.0 → python_entsoe-0.6.0}/.gitignore +0 -0
  17. {python_entsoe-0.5.0 → python_entsoe-0.6.0}/.python-version +0 -0
  18. {python_entsoe-0.5.0 → python_entsoe-0.6.0}/CLAUDE.md +0 -0
  19. {python_entsoe-0.5.0 → python_entsoe-0.6.0}/README.md +0 -0
  20. {python_entsoe-0.5.0 → python_entsoe-0.6.0}/docs/data-availability.md +0 -0
  21. {python_entsoe-0.5.0 → python_entsoe-0.6.0}/examples/balancing.ipynb +0 -0
  22. {python_entsoe-0.5.0 → python_entsoe-0.6.0}/examples/generation.ipynb +0 -0
  23. {python_entsoe-0.5.0 → python_entsoe-0.6.0}/examples/generation_per_plant.ipynb +0 -0
  24. {python_entsoe-0.5.0 → python_entsoe-0.6.0}/examples/load.ipynb +0 -0
  25. {python_entsoe-0.5.0 → python_entsoe-0.6.0}/examples/prices.ipynb +0 -0
  26. {python_entsoe-0.5.0 → python_entsoe-0.6.0}/examples/transmission.ipynb +0 -0
  27. {python_entsoe-0.5.0 → python_entsoe-0.6.0}/release-please-config.json +0 -0
  28. {python_entsoe-0.5.0 → python_entsoe-0.6.0}/scripts/generate_notebooks.py +0 -0
  29. {python_entsoe-0.5.0 → python_entsoe-0.6.0}/src/entsoe/_http.py +0 -0
  30. {python_entsoe-0.5.0 → python_entsoe-0.6.0}/src/entsoe/_xml.py +0 -0
  31. {python_entsoe-0.5.0 → python_entsoe-0.6.0}/src/entsoe/cache.py +0 -0
  32. {python_entsoe-0.5.0 → python_entsoe-0.6.0}/src/entsoe/cli/__init__.py +0 -0
  33. {python_entsoe-0.5.0 → python_entsoe-0.6.0}/src/entsoe/cli/_output.py +0 -0
  34. {python_entsoe-0.5.0 → python_entsoe-0.6.0}/src/entsoe/cli/_resolve.py +0 -0
  35. {python_entsoe-0.5.0 → python_entsoe-0.6.0}/src/entsoe/cli/balancing.py +0 -0
  36. {python_entsoe-0.5.0 → python_entsoe-0.6.0}/src/entsoe/cli/cache_cmd.py +0 -0
  37. {python_entsoe-0.5.0 → python_entsoe-0.6.0}/src/entsoe/cli/config.py +0 -0
  38. {python_entsoe-0.5.0 → python_entsoe-0.6.0}/src/entsoe/cli/config_cmd.py +0 -0
  39. {python_entsoe-0.5.0 → python_entsoe-0.6.0}/src/entsoe/cli/exec_cmd.py +0 -0
  40. {python_entsoe-0.5.0 → python_entsoe-0.6.0}/src/entsoe/cli/generation.py +0 -0
  41. {python_entsoe-0.5.0 → python_entsoe-0.6.0}/src/entsoe/cli/load.py +0 -0
  42. {python_entsoe-0.5.0 → python_entsoe-0.6.0}/src/entsoe/cli/prices.py +0 -0
  43. {python_entsoe-0.5.0 → python_entsoe-0.6.0}/src/entsoe/cli/transmission.py +0 -0
  44. {python_entsoe-0.5.0 → python_entsoe-0.6.0}/src/entsoe/exceptions.py +0 -0
  45. {python_entsoe-0.5.0 → python_entsoe-0.6.0}/src/entsoe/namespaces/__init__.py +0 -0
  46. {python_entsoe-0.5.0 → python_entsoe-0.6.0}/src/entsoe/namespaces/_base.py +0 -0
  47. {python_entsoe-0.5.0 → python_entsoe-0.6.0}/src/entsoe/namespaces/balancing.py +0 -0
  48. {python_entsoe-0.5.0 → python_entsoe-0.6.0}/src/entsoe/namespaces/generation.py +0 -0
  49. {python_entsoe-0.5.0 → python_entsoe-0.6.0}/src/entsoe/namespaces/load.py +0 -0
  50. {python_entsoe-0.5.0 → python_entsoe-0.6.0}/src/entsoe/namespaces/prices.py +0 -0
  51. {python_entsoe-0.5.0 → python_entsoe-0.6.0}/src/entsoe/namespaces/transmission.py +0 -0
  52. {python_entsoe-0.5.0 → python_entsoe-0.6.0}/src/entsoe/py.typed +0 -0
  53. {python_entsoe-0.5.0 → python_entsoe-0.6.0}/tests/__init__.py +0 -0
  54. {python_entsoe-0.5.0 → python_entsoe-0.6.0}/tests/conftest.py +0 -0
  55. {python_entsoe-0.5.0 → python_entsoe-0.6.0}/tests/test_balancing.py +0 -0
  56. {python_entsoe-0.5.0 → python_entsoe-0.6.0}/tests/test_generation.py +0 -0
  57. {python_entsoe-0.5.0 → python_entsoe-0.6.0}/tests/test_load.py +0 -0
  58. {python_entsoe-0.5.0 → python_entsoe-0.6.0}/tests/test_multi.py +0 -0
  59. {python_entsoe-0.5.0 → python_entsoe-0.6.0}/tests/test_prices.py +0 -0
  60. {python_entsoe-0.5.0 → python_entsoe-0.6.0}/tests/test_transmission.py +0 -0
  61. {python_entsoe-0.5.0 → python_entsoe-0.6.0}/tests/test_validation.py +0 -0
@@ -0,0 +1,3 @@
1
+ {
2
+ ".": "0.6.0"
3
+ }
@@ -1,5 +1,18 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.6.0](https://github.com/datons/python-entsoe/compare/python-entsoe-v0.5.0...python-entsoe-v0.6.0) (2026-03-04)
4
+
5
+
6
+ ### Features
7
+
8
+ * add built-in data catalog with CLI and Python API ([987bb18](https://github.com/datons/python-entsoe/commit/987bb181f0d1b6a8d18578b25902b77c7029ac6f))
9
+ * migrate catalog from hardcoded Python to YAML-backed manager ([dcc35f7](https://github.com/datons/python-entsoe/commit/dcc35f7aa6359f49ef9f870d942c6d860c319597))
10
+
11
+
12
+ ### Bug Fixes
13
+
14
+ * update skill with correct exec syntax and Python-first approach ([bd6dca7](https://github.com/datons/python-entsoe/commit/bd6dca7a9a8ac74c0f855719cc660a93a918eaf4))
15
+
3
16
  ## [0.5.0](https://github.com/datons/python-entsoe/compare/python-entsoe-v0.4.2...python-entsoe-v0.5.0) (2026-03-04)
4
17
 
5
18
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-entsoe
3
- Version: 0.5.0
3
+ Version: 0.6.0
4
4
  Summary: Python client for the ENTSO-E Transparency Platform API
5
5
  Project-URL: Homepage, https://github.com/datons/python-entsoe
6
6
  Project-URL: Repository, https://github.com/datons/python-entsoe
@@ -21,6 +21,7 @@ Classifier: Topic :: Scientific/Engineering
21
21
  Requires-Python: >=3.10
22
22
  Requires-Dist: pandas>=2.0
23
23
  Requires-Dist: pyarrow>=23.0.1
24
+ Requires-Dist: pyyaml>=6.0
24
25
  Requires-Dist: requests>=2.28
25
26
  Requires-Dist: rich>=13.0
26
27
  Requires-Dist: typer>=0.9
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "python-entsoe"
3
- version = "0.5.0"
3
+ version = "0.6.0"
4
4
  description = "Python client for the ENTSO-E Transparency Platform API"
5
5
  readme = "README.md"
6
6
  license = "MIT"
@@ -22,6 +22,7 @@ classifiers = [
22
22
  ]
23
23
  dependencies = [
24
24
  "pandas>=2.0",
25
+ "pyyaml>=6.0",
25
26
  "requests>=2.28",
26
27
  "typer>=0.9",
27
28
  "rich>=13.0",
@@ -46,6 +47,9 @@ packages = ["src/entsoe"]
46
47
 
47
48
  [tool.pytest.ini_options]
48
49
  testpaths = ["tests"]
50
+ markers = [
51
+ "integration: tests that hit real APIs (deselect with -m 'not integration')",
52
+ ]
49
53
 
50
54
  [dependency-groups]
51
55
  dev = [
@@ -1,105 +1,61 @@
1
1
  ---
2
2
  name: entsoe
3
3
  description: Query European electricity market data (ENTSO-E Transparency Platform). Use when the user asks about electricity prices, load, generation, transmission, or balancing data for European countries.
4
- version: 1.0.0
4
+ version: 2.0.0
5
5
  ---
6
6
 
7
7
  # ENTSO-E Data Assistant
8
8
 
9
- You have access to the `python-entsoe` CLI and library for querying the ENTSO-E Transparency Platform (European electricity market data).
9
+ You have access to the `python-entsoe` library and CLI for querying the ENTSO-E Transparency Platform (European electricity market data).
10
10
 
11
- ## CLI Reference
11
+ ## When to use what
12
12
 
13
- ### Prices
13
+ - **Python scripts** (default): reproducible, composable, saveable. Use for any data work the user will want to keep or iterate on.
14
+ - **CLI**: quick one-shot lookups, exploration, sanity checks. Use when the user wants a fast answer they won't need again.
15
+ - **If unsure**: ask the user whether they want a script or a quick CLI check.
14
16
 
15
- ```bash
16
- # Day-ahead prices for one country
17
- entsoe prices day-ahead -s 2024-06-01 -e 2024-06-08 --country FR
18
-
19
- # Multi-country
20
- entsoe prices day-ahead -s 2024-06-01 -e 2024-06-08 --country FR --country ES
21
- ```
22
-
23
- ### Load
24
-
25
- ```bash
26
- # Actual total system load
27
- entsoe load actual -s 2024-06-01 -e 2024-06-08 --country FR
28
-
29
- # Day-ahead load forecast
30
- entsoe load forecast -s 2024-06-01 -e 2024-06-08 --country FR
31
- ```
32
-
33
- ### Generation
34
-
35
- ```bash
36
- # Actual generation per type (all types)
37
- entsoe generation actual -s 2024-06-01 -e 2024-06-08 --country FR
38
-
39
- # Filter by PSR type
40
- entsoe generation actual -s 2024-06-01 -e 2024-06-08 --country FR --psr solar --psr wind_onshore
17
+ ## Python Library (default)
41
18
 
42
- # Generation forecast (wind/solar)
43
- entsoe generation forecast -s 2024-06-01 -e 2024-06-08 --country FR
44
-
45
- # Installed capacity
46
- entsoe generation capacity -s 2024-06-01 -e 2024-06-08 --country FR
47
-
48
- # Per production unit
49
- entsoe generation per-plant -s 2024-06-01 -e 2024-06-08 --country FR
50
- ```
51
-
52
- ### Transmission
53
-
54
- ```bash
55
- # Physical cross-border flows
56
- entsoe transmission flows -s 2024-06-01 -e 2024-06-08 --from FR --to ES
57
-
58
- # Scheduled commercial exchanges
59
- entsoe transmission exchanges -s 2024-06-01 -e 2024-06-08 --from FR --to ES
60
-
61
- # Net transfer capacity
62
- entsoe transmission capacity -s 2024-06-01 -e 2024-06-08 --from FR --to ES
63
- ```
64
-
65
- ### Balancing
66
-
67
- ```bash
68
- # Imbalance prices
69
- entsoe balancing prices -s 2024-06-01 -e 2024-06-08 --country FR
70
-
71
- # Imbalance volumes
72
- entsoe balancing volumes -s 2024-06-01 -e 2024-06-08 --country FR
73
- ```
19
+ ```python
20
+ from entsoe import Client
74
21
 
75
- ### Exec (ad-hoc pandas expressions)
22
+ client = Client() # reads config file, then ENTSOE_API_KEY env var
76
23
 
77
- Run any pandas expression against fetched data:
24
+ # --- Prices ---
25
+ df = client.prices.day_ahead("2024-06-01", "2024-06-08", country="FR")
26
+ df = client.prices.day_ahead("2024-06-01", "2024-06-08", country=["FR", "ES"])
78
27
 
79
- ```bash
80
- # Descriptive statistics on prices
81
- entsoe exec prices day-ahead -s 2024-06-01 -e 2024-06-08 -c FR -x "df.describe()"
28
+ # --- Load ---
29
+ df = client.load.actual("2024-06-01", "2024-06-08", country="FR")
30
+ df = client.load.forecast("2024-06-01", "2024-06-08", country="FR")
82
31
 
83
- # Daily mean load
84
- entsoe exec load actual -s 2024-06-01 -e 2024-06-08 -c FR -x "df.resample('D').mean()"
32
+ # --- Generation ---
33
+ df = client.generation.actual("2024-06-01", "2024-06-08", country="FR")
34
+ df = client.generation.actual("2024-06-01", "2024-06-08", country="FR", psr_type="solar")
35
+ df = client.generation.actual("2024-06-01", "2024-06-08", country="FR", psr_type=["solar", "wind_onshore"])
36
+ df = client.generation.forecast("2024-06-01", "2024-06-08", country="FR")
37
+ df = client.generation.installed_capacity("2024-06-01", "2024-06-08", country="FR")
38
+ df = client.generation.per_plant("2024-06-01", "2024-06-08", country="FR")
85
39
 
86
- # Generation with PSR filter
87
- entsoe exec generation actual -s 2024-06-01 -e 2024-06-08 -c FR --psr solar -x "df.head(20)"
40
+ # --- Transmission ---
41
+ df = client.transmission.crossborder_flows("2024-06-01", "2024-06-08", country_from="FR", country_to="ES")
42
+ df = client.transmission.scheduled_exchanges("2024-06-01", "2024-06-08", country_from="FR", country_to="ES")
43
+ df = client.transmission.net_transfer_capacity("2024-06-01", "2024-06-08", country_from="FR", country_to="ES")
88
44
 
89
- # Transmission analysis
90
- entsoe exec transmission flows -s 2024-06-01 -e 2024-06-08 --from FR --to ES -x "df.describe()"
45
+ # --- Balancing ---
46
+ df = client.balancing.imbalance_prices("2024-06-01", "2024-06-08", country="FR")
47
+ df = client.balancing.imbalance_volumes("2024-06-01", "2024-06-08", country="FR")
91
48
  ```
92
49
 
93
- ### Output formats
50
+ ### Key conventions
94
51
 
95
- All commands support:
96
-
97
- ```bash
98
- --format table # Default: Rich table in terminal
99
- --format csv # CSV output
100
- --format json # JSON output
101
- --output file.csv # Write to file instead of stdout
102
- ```
52
+ - **Timezone**: All string dates are interpreted in Europe/Brussels (CET) by default
53
+ - **Auto year-splitting**: Date ranges > 1 year are automatically split into yearly API requests
54
+ - **Rate limiting**: ENTSO-E has a 400-request/minute limit; the library handles retries
55
+ - **Multi-value support**: Pass lists for `country` or `psr_type` to get combined results with label columns
56
+ - **Transmission**: Uses `country_from`/`country_to`; multi-value adds a `border` column
57
+ - **No caching**: Data is fetched fresh on each request
58
+ - **Custom exceptions**: `ENTSOEError`, `AuthenticationError`, `APIResponseError`, `InvalidParameterError`, `NetworkError`
103
59
 
104
60
  ## Country Codes
105
61
 
@@ -143,60 +99,78 @@ Bidding zones: `DK_1`, `DK_2`, `NO_1`–`NO_5`, `SE_1`–`SE_4`, `IT_NORTH`, `IT
143
99
  | waste | Waste | B17 |
144
100
  | other | Other | B20 |
145
101
 
146
- Use shorthands with `--psr` (e.g. `--psr solar --psr wind_onshore`), or ENTSO-E codes (e.g. `--psr B16`).
102
+ Use shorthands with `psr_type=` (Python) or `--psr` (CLI), e.g. `psr_type="solar"` or `--psr solar`.
147
103
 
148
- ## Python Library
104
+ ## CLI Reference (quick lookups)
149
105
 
150
- ```python
151
- from entsoe import Client
106
+ ### Catalog (offline)
152
107
 
153
- client = Client() # reads config file, then ENTSOE_API_KEY env var
108
+ ```bash
109
+ entsoe catalog list # All data categories and endpoints
110
+ entsoe catalog show prices # Detailed info for a category
111
+ entsoe catalog countries # Country/bidding zone codes
112
+ entsoe catalog psr # PSR (generation) types
113
+ entsoe catalog borders # Border groups and interconnections
114
+ ```
154
115
 
116
+ ### Fetch data
117
+
118
+ ```bash
155
119
  # Prices
156
- df = client.prices.day_ahead("2024-06-01", "2024-06-08", country="FR")
157
- df = client.prices.day_ahead("2024-06-01", "2024-06-08", country=["FR", "ES"])
120
+ entsoe prices day-ahead -s 2024-06-01 -e 2024-06-08 -c FR
121
+ entsoe prices day-ahead -P week -c FR,ES # Period shorthand
158
122
 
159
123
  # Load
160
- df = client.load.actual("2024-06-01", "2024-06-08", country="FR")
161
- df = client.load.forecast("2024-06-01", "2024-06-08", country="FR")
124
+ entsoe load actual -P month -c FR
125
+ entsoe load forecast -s 2024-06-01 -e 2024-06-08 -c FR
162
126
 
163
127
  # Generation
164
- df = client.generation.actual("2024-06-01", "2024-06-08", country="FR")
165
- df = client.generation.actual("2024-06-01", "2024-06-08", country="FR", psr_type="solar")
166
- df = client.generation.actual("2024-06-01", "2024-06-08", country="FR", psr_type=["solar", "wind_onshore"])
167
- df = client.generation.forecast("2024-06-01", "2024-06-08", country="FR")
168
- df = client.generation.installed_capacity("2024-06-01", "2024-06-08", country="FR")
169
- df = client.generation.per_plant("2024-06-01", "2024-06-08", country="FR")
128
+ entsoe generation actual -P week -c FR --psr solar --psr wind_onshore
129
+ entsoe generation forecast -P week -c FR
130
+ entsoe generation capacity -s 2024-01-01 -e 2024-12-31 -c FR
131
+ entsoe generation per-plant -P week -c FR
170
132
 
171
133
  # Transmission
172
- df = client.transmission.crossborder_flows("2024-06-01", "2024-06-08", country_from="FR", country_to="ES")
173
- df = client.transmission.scheduled_exchanges("2024-06-01", "2024-06-08", country_from="FR", country_to="ES")
174
- df = client.transmission.net_transfer_capacity("2024-06-01", "2024-06-08", country_from="FR", country_to="ES")
134
+ entsoe transmission flows -P week --from FR --to ES
135
+ entsoe transmission exchanges -P week --border ES-*,FR-*
175
136
 
176
137
  # Balancing
177
- df = client.balancing.imbalance_prices("2024-06-01", "2024-06-08", country="FR")
178
- df = client.balancing.imbalance_volumes("2024-06-01", "2024-06-08", country="FR")
138
+ entsoe balancing prices -P week -c FR
139
+ entsoe balancing volumes -P week -c FR
179
140
  ```
180
141
 
181
- ## Configuration
142
+ ### Exec (ad-hoc pandas)
143
+
144
+ `exec` is a subcommand **within each namespace**:
182
145
 
183
146
  ```bash
184
- # Store your API key persistently (recommended)
185
- entsoe config set api-key YOUR_KEY
147
+ entsoe prices exec day-ahead -P week -c FR -x "df.describe()"
148
+ entsoe load exec actual -P 7d -c FR -x "df.resample('D').mean()"
149
+ entsoe generation exec actual -P month -c FR --psr solar -x "df.head(20)"
150
+ entsoe transmission exec flows -P week --from FR --to ES -x "df.describe()"
151
+ entsoe balancing exec prices -P week -c NL -x "df.describe()"
152
+ ```
186
153
 
187
- # Verify it's stored
188
- entsoe config get api-key
154
+ ### Period shorthand (`-P`)
155
+
156
+ All data commands support `-P` as an alternative to `--start`/`--end`:
157
+
158
+ ```
159
+ -P today, -P yesterday, -P week, -P month, -P ytd, -P 14d
189
160
  ```
190
161
 
191
- The config file is stored at `~/.config/entsoe/config.toml`.
162
+ ### Output options
192
163
 
193
- ## Key Conventions
164
+ ```
165
+ --format table|csv|json (default: table)
166
+ --output file.csv (write to file instead of stdout)
167
+ ```
194
168
 
195
- - **Timezone**: All string dates are interpreted in Europe/Brussels (CET) by default
196
- - **Auto year-splitting**: Date ranges exceeding 1 year are automatically split into yearly API requests
197
- - **Rate limiting**: ENTSO-E has a 400-request/minute limit; the library handles retries
198
- - **Multi-value support**: Pass lists for country or psr_type to get combined results with label columns
199
- - **Transmission**: Uses `--from`/`--to` instead of `--country`; multi-value adds a `border` column
200
- - **API key resolution**: config file (`~/.config/entsoe/config.toml`) > `ENTSOE_API_KEY` env var
201
- - **No caching**: Data is fetched fresh on each request (unlike python-esios)
202
- - **Custom exceptions**: `ENTSOEError`, `AuthenticationError`, `APIResponseError`, `InvalidParameterError`, `NetworkError`
169
+ ## Configuration
170
+
171
+ ```bash
172
+ entsoe config set api-key YOUR_KEY
173
+ entsoe config get api-key
174
+ ```
175
+
176
+ Config file: `~/.config/entsoe/config.toml`. API key resolution: config file > `ENTSOE_API_KEY` env var.
@@ -3,6 +3,7 @@
3
3
  from .client import Client, ENTSOEClient
4
4
  from .exceptions import ENTSOEError, InvalidParameterError, NoDataError, RateLimitError
5
5
  from ._mappings import COUNTRY_NAMES, PSR_CODES, country_name, psr_name
6
+ from . import catalog
6
7
 
7
8
  __version__ = "0.4.2"
8
9
  __all__ = [
@@ -14,6 +15,7 @@ __all__ = [
14
15
  "NoDataError",
15
16
  "PSR_CODES",
16
17
  "RateLimitError",
18
+ "catalog",
17
19
  "country_name",
18
20
  "psr_name",
19
21
  ]
@@ -399,6 +399,7 @@ NEIGHBOURS: dict[str, set[str]] = {
399
399
  "BG": {"RO", "RS", "MK", "GR", "TR"},
400
400
  "MK": {"RS", "BG", "GR", "AL"},
401
401
  "GR": {"BG", "MK", "AL", "IT_SUD", "TR"},
402
+ "IT_SUD": {"GR"},
402
403
  "AL": {"RS", "MK", "GR", "ME"},
403
404
  "ME": {"RS", "BA", "AL"},
404
405
  "TR": {"BG", "GR"},
@@ -0,0 +1,51 @@
1
+ """Built-in data catalog for ENTSO-E Transparency Platform.
2
+
3
+ Provides structured metadata about available data categories, endpoints,
4
+ country codes, PSR types, and border groups — so users don't need to
5
+ consult external documentation every time.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ # Re-export dataclasses for backward compatibility
11
+ from entsoe._models import Category, Endpoint
12
+ from entsoe.catalog_manager import ENTSOECatalogManager as _Manager
13
+
14
+ __all__ = ["Category", "Endpoint", "CATEGORIES", "get_category", "summary"]
15
+
16
+ # ── Load categories from YAML ──────────────────────────────────────────
17
+
18
+ _mgr = _Manager()
19
+ _cats = {c.key: c for c in _mgr._load_categories()}
20
+
21
+ CATEGORIES: dict[str, Category] = _cats
22
+
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"]
29
+
30
+
31
+ def get_category(name: str) -> Category:
32
+ """Look up a category by name (case-insensitive)."""
33
+ key = name.lower().strip()
34
+ if key not in CATEGORIES:
35
+ raise KeyError(
36
+ f"Unknown category '{name}'. Available: {', '.join(CATEGORIES.keys())}"
37
+ )
38
+ return CATEGORIES[key]
39
+
40
+
41
+ def summary() -> str:
42
+ """Return a human-readable summary of all available data."""
43
+ lines = ["ENTSO-E Data Catalog", "=" * 50, ""]
44
+ for key, cat in CATEGORIES.items():
45
+ lines.append(f"{cat.name} ({cat.namespace})")
46
+ lines.append(f" {cat.description}")
47
+ for ep in cat.endpoints:
48
+ lines.append(f" - {ep.name}: {ep.description}")
49
+ lines.append(f" Resolution: {ep.resolution} | Units: {ep.units}")
50
+ lines.append("")
51
+ return "\n".join(lines)
@@ -38,6 +38,7 @@ from entsoe.cli.transmission import transmission_app # noqa: E402
38
38
  from entsoe.cli.balancing import balancing_app # noqa: E402
39
39
  from entsoe.cli.config_cmd import config_app # noqa: E402
40
40
  from entsoe.cli.cache_cmd import cache_app # noqa: E402
41
+ from entsoe.cli.catalog_cmd import catalog_app # noqa: E402
41
42
 
42
43
  app.add_typer(prices_app, name="prices", help="Day-ahead electricity prices")
43
44
  app.add_typer(load_app, name="load", help="Actual load and load forecasts")
@@ -46,6 +47,7 @@ app.add_typer(transmission_app, name="transmission", help="Cross-border flows an
46
47
  app.add_typer(balancing_app, name="balancing", help="Imbalance prices and volumes")
47
48
  app.add_typer(config_app, name="config", help="Configuration management")
48
49
  app.add_typer(cache_app, name="cache", help="Cache management (status, clear)")
50
+ app.add_typer(catalog_app, name="catalog", help="Browse available data, countries, PSR types, and borders")
49
51
 
50
52
 
51
53
  def main() -> None:
@@ -0,0 +1,148 @@
1
+ """CLI command: browse the built-in data catalog."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import Optional
6
+
7
+ import typer
8
+ from rich.console import Console
9
+ from rich.table import Table
10
+
11
+ from entsoe._mappings import AREA_CODES, COUNTRY_NAMES, PSR_CODES, PSR_TYPES, BORDER_GROUPS, NEIGHBOURS
12
+
13
+ catalog_app = typer.Typer(no_args_is_help=True)
14
+ console = Console()
15
+
16
+
17
+ @catalog_app.command("list")
18
+ def catalog_list():
19
+ """List all available data categories and endpoints."""
20
+ from entsoe.catalog import CATEGORIES
21
+
22
+ for key, cat in CATEGORIES.items():
23
+ console.print(f"\n[bold]{cat.name}[/bold] — {cat.description}")
24
+ console.print(f" Python: client.{cat.namespace}.*")
25
+ console.print(f" CLI: entsoe {key} <command>")
26
+
27
+ table = Table(show_header=True, padding=(0, 1))
28
+ table.add_column("Endpoint", style="cyan")
29
+ table.add_column("CLI Command", style="green")
30
+ table.add_column("Resolution")
31
+ table.add_column("Units")
32
+
33
+ for ep in cat.endpoints:
34
+ cli_short = ep.cli.split("entsoe ")[-1].split(" -")[0]
35
+ table.add_row(ep.name, cli_short, ep.resolution, ep.units)
36
+
37
+ console.print(table)
38
+
39
+
40
+ @catalog_app.command("countries")
41
+ def catalog_countries(
42
+ query: Optional[str] = typer.Argument(None, help="Filter by country name or code"),
43
+ ):
44
+ """List available country and bidding zone codes."""
45
+ table = Table(title="Country / Bidding Zone Codes", show_header=True, padding=(0, 1))
46
+ table.add_column("Code", style="cyan")
47
+ table.add_column("Name")
48
+ table.add_column("Neighbours", style="dim")
49
+
50
+ for code in sorted(AREA_CODES.keys()):
51
+ name = COUNTRY_NAMES.get(code, "")
52
+ if query:
53
+ q = query.lower()
54
+ if q not in code.lower() and q not in name.lower():
55
+ continue
56
+ neighbours = ", ".join(sorted(NEIGHBOURS.get(code, set())))
57
+ table.add_row(code, name, neighbours)
58
+
59
+ console.print(table)
60
+
61
+
62
+ @catalog_app.command("psr")
63
+ def catalog_psr():
64
+ """List available PSR (generation) types."""
65
+ table = Table(title="PSR Types (Generation)", show_header=True, padding=(0, 1))
66
+ table.add_column("Shorthand", style="cyan")
67
+ table.add_column("ENTSO-E Code", style="green")
68
+ table.add_column("Full Name")
69
+
70
+ for shorthand, code in sorted(PSR_CODES.items()):
71
+ full_name = PSR_TYPES.get(code, "")
72
+ table.add_row(shorthand, code, full_name)
73
+
74
+ console.print(table)
75
+
76
+
77
+ @catalog_app.command("borders")
78
+ def catalog_borders(
79
+ country: Optional[str] = typer.Argument(None, help="Show borders for a specific country (e.g. FR, DE_LU)"),
80
+ ):
81
+ """List border groups and interconnections."""
82
+ if country:
83
+ code = country.upper().strip()
84
+ if code not in NEIGHBOURS:
85
+ console.print(f"[red]Unknown country '{country}'[/red]. Use 'entsoe catalog countries' to list.")
86
+ raise typer.Exit(1)
87
+
88
+ name = COUNTRY_NAMES.get(code, code)
89
+ console.print(f"\n[bold]{name} ({code})[/bold] — {len(NEIGHBOURS[code])} interconnections:")
90
+
91
+ table = Table(show_header=True, padding=(0, 1))
92
+ table.add_column("Neighbour", style="cyan")
93
+ table.add_column("Name")
94
+ table.add_column("CLI (flows)")
95
+
96
+ for n in sorted(NEIGHBOURS[code]):
97
+ n_name = COUNTRY_NAMES.get(n, n)
98
+ table.add_row(n, n_name, f"entsoe transmission flows --from {code} --to {n}")
99
+
100
+ console.print(table)
101
+ console.print(f"\n[dim]Shortcut: entsoe transmission flows --border {code}-*[/dim]")
102
+ else:
103
+ # Show named border groups
104
+ console.print("\n[bold]Named Border Groups[/bold]")
105
+ table = Table(show_header=True, padding=(0, 1))
106
+ table.add_column("Group", style="cyan")
107
+ table.add_column("Borders")
108
+
109
+ for group_name, pairs in sorted(BORDER_GROUPS.items()):
110
+ unique = set()
111
+ for a, b in pairs:
112
+ key = tuple(sorted([a, b]))
113
+ unique.add(key)
114
+ border_strs = [f"{a}-{b}" for a, b in sorted(unique)]
115
+ table.add_row(group_name, ", ".join(border_strs[:8]) + ("..." if len(border_strs) > 8 else ""))
116
+
117
+ console.print(table)
118
+ console.print(f"\n[dim]Use 'entsoe catalog borders <COUNTRY>' for a specific country.[/dim]")
119
+
120
+
121
+ @catalog_app.command("show")
122
+ def catalog_show(
123
+ category: str = typer.Argument(..., help="Category name: prices, load, generation, transmission, balancing"),
124
+ ):
125
+ """Show detailed info for a specific data category."""
126
+ from entsoe.catalog import get_category
127
+
128
+ try:
129
+ cat = get_category(category)
130
+ except KeyError as e:
131
+ console.print(f"[red]{e}[/red]")
132
+ raise typer.Exit(1)
133
+
134
+ console.print(f"\n[bold]{cat.name}[/bold] — {cat.description}")
135
+ console.print(f" Python namespace: client.{cat.namespace}")
136
+ console.print()
137
+
138
+ for ep in cat.endpoints:
139
+ console.print(f" [cyan]{ep.name}[/cyan]")
140
+ console.print(f" {ep.description}")
141
+ console.print(f" Resolution: {ep.resolution}")
142
+ console.print(f" Units: {ep.units}")
143
+ console.print(f" Columns: {', '.join(ep.columns)}")
144
+ console.print(f" Python: {ep.method}")
145
+ console.print(f" CLI: {ep.cli}")
146
+ if ep.notes:
147
+ console.print(f" Notes: {ep.notes}")
148
+ console.print()
@@ -7,6 +7,7 @@ from pathlib import Path
7
7
 
8
8
  from ._http import HttpClient
9
9
  from .cache import CacheConfig, CacheStore
10
+ from .catalog_manager import ENTSOECatalogManager
10
11
  from .namespaces import (
11
12
  BalancingNamespace,
12
13
  GenerationNamespace,
@@ -100,6 +101,8 @@ class ENTSOEClient:
100
101
  self.transmission = TransmissionNamespace(http, tz=tz, cache=cache_store)
101
102
  self.balancing = BalancingNamespace(http, tz=tz, cache=cache_store)
102
103
 
104
+ self.catalog = ENTSOECatalogManager(self)
105
+
103
106
  # Expose for CLI cache commands
104
107
  self._cache = cache_store
105
108
 
@@ -1705,12 +1705,13 @@ wheels = [
1705
1705
 
1706
1706
  [[package]]
1707
1707
  name = "python-entsoe"
1708
- version = "0.4.1"
1708
+ version = "0.5.0"
1709
1709
  source = { editable = "." }
1710
1710
  dependencies = [
1711
1711
  { name = "pandas", version = "2.3.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" },
1712
1712
  { name = "pandas", version = "3.0.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" },
1713
1713
  { name = "pyarrow" },
1714
+ { name = "pyyaml" },
1714
1715
  { name = "requests" },
1715
1716
  { name = "rich" },
1716
1717
  { name = "typer" },
@@ -1728,6 +1729,7 @@ dev = [
1728
1729
  requires-dist = [
1729
1730
  { name = "pandas", specifier = ">=2.0" },
1730
1731
  { name = "pyarrow", specifier = ">=23.0.1" },
1732
+ { name = "pyyaml", specifier = ">=6.0" },
1731
1733
  { name = "requests", specifier = ">=2.28" },
1732
1734
  { name = "rich", specifier = ">=13.0" },
1733
1735
  { name = "typer", specifier = ">=0.9" },
@@ -1,3 +0,0 @@
1
- {
2
- ".": "0.5.0"
3
- }
@@ -1,202 +0,0 @@
1
- ---
2
- name: entsoe
3
- description: Query European electricity market data (ENTSO-E Transparency Platform). Use when the user asks about electricity prices, load, generation, transmission, or balancing data for European countries.
4
- version: 1.0.0
5
- ---
6
-
7
- # ENTSO-E Data Assistant
8
-
9
- You have access to the `python-entsoe` CLI and library for querying the ENTSO-E Transparency Platform (European electricity market data).
10
-
11
- ## CLI Reference
12
-
13
- ### Prices
14
-
15
- ```bash
16
- # Day-ahead prices for one country
17
- entsoe prices day-ahead -s 2024-06-01 -e 2024-06-08 --country FR
18
-
19
- # Multi-country
20
- entsoe prices day-ahead -s 2024-06-01 -e 2024-06-08 --country FR --country ES
21
- ```
22
-
23
- ### Load
24
-
25
- ```bash
26
- # Actual total system load
27
- entsoe load actual -s 2024-06-01 -e 2024-06-08 --country FR
28
-
29
- # Day-ahead load forecast
30
- entsoe load forecast -s 2024-06-01 -e 2024-06-08 --country FR
31
- ```
32
-
33
- ### Generation
34
-
35
- ```bash
36
- # Actual generation per type (all types)
37
- entsoe generation actual -s 2024-06-01 -e 2024-06-08 --country FR
38
-
39
- # Filter by PSR type
40
- entsoe generation actual -s 2024-06-01 -e 2024-06-08 --country FR --psr solar --psr wind_onshore
41
-
42
- # Generation forecast (wind/solar)
43
- entsoe generation forecast -s 2024-06-01 -e 2024-06-08 --country FR
44
-
45
- # Installed capacity
46
- entsoe generation capacity -s 2024-06-01 -e 2024-06-08 --country FR
47
-
48
- # Per production unit
49
- entsoe generation per-plant -s 2024-06-01 -e 2024-06-08 --country FR
50
- ```
51
-
52
- ### Transmission
53
-
54
- ```bash
55
- # Physical cross-border flows
56
- entsoe transmission flows -s 2024-06-01 -e 2024-06-08 --from FR --to ES
57
-
58
- # Scheduled commercial exchanges
59
- entsoe transmission exchanges -s 2024-06-01 -e 2024-06-08 --from FR --to ES
60
-
61
- # Net transfer capacity
62
- entsoe transmission capacity -s 2024-06-01 -e 2024-06-08 --from FR --to ES
63
- ```
64
-
65
- ### Balancing
66
-
67
- ```bash
68
- # Imbalance prices
69
- entsoe balancing prices -s 2024-06-01 -e 2024-06-08 --country FR
70
-
71
- # Imbalance volumes
72
- entsoe balancing volumes -s 2024-06-01 -e 2024-06-08 --country FR
73
- ```
74
-
75
- ### Exec (ad-hoc pandas expressions)
76
-
77
- Run any pandas expression against fetched data:
78
-
79
- ```bash
80
- # Descriptive statistics on prices
81
- entsoe exec prices day-ahead -s 2024-06-01 -e 2024-06-08 -c FR -x "df.describe()"
82
-
83
- # Daily mean load
84
- entsoe exec load actual -s 2024-06-01 -e 2024-06-08 -c FR -x "df.resample('D').mean()"
85
-
86
- # Generation with PSR filter
87
- entsoe exec generation actual -s 2024-06-01 -e 2024-06-08 -c FR --psr solar -x "df.head(20)"
88
-
89
- # Transmission analysis
90
- entsoe exec transmission flows -s 2024-06-01 -e 2024-06-08 --from FR --to ES -x "df.describe()"
91
- ```
92
-
93
- ### Output formats
94
-
95
- All commands support:
96
-
97
- ```bash
98
- --format table # Default: Rich table in terminal
99
- --format csv # CSV output
100
- --format json # JSON output
101
- --output file.csv # Write to file instead of stdout
102
- ```
103
-
104
- ## Country Codes
105
-
106
- | Code | Country | Code | Country |
107
- |------|---------|------|---------|
108
- | AT | Austria | IT | Italy |
109
- | BE | Belgium | LT | Lithuania |
110
- | BG | Bulgaria | LU | Luxembourg |
111
- | CH | Switzerland | LV | Latvia |
112
- | CZ | Czech Republic | NL | Netherlands |
113
- | DE_LU | Germany/Luxembourg | NO | Norway |
114
- | DK | Denmark | PL | Poland |
115
- | EE | Estonia | PT | Portugal |
116
- | ES | Spain | RO | Romania |
117
- | FI | Finland | RS | Serbia |
118
- | FR | France | SE | Sweden |
119
- | GB | Great Britain | SI | Slovenia |
120
- | GR | Greece | SK | Slovakia |
121
- | HR | Croatia | TR | Turkey |
122
- | HU | Hungary | UA | Ukraine |
123
-
124
- Bidding zones: `DK_1`, `DK_2`, `NO_1`–`NO_5`, `SE_1`–`SE_4`, `IT_NORTH`, `IT_CNOR`, `IT_CSUD`, `IT_SUD`, `IT_SICI`, `IT_SARD`, `DE_AT_LU`, `IE_SEM`.
125
-
126
- ## PSR Types (Generation)
127
-
128
- | Shorthand | Full Name | Code |
129
- |-----------|-----------|------|
130
- | solar | Solar | B16 |
131
- | wind_onshore | Wind Onshore | B19 |
132
- | wind_offshore | Wind Offshore | B18 |
133
- | nuclear | Nuclear | B14 |
134
- | gas | Fossil Gas | B04 |
135
- | hard_coal | Fossil Hard coal | B05 |
136
- | lignite | Fossil Brown coal/Lignite | B02 |
137
- | hydro_reservoir | Hydro Water Reservoir | B12 |
138
- | run_of_river | Hydro Run-of-river | B11 |
139
- | pumped_storage | Hydro Pumped Storage | B10 |
140
- | biomass | Biomass | B01 |
141
- | oil | Fossil Oil | B06 |
142
- | geothermal | Geothermal | B09 |
143
- | waste | Waste | B17 |
144
- | other | Other | B20 |
145
-
146
- Use shorthands with `--psr` (e.g. `--psr solar --psr wind_onshore`), or ENTSO-E codes (e.g. `--psr B16`).
147
-
148
- ## Python Library
149
-
150
- ```python
151
- from entsoe import ENTSOEClient
152
-
153
- client = ENTSOEClient() # reads config file, then ENTSOE_API_KEY env var
154
-
155
- # Prices
156
- df = client.prices.day_ahead("2024-06-01", "2024-06-08", country="FR")
157
- df = client.prices.day_ahead("2024-06-01", "2024-06-08", country=["FR", "ES"])
158
-
159
- # Load
160
- df = client.load.actual("2024-06-01", "2024-06-08", country="FR")
161
- df = client.load.forecast("2024-06-01", "2024-06-08", country="FR")
162
-
163
- # Generation
164
- df = client.generation.actual("2024-06-01", "2024-06-08", country="FR")
165
- df = client.generation.actual("2024-06-01", "2024-06-08", country="FR", psr_type="solar")
166
- df = client.generation.actual("2024-06-01", "2024-06-08", country="FR", psr_type=["solar", "wind_onshore"])
167
- df = client.generation.forecast("2024-06-01", "2024-06-08", country="FR")
168
- df = client.generation.installed_capacity("2024-06-01", "2024-06-08", country="FR")
169
- df = client.generation.per_plant("2024-06-01", "2024-06-08", country="FR")
170
-
171
- # Transmission
172
- df = client.transmission.crossborder_flows("2024-06-01", "2024-06-08", country_from="FR", country_to="ES")
173
- df = client.transmission.scheduled_exchanges("2024-06-01", "2024-06-08", country_from="FR", country_to="ES")
174
- df = client.transmission.net_transfer_capacity("2024-06-01", "2024-06-08", country_from="FR", country_to="ES")
175
-
176
- # Balancing
177
- df = client.balancing.imbalance_prices("2024-06-01", "2024-06-08", country="FR")
178
- df = client.balancing.imbalance_volumes("2024-06-01", "2024-06-08", country="FR")
179
- ```
180
-
181
- ## Configuration
182
-
183
- ```bash
184
- # Store your API key persistently (recommended)
185
- entsoe config set api-key YOUR_KEY
186
-
187
- # Verify it's stored
188
- entsoe config get api-key
189
- ```
190
-
191
- The config file is stored at `~/.config/entsoe/config.toml`.
192
-
193
- ## Key Conventions
194
-
195
- - **Timezone**: All string dates are interpreted in Europe/Brussels (CET) by default
196
- - **Auto year-splitting**: Date ranges exceeding 1 year are automatically split into yearly API requests
197
- - **Rate limiting**: ENTSO-E has a 400-request/minute limit; the library handles retries
198
- - **Multi-value support**: Pass lists for country or psr_type to get combined results with label columns
199
- - **Transmission**: Uses `--from`/`--to` instead of `--country`; multi-value adds a `border` column
200
- - **API key resolution**: config file (`~/.config/entsoe/config.toml`) > `ENTSOE_API_KEY` env var
201
- - **No caching**: Data is fetched fresh on each request (unlike python-esios)
202
- - **Custom exceptions**: `ENTSOEError`, `AuthenticationError`, `APIResponseError`, `InvalidParameterError`, `NetworkError`
File without changes
File without changes
File without changes