python-entsoe 0.6.3__py3-none-any.whl → 0.7.0__py3-none-any.whl

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.
entsoe/_mappings.py CHANGED
@@ -64,6 +64,30 @@ AREA_CODES: dict[str, str] = {
64
64
  "XK": "10Y1001C--00100H",
65
65
  }
66
66
 
67
+ # IANA timezone of each ENTSO-E bidding area. Keys intentionally mirror AREA_CODES.
68
+ AREA_TZ: dict[str, str] = {
69
+ "AL": "Europe/Tirane", "AT": "Europe/Vienna", "BA": "Europe/Sarajevo",
70
+ "BE": "Europe/Brussels", "BG": "Europe/Sofia", "CH": "Europe/Zurich",
71
+ "CZ": "Europe/Prague", "DE": "Europe/Berlin", "DE_LU": "Europe/Berlin",
72
+ "DE_AT_LU": "Europe/Berlin", "DK": "Europe/Copenhagen",
73
+ "DK_1": "Europe/Copenhagen", "DK_2": "Europe/Copenhagen",
74
+ "EE": "Europe/Tallinn", "ES": "Europe/Madrid", "FI": "Europe/Helsinki",
75
+ "FR": "Europe/Paris", "GB": "Europe/London", "GR": "Europe/Athens",
76
+ "HR": "Europe/Zagreb", "HU": "Europe/Budapest", "IE": "Europe/Dublin",
77
+ "IE_SEM": "Europe/Dublin", "IT": "Europe/Rome", "IT_NORTH": "Europe/Rome",
78
+ "IT_CNOR": "Europe/Rome", "IT_CSUD": "Europe/Rome", "IT_SUD": "Europe/Rome",
79
+ "IT_SICI": "Europe/Rome", "IT_SARD": "Europe/Rome", "LT": "Europe/Vilnius",
80
+ "LU": "Europe/Luxembourg", "LV": "Europe/Riga", "ME": "Europe/Podgorica",
81
+ "MK": "Europe/Skopje", "MT": "Europe/Malta", "NL": "Europe/Amsterdam",
82
+ "NO": "Europe/Oslo", "NO_1": "Europe/Oslo", "NO_2": "Europe/Oslo",
83
+ "NO_3": "Europe/Oslo", "NO_4": "Europe/Oslo", "NO_5": "Europe/Oslo",
84
+ "PL": "Europe/Warsaw", "PT": "Europe/Lisbon", "RO": "Europe/Bucharest",
85
+ "RS": "Europe/Belgrade", "SE": "Europe/Stockholm", "SE_1": "Europe/Stockholm",
86
+ "SE_2": "Europe/Stockholm", "SE_3": "Europe/Stockholm", "SE_4": "Europe/Stockholm",
87
+ "SI": "Europe/Ljubljana", "SK": "Europe/Bratislava", "TR": "Europe/Istanbul",
88
+ "UA": "Europe/Kyiv", "UK": "Europe/London", "XK": "Europe/Belgrade",
89
+ }
90
+
67
91
  # ISO code → human-readable country/area name
68
92
  COUNTRY_NAMES: dict[str, str] = {
69
93
  "AL": "Albania",
entsoe/cli/_output.py CHANGED
@@ -34,7 +34,10 @@ def output(df, format: str, title: str = "", output_path: str | None = None):
34
34
  typer.echo(text)
35
35
 
36
36
  elif format == "json":
37
- text = df.to_json(orient="records", indent=2, date_format="iso")
37
+ display = df.copy()
38
+ if "timestamp" in display:
39
+ display["timestamp"] = display["timestamp"].map(lambda value: value.isoformat())
40
+ text = display.to_json(orient="records", indent=2)
38
41
  if output_path:
39
42
  with open(output_path, "w") as f:
40
43
  f.write(text)
@@ -72,7 +75,10 @@ def render_result(result, format: str, output_path: str | None) -> None:
72
75
  if format == "csv":
73
76
  text = result.to_csv()
74
77
  elif format == "json":
75
- text = result.to_json(orient="records", indent=2, date_format="iso")
78
+ display = result.copy()
79
+ if "timestamp" in display:
80
+ display["timestamp"] = display["timestamp"].map(lambda value: value.isoformat())
81
+ text = display.to_json(orient="records", indent=2)
76
82
  else:
77
83
  table = Table()
78
84
  idx_name = result.index.name or ""
entsoe/cli/app.py CHANGED
@@ -6,7 +6,7 @@ from typing import Optional
6
6
 
7
7
  import typer
8
8
 
9
- from entsoe.cli.config import get_api_key
9
+ from entsoe.cli.config import get_api_key, get_config
10
10
 
11
11
  app = typer.Typer(
12
12
  name="entsoe",
@@ -15,7 +15,7 @@ app = typer.Typer(
15
15
  )
16
16
 
17
17
 
18
- def get_client(api_key: str | None = None):
18
+ def get_client(api_key: str | None = None, output_tz: str | None = None):
19
19
  """Lazy import + construct client."""
20
20
  from entsoe.client import ENTSOEClient
21
21
 
@@ -26,7 +26,8 @@ def get_client(api_key: str | None = None):
26
26
  err=True,
27
27
  )
28
28
  raise typer.Exit(1)
29
- return ENTSOEClient(api_key=resolved)
29
+ configured_tz = get_config("output-tz") if output_tz is None else output_tz
30
+ return ENTSOEClient(api_key=resolved, output_tz="UTC" if configured_tz is None else configured_tz)
30
31
 
31
32
 
32
33
  # -- Register sub-commands ---------------------------------------------------
entsoe/cli/balancing.py CHANGED
@@ -21,12 +21,13 @@ def prices(
21
21
  format: str = typer.Option("table", "--format", "-f", help="Output format: table, csv, json"),
22
22
  output_path: Optional[str] = typer.Option(None, "--output", "-o", help="Output file path"),
23
23
  api_key: Optional[str] = typer.Option(None, "--api-key", help="ENTSO-E API key"),
24
+ tz: Optional[str] = typer.Option(None, "--tz", help="Output timezone: UTC, local, or IANA name"),
24
25
  ):
25
26
  """Query imbalance prices."""
26
27
  from entsoe.cli.app import get_client
27
28
 
28
29
  s, e = resolve_dates(start, end, period)
29
- client = get_client(api_key)
30
+ client = get_client(api_key, tz)
30
31
  countries = resolve_many_required(country)
31
32
  df = client.balancing.imbalance_prices(s, e, country=countries)
32
33
  output(df, format, title="Imbalance Prices", output_path=output_path)
@@ -41,12 +42,13 @@ def volumes(
41
42
  format: str = typer.Option("table", "--format", "-f", help="Output format: table, csv, json"),
42
43
  output_path: Optional[str] = typer.Option(None, "--output", "-o", help="Output file path"),
43
44
  api_key: Optional[str] = typer.Option(None, "--api-key", help="ENTSO-E API key"),
45
+ tz: Optional[str] = typer.Option(None, "--tz", help="Output timezone: UTC, local, or IANA name"),
44
46
  ):
45
47
  """Query imbalance volumes."""
46
48
  from entsoe.cli.app import get_client
47
49
 
48
50
  s, e = resolve_dates(start, end, period)
49
- client = get_client(api_key)
51
+ client = get_client(api_key, tz)
50
52
  countries = resolve_many_required(country)
51
53
  df = client.balancing.imbalance_volumes(s, e, country=countries)
52
54
  output(df, format, title="Imbalance Volumes", output_path=output_path)
entsoe/cli/config_cmd.py CHANGED
@@ -9,12 +9,16 @@ config_app = typer.Typer(no_args_is_help=True)
9
9
 
10
10
  @config_app.command("set")
11
11
  def config_set(
12
- key: str = typer.Argument(..., help="Configuration key (e.g., 'api-key')"),
12
+ key: str = typer.Argument(..., help="Configuration key (api-key or output-tz)"),
13
13
  value: str = typer.Argument(..., help="Configuration value"),
14
14
  ):
15
15
  """Set a configuration value."""
16
16
  from entsoe.cli.config import set_config
17
17
 
18
+ if key == "output-tz":
19
+ from entsoe.namespaces._base import validate_output_tz
20
+ validate_output_tz(value)
21
+
18
22
  set_config(key, value)
19
23
  typer.echo(f"Set {key} = {'***' if 'key' in key.lower() else value}")
20
24
 
entsoe/cli/exec_cmd.py CHANGED
@@ -62,6 +62,7 @@ def exec_prices(
62
62
  format: str = typer.Option("table", "--format", "-f", help="Output format: table, csv, json"),
63
63
  output_path: Optional[str] = typer.Option(None, "--output", "-o", help="Output file path"),
64
64
  api_key: Optional[str] = typer.Option(None, "--api-key", help="ENTSO-E API key"),
65
+ tz: Optional[str] = typer.Option(None, "--tz", help="Output timezone: UTC, local, or IANA name"),
65
66
  ):
66
67
  """Fetch price data and evaluate a Python expression.
67
68
 
@@ -73,7 +74,7 @@ def exec_prices(
73
74
 
74
75
  method_name = _resolve_method(method, _PRICES_METHODS)
75
76
  s, e = resolve_dates(start, end, period)
76
- client = get_client(api_key)
77
+ client = get_client(api_key, tz)
77
78
  fn = getattr(client.prices, method_name)
78
79
  df = fn(s, e, country=resolve_many_required(country))
79
80
  _eval_and_render(df, expr, format, output_path)
@@ -96,6 +97,7 @@ def exec_load(
96
97
  format: str = typer.Option("table", "--format", "-f", help="Output format: table, csv, json"),
97
98
  output_path: Optional[str] = typer.Option(None, "--output", "-o", help="Output file path"),
98
99
  api_key: Optional[str] = typer.Option(None, "--api-key", help="ENTSO-E API key"),
100
+ tz: Optional[str] = typer.Option(None, "--tz", help="Output timezone: UTC, local, or IANA name"),
99
101
  ):
100
102
  """Fetch load data and evaluate a Python expression.
101
103
 
@@ -107,7 +109,7 @@ def exec_load(
107
109
 
108
110
  method_name = _resolve_method(method, _LOAD_METHODS)
109
111
  s, e = resolve_dates(start, end, period)
110
- client = get_client(api_key)
112
+ client = get_client(api_key, tz)
111
113
  fn = getattr(client.load, method_name)
112
114
  df = fn(s, e, country=resolve_many_required(country))
113
115
  _eval_and_render(df, expr, format, output_path)
@@ -136,6 +138,7 @@ def exec_generation(
136
138
  format: str = typer.Option("table", "--format", "-f", help="Output format: table, csv, json"),
137
139
  output_path: Optional[str] = typer.Option(None, "--output", "-o", help="Output file path"),
138
140
  api_key: Optional[str] = typer.Option(None, "--api-key", help="ENTSO-E API key"),
141
+ tz: Optional[str] = typer.Option(None, "--tz", help="Output timezone: UTC, local, or IANA name"),
139
142
  ):
140
143
  """Fetch generation data and evaluate a Python expression.
141
144
 
@@ -147,7 +150,7 @@ def exec_generation(
147
150
 
148
151
  method_name = _resolve_method(method, _GENERATION_METHODS)
149
152
  s, e = resolve_dates(start, end, period)
150
- client = get_client(api_key)
153
+ client = get_client(api_key, tz)
151
154
  fn = getattr(client.generation, method_name)
152
155
  df = fn(s, e, country=resolve_many_required(country), psr_type=resolve_many(psr))
153
156
  _eval_and_render(df, expr, format, output_path)
@@ -176,6 +179,7 @@ def exec_transmission(
176
179
  format: str = typer.Option("table", "--format", "-f", help="Output format: table, csv, json"),
177
180
  output_path: Optional[str] = typer.Option(None, "--output", "-o", help="Output file path"),
178
181
  api_key: Optional[str] = typer.Option(None, "--api-key", help="ENTSO-E API key"),
182
+ tz: Optional[str] = typer.Option(None, "--tz", help="Output timezone: UTC, local, or IANA name"),
179
183
  ):
180
184
  """Fetch transmission data and evaluate a Python expression.
181
185
 
@@ -200,7 +204,7 @@ def exec_transmission(
200
204
  typer.echo("Error: Provide --from/--to or --border.", err=True)
201
205
  raise typer.Exit(1)
202
206
 
203
- client = get_client(api_key)
207
+ client = get_client(api_key, tz)
204
208
  fn = getattr(client.transmission, method_name)
205
209
  df = fn(s, e, **kwargs)
206
210
  _eval_and_render(df, expr, format, output_path)
@@ -223,6 +227,7 @@ def exec_balancing(
223
227
  format: str = typer.Option("table", "--format", "-f", help="Output format: table, csv, json"),
224
228
  output_path: Optional[str] = typer.Option(None, "--output", "-o", help="Output file path"),
225
229
  api_key: Optional[str] = typer.Option(None, "--api-key", help="ENTSO-E API key"),
230
+ tz: Optional[str] = typer.Option(None, "--tz", help="Output timezone: UTC, local, or IANA name"),
226
231
  ):
227
232
  """Fetch balancing data and evaluate a Python expression.
228
233
 
@@ -234,7 +239,7 @@ def exec_balancing(
234
239
 
235
240
  method_name = _resolve_method(method, _BALANCING_METHODS)
236
241
  s, e = resolve_dates(start, end, period)
237
- client = get_client(api_key)
242
+ client = get_client(api_key, tz)
238
243
  fn = getattr(client.balancing, method_name)
239
244
  df = fn(s, e, country=resolve_many_required(country))
240
245
  _eval_and_render(df, expr, format, output_path)
entsoe/cli/generation.py CHANGED
@@ -22,12 +22,13 @@ def actual(
22
22
  format: str = typer.Option("table", "--format", "-f", help="Output format: table, csv, json"),
23
23
  output_path: Optional[str] = typer.Option(None, "--output", "-o", help="Output file path"),
24
24
  api_key: Optional[str] = typer.Option(None, "--api-key", help="ENTSO-E API key"),
25
+ tz: Optional[str] = typer.Option(None, "--tz", help="Output timezone: UTC, local, or IANA name"),
25
26
  ):
26
27
  """Query actual generation output per type."""
27
28
  from entsoe.cli.app import get_client
28
29
 
29
30
  s, e = resolve_dates(start, end, period)
30
- client = get_client(api_key)
31
+ client = get_client(api_key, tz)
31
32
  df = client.generation.actual(s, e, country=resolve_many_required(country), psr_type=resolve_many(psr))
32
33
  output(df, format, title="Actual Generation", output_path=output_path)
33
34
 
@@ -42,12 +43,13 @@ def forecast(
42
43
  format: str = typer.Option("table", "--format", "-f", help="Output format: table, csv, json"),
43
44
  output_path: Optional[str] = typer.Option(None, "--output", "-o", help="Output file path"),
44
45
  api_key: Optional[str] = typer.Option(None, "--api-key", help="ENTSO-E API key"),
46
+ tz: Optional[str] = typer.Option(None, "--tz", help="Output timezone: UTC, local, or IANA name"),
45
47
  ):
46
48
  """Query day-ahead generation forecast (wind/solar)."""
47
49
  from entsoe.cli.app import get_client
48
50
 
49
51
  s, e = resolve_dates(start, end, period)
50
- client = get_client(api_key)
52
+ client = get_client(api_key, tz)
51
53
  df = client.generation.forecast(s, e, country=resolve_many_required(country), psr_type=resolve_many(psr))
52
54
  output(df, format, title="Generation Forecast", output_path=output_path)
53
55
 
@@ -62,12 +64,13 @@ def capacity(
62
64
  format: str = typer.Option("table", "--format", "-f", help="Output format: table, csv, json"),
63
65
  output_path: Optional[str] = typer.Option(None, "--output", "-o", help="Output file path"),
64
66
  api_key: Optional[str] = typer.Option(None, "--api-key", help="ENTSO-E API key"),
67
+ tz: Optional[str] = typer.Option(None, "--tz", help="Output timezone: UTC, local, or IANA name"),
65
68
  ):
66
69
  """Query installed generation capacity per type."""
67
70
  from entsoe.cli.app import get_client
68
71
 
69
72
  s, e = resolve_dates(start, end, period)
70
- client = get_client(api_key)
73
+ client = get_client(api_key, tz)
71
74
  df = client.generation.installed_capacity(s, e, country=resolve_many_required(country), psr_type=resolve_many(psr))
72
75
  output(df, format, title="Installed Capacity", output_path=output_path)
73
76
 
@@ -82,12 +85,13 @@ def per_plant(
82
85
  format: str = typer.Option("table", "--format", "-f", help="Output format: table, csv, json"),
83
86
  output_path: Optional[str] = typer.Option(None, "--output", "-o", help="Output file path"),
84
87
  api_key: Optional[str] = typer.Option(None, "--api-key", help="ENTSO-E API key"),
88
+ tz: Optional[str] = typer.Option(None, "--tz", help="Output timezone: UTC, local, or IANA name"),
85
89
  ):
86
90
  """Query actual generation per production unit."""
87
91
  from entsoe.cli.app import get_client
88
92
 
89
93
  s, e = resolve_dates(start, end, period)
90
- client = get_client(api_key)
94
+ client = get_client(api_key, tz)
91
95
  df = client.generation.per_plant(s, e, country=resolve_many_required(country), psr_type=resolve_many(psr))
92
96
  output(df, format, title="Generation Per Plant", output_path=output_path)
93
97
 
entsoe/cli/load.py CHANGED
@@ -21,12 +21,13 @@ def actual(
21
21
  format: str = typer.Option("table", "--format", "-f", help="Output format: table, csv, json"),
22
22
  output_path: Optional[str] = typer.Option(None, "--output", "-o", help="Output file path"),
23
23
  api_key: Optional[str] = typer.Option(None, "--api-key", help="ENTSO-E API key"),
24
+ tz: Optional[str] = typer.Option(None, "--tz", help="Output timezone: UTC, local, or IANA name"),
24
25
  ):
25
26
  """Query actual total system load."""
26
27
  from entsoe.cli.app import get_client
27
28
 
28
29
  s, e = resolve_dates(start, end, period)
29
- client = get_client(api_key)
30
+ client = get_client(api_key, tz)
30
31
  countries = resolve_many_required(country)
31
32
  df = client.load.actual(s, e, country=countries)
32
33
  output(df, format, title="Actual Load", output_path=output_path)
@@ -41,12 +42,13 @@ def forecast(
41
42
  format: str = typer.Option("table", "--format", "-f", help="Output format: table, csv, json"),
42
43
  output_path: Optional[str] = typer.Option(None, "--output", "-o", help="Output file path"),
43
44
  api_key: Optional[str] = typer.Option(None, "--api-key", help="ENTSO-E API key"),
45
+ tz: Optional[str] = typer.Option(None, "--tz", help="Output timezone: UTC, local, or IANA name"),
44
46
  ):
45
47
  """Query day-ahead load forecast."""
46
48
  from entsoe.cli.app import get_client
47
49
 
48
50
  s, e = resolve_dates(start, end, period)
49
- client = get_client(api_key)
51
+ client = get_client(api_key, tz)
50
52
  countries = resolve_many_required(country)
51
53
  df = client.load.forecast(s, e, country=countries)
52
54
  output(df, format, title="Load Forecast", output_path=output_path)
entsoe/cli/prices.py CHANGED
@@ -22,12 +22,13 @@ def day_ahead(
22
22
  format: str = typer.Option("table", "--format", "-f", help="Output format: table, csv, json"),
23
23
  output_path: Optional[str] = typer.Option(None, "--output", "-o", help="Output file path"),
24
24
  api_key: Optional[str] = typer.Option(None, "--api-key", help="ENTSO-E API key"),
25
+ tz: Optional[str] = typer.Option(None, "--tz", help="Output timezone: UTC, local, or IANA name"),
25
26
  ):
26
27
  """Query day-ahead electricity prices."""
27
28
  from entsoe.cli.app import get_client
28
29
 
29
30
  s, e = resolve_dates(start, end, period)
30
- client = get_client(api_key)
31
+ client = get_client(api_key, tz)
31
32
  countries = resolve_many_required(country)
32
33
  df = client.prices.day_ahead(s, e, country=countries, sequence=sequence)
33
34
  output(df, format, title="Day-Ahead Prices", output_path=output_path)
@@ -43,13 +43,14 @@ def flows(
43
43
  format: str = typer.Option("table", "--format", "-f", help="Output format: table, csv, json"),
44
44
  output_path: Optional[str] = typer.Option(None, "--output", "-o", help="Output file path"),
45
45
  api_key: Optional[str] = typer.Option(None, "--api-key", help="ENTSO-E API key"),
46
+ tz: Optional[str] = typer.Option(None, "--tz", help="Output timezone: UTC, local, or IANA name"),
46
47
  ):
47
48
  """Query physical cross-border flows."""
48
49
  from entsoe.cli.app import get_client
49
50
 
50
51
  s, e = resolve_dates(start, end, period)
51
52
  kwargs = _resolve_borders_or_pairs(country_from, country_to, border)
52
- client = get_client(api_key)
53
+ client = get_client(api_key, tz)
53
54
  df = client.transmission.crossborder_flows(s, e, **kwargs)
54
55
  output(df, format, title="Cross-Border Flows", output_path=output_path)
55
56
 
@@ -65,13 +66,14 @@ def exchanges(
65
66
  format: str = typer.Option("table", "--format", "-f", help="Output format: table, csv, json"),
66
67
  output_path: Optional[str] = typer.Option(None, "--output", "-o", help="Output file path"),
67
68
  api_key: Optional[str] = typer.Option(None, "--api-key", help="ENTSO-E API key"),
69
+ tz: Optional[str] = typer.Option(None, "--tz", help="Output timezone: UTC, local, or IANA name"),
68
70
  ):
69
71
  """Query scheduled commercial exchanges (day-ahead)."""
70
72
  from entsoe.cli.app import get_client
71
73
 
72
74
  s, e = resolve_dates(start, end, period)
73
75
  kwargs = _resolve_borders_or_pairs(country_from, country_to, border)
74
- client = get_client(api_key)
76
+ client = get_client(api_key, tz)
75
77
  df = client.transmission.scheduled_exchanges(s, e, **kwargs)
76
78
  output(df, format, title="Scheduled Exchanges", output_path=output_path)
77
79
 
@@ -87,13 +89,14 @@ def capacity(
87
89
  format: str = typer.Option("table", "--format", "-f", help="Output format: table, csv, json"),
88
90
  output_path: Optional[str] = typer.Option(None, "--output", "-o", help="Output file path"),
89
91
  api_key: Optional[str] = typer.Option(None, "--api-key", help="ENTSO-E API key"),
92
+ tz: Optional[str] = typer.Option(None, "--tz", help="Output timezone: UTC, local, or IANA name"),
90
93
  ):
91
94
  """Query day-ahead net transfer capacity."""
92
95
  from entsoe.cli.app import get_client
93
96
 
94
97
  s, e = resolve_dates(start, end, period)
95
98
  kwargs = _resolve_borders_or_pairs(country_from, country_to, border)
96
- client = get_client(api_key)
99
+ client = get_client(api_key, tz)
97
100
  df = client.transmission.net_transfer_capacity(s, e, **kwargs)
98
101
  output(df, format, title="Net Transfer Capacity", output_path=output_path)
99
102
 
entsoe/client.py CHANGED
@@ -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 .namespaces._base import validate_output_tz
10
11
  from .namespaces import (
11
12
  BalancingNamespace,
12
13
  GenerationNamespace,
@@ -38,6 +39,8 @@ class ENTSOEClient:
38
39
 
39
40
  # Override default timezone
40
41
  client = ENTSOEClient(tz="UTC")
42
+ client = ENTSOEClient(output_tz="local") # results use each zone's local time
43
+ client = ENTSOEClient(output_tz="Europe/Madrid") # fixed output zone
41
44
 
42
45
  # Disable cache
43
46
  client = ENTSOEClient(cache=False)
@@ -60,6 +63,7 @@ class ENTSOEClient:
60
63
  cache: bool = True,
61
64
  cache_dir: str | Path | None = None,
62
65
  cache_recent_ttl: int = 48,
66
+ output_tz: str = "UTC",
63
67
  ) -> None:
64
68
  """Initialize the client.
65
69
 
@@ -71,10 +75,13 @@ class ENTSOEClient:
71
75
  cache: Whether to enable local parquet caching. Defaults to True.
72
76
  cache_dir: Custom cache directory. Defaults to ``~/.cache/entsoe/``.
73
77
  cache_recent_ttl: Hours before data is considered final (default 48).
78
+ output_tz: Result timezone: ``UTC`` (default), ``local`` for the requested area, or an IANA name.
74
79
 
75
80
  Raises:
76
81
  ValueError: If no API key is found.
82
+ InvalidParameterError: If output_tz is not UTC, local, or a valid IANA timezone.
77
83
  """
84
+ output_tz = validate_output_tz(output_tz)
78
85
  resolved_key = api_key or os.environ.get("ENTSOE_API_KEY")
79
86
  if not resolved_key:
80
87
  raise ValueError(
@@ -94,11 +101,11 @@ class ENTSOEClient:
94
101
 
95
102
  cache_store = CacheStore(cache_config) if cache else None
96
103
 
97
- self.load = LoadNamespace(http, tz=tz, cache=cache_store)
98
- self.prices = PricesNamespace(http, tz=tz, cache=cache_store)
99
- self.generation = GenerationNamespace(http, tz=tz, cache=cache_store)
100
- self.transmission = TransmissionNamespace(http, tz=tz, cache=cache_store)
101
- self.balancing = BalancingNamespace(http, tz=tz, cache=cache_store)
104
+ self.load = LoadNamespace(http, tz=tz, output_tz=output_tz, cache=cache_store)
105
+ self.prices = PricesNamespace(http, tz=tz, output_tz=output_tz, cache=cache_store)
106
+ self.generation = GenerationNamespace(http, tz=tz, output_tz=output_tz, cache=cache_store)
107
+ self.transmission = TransmissionNamespace(http, tz=tz, output_tz=output_tz, cache=cache_store)
108
+ self.balancing = BalancingNamespace(http, tz=tz, output_tz=output_tz, cache=cache_store)
102
109
 
103
110
  # Expose for CLI cache commands
104
111
  self._cache = cache_store
@@ -3,12 +3,13 @@
3
3
  from __future__ import annotations
4
4
 
5
5
  import logging
6
+ from zoneinfo import ZoneInfo, ZoneInfoNotFoundError
6
7
  from typing import TYPE_CHECKING, Callable, Optional, Union
7
8
 
8
9
  import pandas as pd
9
10
 
10
11
  from ..exceptions import InvalidParameterError
11
- from .._mappings import country_name, lookup_area
12
+ from .._mappings import AREA_TZ, EIC_TO_ISO, country_name, lookup_area
12
13
 
13
14
  if TYPE_CHECKING:
14
15
  import xml.etree.ElementTree as ET
@@ -28,6 +29,52 @@ OneOrMany = Union[str, list[str]]
28
29
  TimeSeriesFilter = Optional[Callable[["ET.Element"], bool]]
29
30
 
30
31
 
32
+ def validate_output_tz(value: str) -> str:
33
+ """Validate an output timezone without changing its spelling."""
34
+ if value == "local":
35
+ return value
36
+ if not isinstance(value, str):
37
+ raise InvalidParameterError("output_tz must be 'UTC', 'local', or an IANA timezone.")
38
+ try:
39
+ ZoneInfo(value)
40
+ except (ZoneInfoNotFoundError, ValueError):
41
+ raise InvalidParameterError(
42
+ f"Invalid output_tz {value!r}; use 'UTC', 'local', or an IANA timezone."
43
+ ) from None
44
+ return value
45
+
46
+
47
+ def _to_output_tz(df: pd.DataFrame, zones: OneOrMany, output_tz: str) -> pd.DataFrame:
48
+ """Convert a UTC result at the namespace boundary without mutating cached data.
49
+
50
+ For cross-border requests, callers pass the first in_domain zone; local time then follows that zone.
51
+ """
52
+ target = validate_output_tz(output_tz)
53
+ if target == "UTC":
54
+ return df
55
+ if target == "local":
56
+ requested = [zones] if isinstance(zones, str) else zones
57
+ timezones = [AREA_TZ[EIC_TO_ISO[lookup_area(zone)]] for zone in requested]
58
+ instants = df["timestamp"].drop_duplicates() if "timestamp" in df else []
59
+ if not len(instants):
60
+ instants = [pd.Timestamp("2024-01-01", tz="UTC"), pd.Timestamp("2024-07-01", tz="UTC")]
61
+ signatures = {
62
+ zone: tuple(instant.to_pydatetime().astimezone(ZoneInfo(zone)).utcoffset() for instant in instants)
63
+ for zone in set(timezones)
64
+ }
65
+ if len(set(signatures.values())) != 1:
66
+ raise InvalidParameterError(
67
+ f"Local output spans different timezones: {', '.join(sorted(set(timezones)))}. "
68
+ "Use 'UTC' or a fixed IANA timezone."
69
+ )
70
+ target = timezones[0]
71
+ if df.empty or "timestamp" not in df:
72
+ return df.copy()
73
+ result = df.copy()
74
+ result["timestamp"] = result["timestamp"].dt.tz_convert(target)
75
+ return result
76
+
77
+
31
78
  class BaseNamespace:
32
79
  """Base class for domain namespaces.
33
80
 
@@ -40,12 +87,17 @@ class BaseNamespace:
40
87
  http: HttpClient,
41
88
  *,
42
89
  tz: str = "Europe/Brussels",
90
+ output_tz: str = "UTC",
43
91
  cache: CacheStore | None = None,
44
92
  ) -> None:
45
93
  self._http = http
46
94
  self._tz = tz
95
+ self._output_tz = validate_output_tz(output_tz)
47
96
  self._cache = cache
48
97
 
98
+ def _output(self, df: pd.DataFrame, zones: OneOrMany, output_tz: str | None) -> pd.DataFrame:
99
+ return _to_output_tz(df, zones, self._output_tz if output_tz is None else output_tz)
100
+
49
101
  # ------------------------------------------------------------------
50
102
  # Timestamp coercion
51
103
  # ------------------------------------------------------------------
@@ -20,6 +20,8 @@ class BalancingNamespace(BaseNamespace):
20
20
  start: Timestamp,
21
21
  end: Timestamp,
22
22
  country: OneOrMany,
23
+ *,
24
+ output_tz: str | None = None,
23
25
  ) -> pd.DataFrame:
24
26
  """Query imbalance prices.
25
27
 
@@ -29,6 +31,8 @@ class BalancingNamespace(BaseNamespace):
29
31
  country: Country code or list of codes (e.g., "FR" or ["FR", "NL"]).
30
32
  When a list is passed, results include a ``country`` column.
31
33
 
34
+ output_tz: Override the client result timezone (UTC, local, or IANA name).
35
+
32
36
  Returns:
33
37
  DataFrame with columns: timestamp, value (EUR/MWh).
34
38
  """
@@ -39,15 +43,17 @@ class BalancingNamespace(BaseNamespace):
39
43
  "controlArea_Domain": self._area(code),
40
44
  }
41
45
 
42
- return self._query_multi_cached(
46
+ return self._output(self._query_multi_cached(
43
47
  "balancing", "imbalance_prices", _params, country, start, end,
44
- )
48
+ ), country, output_tz)
45
49
 
46
50
  def imbalance_volumes(
47
51
  self,
48
52
  start: Timestamp,
49
53
  end: Timestamp,
50
54
  country: OneOrMany,
55
+ *,
56
+ output_tz: str | None = None,
51
57
  ) -> pd.DataFrame:
52
58
  """Query imbalance volumes.
53
59
 
@@ -57,6 +63,8 @@ class BalancingNamespace(BaseNamespace):
57
63
  country: Country code or list of codes (e.g., "FR" or ["FR", "NL"]).
58
64
  When a list is passed, results include a ``country`` column.
59
65
 
66
+ output_tz: Override the client result timezone (UTC, local, or IANA name).
67
+
60
68
  Returns:
61
69
  DataFrame with columns: timestamp, value (MW).
62
70
  """
@@ -67,6 +75,6 @@ class BalancingNamespace(BaseNamespace):
67
75
  "controlArea_Domain": self._area(code),
68
76
  }
69
77
 
70
- return self._query_multi_cached(
78
+ return self._output(self._query_multi_cached(
71
79
  "balancing", "imbalance_volumes", _params, country, start, end,
72
- )
80
+ ), country, output_tz)
@@ -28,6 +28,7 @@ class GenerationNamespace(BaseNamespace):
28
28
  psr_type: OneOrMany | None,
29
29
  *,
30
30
  cache_topic: str,
31
+ output_tz: str | None,
31
32
  ) -> pd.DataFrame:
32
33
  """Shared logic for generation queries with country + psr_type multi-support."""
33
34
 
@@ -67,7 +68,7 @@ class GenerationNamespace(BaseNamespace):
67
68
  from .._mappings import country_name
68
69
  sub_df["country"] = country_name(code)
69
70
  frames.append(sub_df)
70
- return pd.concat(frames, ignore_index=True)
71
+ return self._output(pd.concat(frames, ignore_index=True), country, output_tz)
71
72
 
72
73
  # Standard case: single or no psr_type filter
73
74
  df = self._query_multi_cached(
@@ -81,7 +82,7 @@ class GenerationNamespace(BaseNamespace):
81
82
  resolved_name = psr_name(psr_type)
82
83
  df = df[df[pivot_col] == resolved_name].reset_index(drop=True)
83
84
 
84
- return df
85
+ return self._output(df, country, output_tz)
85
86
 
86
87
  def actual(
87
88
  self,
@@ -89,6 +90,8 @@ class GenerationNamespace(BaseNamespace):
89
90
  end: Timestamp,
90
91
  country: OneOrMany,
91
92
  psr_type: OneOrMany | None = None,
93
+ *,
94
+ output_tz: str | None = None,
92
95
  ) -> pd.DataFrame:
93
96
  """Query actual generation output per type.
94
97
 
@@ -101,11 +104,13 @@ class GenerationNamespace(BaseNamespace):
101
104
  (e.g., "solar", ["solar", "wind_onshore"], or "B16").
102
105
  If None, returns all types.
103
106
 
107
+ output_tz: Override the client result timezone (UTC, local, or IANA name).
108
+
104
109
  Returns:
105
110
  DataFrame with columns: timestamp, value (MW), psr_type.
106
111
  """
107
112
  return self._gen_query("A75", "A16", start, end, country, psr_type,
108
- cache_topic="actual")
113
+ cache_topic="actual", output_tz=output_tz)
109
114
 
110
115
  def forecast(
111
116
  self,
@@ -113,6 +118,8 @@ class GenerationNamespace(BaseNamespace):
113
118
  end: Timestamp,
114
119
  country: OneOrMany,
115
120
  psr_type: OneOrMany | None = None,
121
+ *,
122
+ output_tz: str | None = None,
116
123
  ) -> pd.DataFrame:
117
124
  """Query day-ahead generation forecast (wind and solar).
118
125
 
@@ -123,11 +130,13 @@ class GenerationNamespace(BaseNamespace):
123
130
  When a list is passed, results include a ``country`` column.
124
131
  psr_type: PSR type code/name, list of codes/names, or None.
125
132
 
133
+ output_tz: Override the client result timezone (UTC, local, or IANA name).
134
+
126
135
  Returns:
127
136
  DataFrame with columns: timestamp, value (MW), psr_type.
128
137
  """
129
138
  return self._gen_query("A69", "A01", start, end, country, psr_type,
130
- cache_topic="forecast")
139
+ cache_topic="forecast", output_tz=output_tz)
131
140
 
132
141
  def installed_capacity(
133
142
  self,
@@ -135,6 +144,8 @@ class GenerationNamespace(BaseNamespace):
135
144
  end: Timestamp,
136
145
  country: OneOrMany,
137
146
  psr_type: OneOrMany | None = None,
147
+ *,
148
+ output_tz: str | None = None,
138
149
  ) -> pd.DataFrame:
139
150
  """Query installed generation capacity per type.
140
151
 
@@ -145,11 +156,13 @@ class GenerationNamespace(BaseNamespace):
145
156
  When a list is passed, results include a ``country`` column.
146
157
  psr_type: PSR type code/name, list of codes/names, or None.
147
158
 
159
+ output_tz: Override the client result timezone (UTC, local, or IANA name).
160
+
148
161
  Returns:
149
162
  DataFrame with columns: timestamp, value (MW), psr_type.
150
163
  """
151
164
  return self._gen_query("A68", "A33", start, end, country, psr_type,
152
- cache_topic="capacity")
165
+ cache_topic="capacity", output_tz=output_tz)
153
166
 
154
167
  def per_plant(
155
168
  self,
@@ -157,6 +170,8 @@ class GenerationNamespace(BaseNamespace):
157
170
  end: Timestamp,
158
171
  country: OneOrMany,
159
172
  psr_type: OneOrMany | None = None,
173
+ *,
174
+ output_tz: str | None = None,
160
175
  ) -> pd.DataFrame:
161
176
  """Query actual generation per production unit.
162
177
 
@@ -167,9 +182,11 @@ class GenerationNamespace(BaseNamespace):
167
182
  When a list is passed, results include a ``country`` column.
168
183
  psr_type: PSR type code/name, list of codes/names, or None.
169
184
 
185
+ output_tz: Override the client result timezone (UTC, local, or IANA name).
186
+
170
187
  Returns:
171
188
  DataFrame with columns: timestamp, value (MW), psr_type,
172
189
  and additional unit identifiers.
173
190
  """
174
191
  return self._gen_query("A73", "A16", start, end, country, psr_type,
175
- cache_topic="per_plant")
192
+ cache_topic="per_plant", output_tz=output_tz)
entsoe/namespaces/load.py CHANGED
@@ -20,6 +20,8 @@ class LoadNamespace(BaseNamespace):
20
20
  start: Timestamp,
21
21
  end: Timestamp,
22
22
  country: OneOrMany,
23
+ *,
24
+ output_tz: str | None = None,
23
25
  ) -> pd.DataFrame:
24
26
  """Query actual total system load.
25
27
 
@@ -29,6 +31,8 @@ class LoadNamespace(BaseNamespace):
29
31
  country: Country code or list of codes (e.g., "FR" or ["FR", "ES"]).
30
32
  When a list is passed, results include a ``country`` column.
31
33
 
34
+ output_tz: Override the client result timezone (UTC, local, or IANA name).
35
+
32
36
  Returns:
33
37
  DataFrame with columns: timestamp, value (MW).
34
38
  """
@@ -40,15 +44,17 @@ class LoadNamespace(BaseNamespace):
40
44
  "outBiddingZone_Domain": self._area(code),
41
45
  }
42
46
 
43
- return self._query_multi_cached(
47
+ return self._output(self._query_multi_cached(
44
48
  "load", "actual", _params, country, start, end,
45
- )
49
+ ), country, output_tz)
46
50
 
47
51
  def forecast(
48
52
  self,
49
53
  start: Timestamp,
50
54
  end: Timestamp,
51
55
  country: OneOrMany,
56
+ *,
57
+ output_tz: str | None = None,
52
58
  ) -> pd.DataFrame:
53
59
  """Query day-ahead load forecast.
54
60
 
@@ -58,6 +64,8 @@ class LoadNamespace(BaseNamespace):
58
64
  country: Country code or list of codes (e.g., "FR" or ["FR", "ES"]).
59
65
  When a list is passed, results include a ``country`` column.
60
66
 
67
+ output_tz: Override the client result timezone (UTC, local, or IANA name).
68
+
61
69
  Returns:
62
70
  DataFrame with columns: timestamp, value (MW).
63
71
  """
@@ -69,6 +77,6 @@ class LoadNamespace(BaseNamespace):
69
77
  "outBiddingZone_Domain": self._area(code),
70
78
  }
71
79
 
72
- return self._query_multi_cached(
80
+ return self._output(self._query_multi_cached(
73
81
  "load", "forecast", _params, country, start, end,
74
- )
82
+ ), country, output_tz)
@@ -22,6 +22,8 @@ class PricesNamespace(BaseNamespace):
22
22
  end: Timestamp,
23
23
  country: OneOrMany,
24
24
  sequence: int = 1,
25
+ *,
26
+ output_tz: str | None = None,
25
27
  ) -> pd.DataFrame:
26
28
  """Query day-ahead electricity prices.
27
29
 
@@ -40,6 +42,8 @@ class PricesNamespace(BaseNamespace):
40
42
  DE_LU and AT. Zones that publish a single auction without a
41
43
  sequence count as ``1``.
42
44
 
45
+ output_tz: Override the client result timezone (UTC, local, or IANA name).
46
+
43
47
  Returns:
44
48
  DataFrame with columns: timestamp, value (EUR/MWh).
45
49
  Multi-country queries add a ``country`` column.
@@ -58,8 +62,8 @@ class PricesNamespace(BaseNamespace):
58
62
  return False
59
63
  return (timeseries_sequence(ts) or 1) == sequence
60
64
 
61
- return self._query_multi_cached(
65
+ return self._output(self._query_multi_cached(
62
66
  "prices", "day_ahead", _params, country, start, end,
63
67
  ts_filter=_keep,
64
68
  partition_fn=lambda code: code if sequence == 1 else f"{code}.seq{sequence}",
65
- )
69
+ ), country, output_tz)
@@ -32,6 +32,7 @@ class TransmissionNamespace(BaseNamespace):
32
32
  extra_params: dict | None = None,
33
33
  *,
34
34
  cache_topic: str,
35
+ output_tz: str | None,
35
36
  ) -> pd.DataFrame:
36
37
  """Shared logic for transmission queries with multi-value support.
37
38
 
@@ -75,9 +76,9 @@ class TransmissionNamespace(BaseNamespace):
75
76
  "out_Domain": self._area(country_from),
76
77
  **extra,
77
78
  }
78
- return self._query_single_border(
79
+ return self._output(self._query_single_border(
79
80
  cache_topic, country_from, country_to, params, start, end,
80
- )
81
+ ), country_to, output_tz)
81
82
 
82
83
  froms = country_from if is_multi_from else [country_from]
83
84
  tos = country_to if is_multi_to else [country_to]
@@ -92,9 +93,9 @@ class TransmissionNamespace(BaseNamespace):
92
93
  "out_Domain": self._area(cf),
93
94
  **extra,
94
95
  }
95
- return self._query_single_border(
96
+ return self._output(self._query_single_border(
96
97
  cache_topic, cf, ct, params, start, end,
97
- )
98
+ ), ct, output_tz)
98
99
 
99
100
  frames = []
100
101
  for cf, ct in pairs:
@@ -109,7 +110,7 @@ class TransmissionNamespace(BaseNamespace):
109
110
  )
110
111
  df["border"] = f"{country_name(cf)} → {country_name(ct)}"
111
112
  frames.append(df)
112
- return pd.concat(frames, ignore_index=True)
113
+ return self._output(pd.concat(frames, ignore_index=True), pairs[0][1], output_tz)
113
114
 
114
115
  def _query_single_border(
115
116
  self,
@@ -139,6 +140,8 @@ class TransmissionNamespace(BaseNamespace):
139
140
  country_from: OneOrMany | None = None,
140
141
  country_to: OneOrMany | None = None,
141
142
  borders: OneOrMany | None = None,
143
+ *,
144
+ output_tz: str | None = None,
142
145
  ) -> pd.DataFrame:
143
146
  """Query physical cross-border flows.
144
147
 
@@ -153,12 +156,14 @@ class TransmissionNamespace(BaseNamespace):
153
156
  and comma-separated combinations like ``"ES-*,FR-*"``.
154
157
  Cannot be combined with country_from/country_to.
155
158
 
159
+ output_tz: Override the client result timezone. With local, cross-border output follows the first in_domain (importing) zone.
160
+
156
161
  Returns:
157
162
  DataFrame with columns: timestamp, value (MW).
158
163
  """
159
164
  return self._transmission_query(
160
165
  "A11", start, end, country_from, country_to, borders,
161
- cache_topic="crossborder_flows",
166
+ cache_topic="crossborder_flows", output_tz=output_tz,
162
167
  )
163
168
 
164
169
  def scheduled_exchanges(
@@ -168,6 +173,8 @@ class TransmissionNamespace(BaseNamespace):
168
173
  country_from: OneOrMany | None = None,
169
174
  country_to: OneOrMany | None = None,
170
175
  borders: OneOrMany | None = None,
176
+ *,
177
+ output_tz: str | None = None,
171
178
  ) -> pd.DataFrame:
172
179
  """Query scheduled commercial exchanges (day-ahead).
173
180
 
@@ -179,12 +186,14 @@ class TransmissionNamespace(BaseNamespace):
179
186
  When either is a list, results include a ``border`` column.
180
187
  borders: Border spec or list of specs. See :meth:`crossborder_flows`.
181
188
 
189
+ output_tz: Override the client result timezone. With local, cross-border output follows the first in_domain (importing) zone.
190
+
182
191
  Returns:
183
192
  DataFrame with columns: timestamp, value (MW).
184
193
  """
185
194
  return self._transmission_query(
186
195
  "A09", start, end, country_from, country_to, borders,
187
- cache_topic="scheduled_exchanges",
196
+ cache_topic="scheduled_exchanges", output_tz=output_tz,
188
197
  )
189
198
 
190
199
  def net_transfer_capacity(
@@ -194,6 +203,8 @@ class TransmissionNamespace(BaseNamespace):
194
203
  country_from: OneOrMany | None = None,
195
204
  country_to: OneOrMany | None = None,
196
205
  borders: OneOrMany | None = None,
206
+ *,
207
+ output_tz: str | None = None,
197
208
  ) -> pd.DataFrame:
198
209
  """Query day-ahead net transfer capacity.
199
210
 
@@ -205,11 +216,13 @@ class TransmissionNamespace(BaseNamespace):
205
216
  When either is a list, results include a ``border`` column.
206
217
  borders: Border spec or list of specs. See :meth:`crossborder_flows`.
207
218
 
219
+ output_tz: Override the client result timezone. With local, cross-border output follows the first in_domain (importing) zone.
220
+
208
221
  Returns:
209
222
  DataFrame with columns: timestamp, value (MW).
210
223
  """
211
224
  return self._transmission_query(
212
225
  "A61", start, end, country_from, country_to, borders,
213
226
  extra_params={"contract_MarketAgreement.Type": "A01"},
214
- cache_topic="net_transfer_capacity",
227
+ cache_topic="net_transfer_capacity", output_tz=output_tz,
215
228
  )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: python-entsoe
3
- Version: 0.6.3
3
+ Version: 0.7.0
4
4
  Summary: Python client for the ENTSO-E Transparency Platform API
5
5
  Project-URL: Homepage, https://gitlab.com/datons.com/libraries/python-entsoe
6
6
  Project-URL: Repository, https://gitlab.com/datons.com/libraries/python-entsoe
@@ -57,7 +57,7 @@ start = pd.Timestamp("2024-06-01", tz="Europe/Paris")
57
57
  df = client.load.actual(start, "2024-06-08", country="FR")
58
58
  ```
59
59
 
60
- Every method returns a `pandas.DataFrame` with a `timestamp` column (UTC) and a `value` column.
60
+ Every method returns a `pandas.DataFrame` with a timezone-aware `timestamp` column and a `value` column.
61
61
 
62
62
  ## Authentication
63
63
 
@@ -216,7 +216,11 @@ df = client.load.actual("2024-01-01", pd.Timestamp("2024-01-07", tz="UTC"), coun
216
216
  start = pd.Timestamp("2024-01-01") # ← no tz, will error
217
217
  ```
218
218
 
219
- Returned timestamps are always in **UTC**.
219
+ ## Timezones
220
+
221
+ The client `tz` setting interprets input date strings (default `Europe/Brussels`); it does not control returned timestamps. The separate `output_tz` setting controls results: `"UTC"` (default, unchanged behavior), `"local"` (the requested area's timezone), or a fixed IANA timezone such as `"Europe/Madrid"`. Every namespace method also accepts `output_tz=` for one call. The CLI accepts `--tz` on data commands, or `entsoe config set output-tz local` as a persistent default; `--tz` takes precedence.
222
+
223
+ For a multi-area request, `"local"` requires matching clock offsets throughout the returned period (for example, FR and ES); otherwise choose `"UTC"` or a fixed IANA zone. Cross-border results use the first importing (`in_domain`) zone. During the October DST fall-back, local wall-clock times repeat; each row retains its offset, but timestamps cease to be unique if the timezone is stripped.
220
224
 
221
225
  ## Features
222
226
 
@@ -0,0 +1,35 @@
1
+ entsoe/__init__.py,sha256=9qzvMUzoD-CRfX1vTzWIBfpXBMdJ2MgRwJEgQQsw1fA,529
2
+ entsoe/_http.py,sha256=XhZZy059XHh8uAP2Vsm1e7BfRwQcmGLEYdREcgaF3Tk,6608
3
+ entsoe/_mappings.py,sha256=d70uUyGzB1NaJYoUTCdtkRe0N-gt0wuaagNxzb7w4jc,17158
4
+ entsoe/_xml.py,sha256=cJa4_nVIk27O9bCXkp2w-QR2fV3UrH-A80mX54KReVU,8439
5
+ entsoe/cache.py,sha256=3UIuhaSH9LVGk9Ony5eMsk_qOmRzzMEyskQS_cmY020,14547
6
+ entsoe/catalog.py,sha256=FUPg_WqLBkfl5sUgT9m8Bua7IP10NvBsakcndpUOBa0,9733
7
+ entsoe/client.py,sha256=mFqPhpEZxt4rGL98EM9LCOtTAo_xZRgffkAKiPRP4cw,4146
8
+ entsoe/exceptions.py,sha256=vqeu6_LxAtDvJziPnjbH52KV0fm63F8n2Y1lzSNp2Bs,1017
9
+ entsoe/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
+ entsoe/.agents/skills/entsoe/SKILL.md,sha256=JsFECSkfnxyR6iFx55WBBcMJjAOaMu84vhcsPsTVWC0,6452
11
+ entsoe/cli/__init__.py,sha256=qUGXx4zdi8dCQkq3PPPa1sgD3Q6KIhJwWeBfTub4suM,139
12
+ entsoe/cli/_output.py,sha256=bP1KqGtvDBy3Mtm_mZMY2Qp4dzmGWz7hcklKZuS0fno,3239
13
+ entsoe/cli/_resolve.py,sha256=oIUgZ2BF-p3AD2wQQBhkVCBHg8fbhIVFdrvll2sesD8,4799
14
+ entsoe/cli/app.py,sha256=vw5_Pabd7feTeP-Vpt50KVwbg70hFex6z7JNWTem9v0,2252
15
+ entsoe/cli/balancing.py,sha256=sYoyZ8KcU6WXNu_9HZNgehhEjJkockW86D3pHg6XGw8,2964
16
+ entsoe/cli/cache_cmd.py,sha256=ozbQ5apxeLBIjbPsH-Cs5rDOVBVfrzJfDPKv1anLFgY,2255
17
+ entsoe/cli/catalog_cmd.py,sha256=TzkkecSlnlz-f2_BlRqidKN6uTJtSInR0np4BA1rQ5c,5361
18
+ entsoe/cli/config.py,sha256=YB6IeOBGMKahcVJBGUaCN5r1vs6YILv_XbXlcKLxLiU,1663
19
+ entsoe/cli/config_cmd.py,sha256=gduIqUaW13APCUtf5eUc2g0l4i4_xqI5vFDs4-iR-pQ,1053
20
+ entsoe/cli/exec_cmd.py,sha256=9cCtDSCnzY5Z1iDWidY_iJ2fvALFraMFCdbbWqliYb8,11838
21
+ entsoe/cli/generation.py,sha256=TDLXWcA2kH9LGnueegBkKVkOyHTg_iWWNdoa2OV7h2Q,6105
22
+ entsoe/cli/load.py,sha256=ErvHaeZG8TUKdusoG4vWvFU2J8etiHE0G7c5jDqzvGc,2897
23
+ entsoe/cli/prices.py,sha256=3lyCGICm_CIzaVLkfYaGVju76BHbRkxNDTfYbTh5FHw,1835
24
+ entsoe/cli/transmission.py,sha256=oC4qoIQCnFUpi9A-2K8UI1tGDFMFAbG05T9jMEOfNig,5910
25
+ entsoe/namespaces/__init__.py,sha256=ZVd80s5OVxegLo3A6nI64tHlBA1Iwe2ejqQilGNod5E,399
26
+ entsoe/namespaces/_base.py,sha256=ExhByzVDnrj4CLmg0EXd7Zhm1Cd6gL-gQ7lp-J-60IM,17202
27
+ entsoe/namespaces/balancing.py,sha256=N4D_5n2a__HOodmG1p_3OP8Bw4NTSPyL16UWhGW6Vl0,2485
28
+ entsoe/namespaces/generation.py,sha256=UapqnvCyWmVdMasdKHHXeRJO6ybZN0NIIySIascXSlo,7460
29
+ entsoe/namespaces/load.py,sha256=QLXZY8Cg4I5ph5IBeJHY1op-9_Ku7cqeHqH91oR32bs,2502
30
+ entsoe/namespaces/prices.py,sha256=gUHxb-UeG7MLn9PWSzifsIM43QJGhDjW6rrzJatxfwM,2482
31
+ entsoe/namespaces/transmission.py,sha256=v7TDHBE2MhkUEG2ixXzZviD1GzAiY1fXMV2OXqtwoLk,8829
32
+ python_entsoe-0.7.0.dist-info/METADATA,sha256=lV2M8F4mqdkzvKu4Yo150iOGnmwp4Cqn7-XjWSqt0Vs,9740
33
+ python_entsoe-0.7.0.dist-info/WHEEL,sha256=2iZrJkDIkeDh0k9SikKMqFuRP-ua6mb4Ir1AsER4BEw,87
34
+ python_entsoe-0.7.0.dist-info/entry_points.txt,sha256=tYyCheggCsGRKOq2vIjpAxBksEM7K_iGI6vHkkQLmYg,42
35
+ python_entsoe-0.7.0.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: hatchling 1.32.4
2
+ Generator: hatchling 1.33.0
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
@@ -1,35 +0,0 @@
1
- entsoe/__init__.py,sha256=9qzvMUzoD-CRfX1vTzWIBfpXBMdJ2MgRwJEgQQsw1fA,529
2
- entsoe/_http.py,sha256=XhZZy059XHh8uAP2Vsm1e7BfRwQcmGLEYdREcgaF3Tk,6608
3
- entsoe/_mappings.py,sha256=6-IKLtwChvM7_YG90oSRDxo3IfQUuz3Gnv17TmQgPjM,15534
4
- entsoe/_xml.py,sha256=cJa4_nVIk27O9bCXkp2w-QR2fV3UrH-A80mX54KReVU,8439
5
- entsoe/cache.py,sha256=3UIuhaSH9LVGk9Ony5eMsk_qOmRzzMEyskQS_cmY020,14547
6
- entsoe/catalog.py,sha256=FUPg_WqLBkfl5sUgT9m8Bua7IP10NvBsakcndpUOBa0,9733
7
- entsoe/client.py,sha256=zHB9y2TbCRjSNe9d5c9XVt_BNZ7b8KsvJDORc5V-ypE,3542
8
- entsoe/exceptions.py,sha256=vqeu6_LxAtDvJziPnjbH52KV0fm63F8n2Y1lzSNp2Bs,1017
9
- entsoe/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
- entsoe/.agents/skills/entsoe/SKILL.md,sha256=JsFECSkfnxyR6iFx55WBBcMJjAOaMu84vhcsPsTVWC0,6452
11
- entsoe/cli/__init__.py,sha256=qUGXx4zdi8dCQkq3PPPa1sgD3Q6KIhJwWeBfTub4suM,139
12
- entsoe/cli/_output.py,sha256=aV_3CLmOHSxTAVuYdccTWYahqTNPunCbSeoq3YZL-4A,2943
13
- entsoe/cli/_resolve.py,sha256=oIUgZ2BF-p3AD2wQQBhkVCBHg8fbhIVFdrvll2sesD8,4799
14
- entsoe/cli/app.py,sha256=_dQsejLncSFJTgOy-26Bvl7pIMXve_YD3gxP-gRVsG4,2069
15
- entsoe/cli/balancing.py,sha256=ZXcjTEdbx00MUL4L6116G7MwBfpffB02DgazYexq-dc,2752
16
- entsoe/cli/cache_cmd.py,sha256=ozbQ5apxeLBIjbPsH-Cs5rDOVBVfrzJfDPKv1anLFgY,2255
17
- entsoe/cli/catalog_cmd.py,sha256=TzkkecSlnlz-f2_BlRqidKN6uTJtSInR0np4BA1rQ5c,5361
18
- entsoe/cli/config.py,sha256=YB6IeOBGMKahcVJBGUaCN5r1vs6YILv_XbXlcKLxLiU,1663
19
- entsoe/cli/config_cmd.py,sha256=HfpMMv8S1kDUIid6kxX-cNirCvhDby2lSPNSD8o3qX8,923
20
- entsoe/cli/exec_cmd.py,sha256=KiGwOTIjYQQPEg7v51oRbpk3Cj9-7hDDCbEYXfZ_lfQ,11308
21
- entsoe/cli/generation.py,sha256=wSQUyZJ3vuhcHss4R8g__2BMkTSik6rYkr4FvwWvvrs,5681
22
- entsoe/cli/load.py,sha256=wC8ZYGi8ce_b5OBBC7fdUPLCgUN_ssC79A0eZJuXGSQ,2685
23
- entsoe/cli/prices.py,sha256=Gj_Irw4i5KJ7lUUUChkm9FqBDCHorP9tN4fFMnc5v0c,1729
24
- entsoe/cli/transmission.py,sha256=nQMQwxNcvxHEdlldHnVY02oL2aUKONKRpz2M3bFKM1U,5592
25
- entsoe/namespaces/__init__.py,sha256=ZVd80s5OVxegLo3A6nI64tHlBA1Iwe2ejqQilGNod5E,399
26
- entsoe/namespaces/_base.py,sha256=Mxsdix1FiYXilVoI1tapoIkgMmXY9XPCQ6NKFUy5xkI,14918
27
- entsoe/namespaces/balancing.py,sha256=210Ft6dE7WXEuxtTJqyEvCIL960n-sDHT7tsqpSbXIw,2143
28
- entsoe/namespaces/generation.py,sha256=V4DkvV5ai7aWYYSdZKwWyxTEv1ed4nCCq7DYyVwvc6M,6729
29
- entsoe/namespaces/load.py,sha256=fbkwKWZifb8DOf5Rc_7c4_eFAXiqT_562r9WTMQwsuo,2160
30
- entsoe/namespaces/prices.py,sha256=Dr1y5Y9wVdTOzTTWXlx11eiQLQc75chua3UoRpBYfxw,2311
31
- entsoe/namespaces/transmission.py,sha256=V8zrs2CQXf1WPjJRqz7wc-ztnkfriIKXPLfYHBDJD9M,8067
32
- python_entsoe-0.6.3.dist-info/METADATA,sha256=ydDvnqNB_ohS3tLgq9_Gbk3wzfVe42uIPcO695UVTWc,8863
33
- python_entsoe-0.6.3.dist-info/WHEEL,sha256=W3fkpkm7-wf9vBI5Z-7s0eWkeM-spu78I8Neb98DeEg,87
34
- python_entsoe-0.6.3.dist-info/entry_points.txt,sha256=tYyCheggCsGRKOq2vIjpAxBksEM7K_iGI6vHkkQLmYg,42
35
- python_entsoe-0.6.3.dist-info/RECORD,,