python-entsoe 0.6.1__py3-none-any.whl → 0.6.3__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/_xml.py CHANGED
@@ -15,6 +15,7 @@ from __future__ import annotations
15
15
  import re
16
16
  import xml.etree.ElementTree as ET
17
17
  from datetime import timedelta
18
+ from typing import Callable
18
19
 
19
20
  import pandas as pd
20
21
 
@@ -79,12 +80,42 @@ def _extract_point_value(point: ET.Element) -> float | None:
79
80
  return None
80
81
 
81
82
 
82
- def parse_timeseries(xml_text: str) -> pd.DataFrame:
83
+ #: Element holding the sequence of a TimeSeries within a document, e.g. the
84
+ #: SDAC (1) and EXAA (2) day-ahead auctions both published for DE_LU and AT.
85
+ SEQUENCE_TAG = "classificationSequence_AttributeInstanceComponent.position"
86
+
87
+
88
+ def timeseries_sequence(ts: ET.Element) -> int | None:
89
+ """Return the classification sequence of a TimeSeries, or None if absent."""
90
+ for el in ts.iter():
91
+ if _strip_ns(el.tag) == SEQUENCE_TAG and el.text:
92
+ return int(el.text)
93
+ return None
94
+
95
+
96
+ def timeseries_contract_type(ts: ET.Element) -> str | None:
97
+ """Return the contract_MarketAgreement.type of a TimeSeries (A01 daily, A07 intraday)."""
98
+ return _find_text(ts, "contract_MarketAgreement.type")
99
+
100
+
101
+ def parse_timeseries(
102
+ xml_text: str,
103
+ ts_filter: Callable[[ET.Element], bool] | None = None,
104
+ ) -> pd.DataFrame:
83
105
  """Parse an ENTSO-E XML response into a DataFrame.
84
106
 
85
107
  Handles multiple TimeSeries (e.g., generation per type) and multiple
86
108
  Periods within each TimeSeries (e.g., multi-day responses).
87
109
 
110
+ Points omitted from a curveType A03 (variable-sized block) Period carry
111
+ the previous point's value, so they are filled in. TimeSeries the API
112
+ repeats verbatim produce duplicate rows, which are dropped.
113
+
114
+ Args:
115
+ xml_text: Raw XML response.
116
+ ts_filter: Optional predicate on each TimeSeries element; series for
117
+ which it returns False are skipped.
118
+
88
119
  Returns a DataFrame with columns:
89
120
  - timestamp: tz-aware UTC datetime
90
121
  - value: numeric value (MW or EUR/MWh depending on query)
@@ -107,6 +138,9 @@ def parse_timeseries(xml_text: str) -> pd.DataFrame:
107
138
  rows: list[dict] = []
108
139
 
109
140
  for ts in timeseries_list:
141
+ if ts_filter is not None and not ts_filter(ts):
142
+ continue
143
+
110
144
  # Extract TimeSeries metadata
111
145
  ts_meta: dict = {}
112
146
 
@@ -163,23 +197,38 @@ def parse_timeseries(xml_text: str) -> pd.DataFrame:
163
197
  period_start = pd.Timestamp(start_text)
164
198
  resolution = _parse_resolution(resolution_text)
165
199
 
200
+ values: dict[int, float | None] = {}
166
201
  for point in _findall(period, "Point"):
167
202
  position_text = _find_text(point, "position")
168
203
  if position_text is None:
169
204
  continue
205
+ values[int(position_text)] = _extract_point_value(point)
170
206
 
171
- position = int(position_text)
172
- value = _extract_point_value(point)
207
+ if not values:
208
+ continue
173
209
 
210
+ positions = sorted(values)
211
+ if _find_text(ts, "curveType") == "A03":
212
+ end_text = _find_text(time_interval, "end")
213
+ if end_text is not None:
214
+ n_slots = int((pd.Timestamp(end_text) - period_start) / resolution)
215
+ else:
216
+ n_slots = positions[-1]
217
+ filled: dict[int, float | None] = {}
218
+ last = None
219
+ for pos in range(positions[0], max(n_slots, positions[-1]) + 1):
220
+ last = values.get(pos, last)
221
+ filled[pos] = last
222
+ values, positions = filled, list(filled)
223
+
224
+ for position in positions:
174
225
  timestamp = period_start + resolution * (position - 1)
175
-
176
- row = {"timestamp": timestamp, "value": value, **ts_meta}
177
- rows.append(row)
226
+ rows.append({"timestamp": timestamp, "value": values[position], **ts_meta})
178
227
 
179
228
  if not rows:
180
229
  raise NoDataError()
181
230
 
182
- df = pd.DataFrame(rows)
231
+ df = pd.DataFrame(rows).drop_duplicates()
183
232
  df["timestamp"] = pd.to_datetime(df["timestamp"], utc=True)
184
233
  df = df.sort_values("timestamp").reset_index(drop=True)
185
234
  return df
entsoe/cache.py CHANGED
@@ -6,7 +6,7 @@ published (~48h), so caching is safe and enabled by default.
6
6
 
7
7
  Storage layout::
8
8
 
9
- {cache_dir}/
9
+ {cache_dir}/v{CACHE_LAYOUT_VERSION}/
10
10
  ├── prices/day_ahead/{ES,FR,...}/data.parquet
11
11
  ├── load/{actual,forecast}/{ES,FR,...}/data.parquet
12
12
  ├── generation/{actual,forecast,capacity}/{ES,...}/data.parquet
@@ -18,6 +18,9 @@ Each partition stores a single wide-format parquet file: the DatetimeIndex
18
18
  holds timestamps, and columns are values (e.g. "value", or per-type
19
19
  columns like "solar", "wind_onshore").
20
20
 
21
+ The version directory changes whenever cached values from earlier releases
22
+ are known to be wrong; data from older layouts is removed on first use.
23
+
21
24
  Gap detection works per-column: requesting specific columns checks whether
22
25
  those columns have data for the requested range, not whether any column does.
23
26
  """
@@ -42,6 +45,13 @@ _DEFAULT_CACHE_DIR = Path(
42
45
  os.environ.get("XDG_CACHE_HOME", Path.home() / ".cache")
43
46
  ) / "entsoe"
44
47
 
48
+ # Bumped when previously cached values are known to be wrong.
49
+ # v2 (0.6.2): A03 curves lost their omitted points; day-ahead mixed auctions.
50
+ CACHE_LAYOUT_VERSION = 2
51
+
52
+ # Domain directories written by the unversioned (<= 0.6.1) layout.
53
+ _LEGACY_DOMAINS = ("prices", "load", "generation", "transmission", "balancing")
54
+
45
55
  # Data older than this (hours) is considered final and won't be re-fetched
46
56
  _DEFAULT_RECENT_TTL_HOURS = 48
47
57
 
@@ -71,16 +81,37 @@ class CacheStore:
71
81
 
72
82
  def __init__(self, config: CacheConfig):
73
83
  self.config = config
84
+ self._purge_stale_layouts()
85
+
86
+ @property
87
+ def root(self) -> Path:
88
+ """Directory holding the current cache layout."""
89
+ return self.config.cache_dir / f"v{CACHE_LAYOUT_VERSION}"
90
+
91
+ def _purge_stale_layouts(self) -> None:
92
+ """Delete data cached by older layouts, which may hold wrong values."""
93
+ base = self.config.cache_dir
94
+ if not base.is_dir():
95
+ return
96
+ stale = [base / d for d in _LEGACY_DOMAINS]
97
+ stale += [
98
+ p for p in base.glob("v*")
99
+ if p.name[1:].isdigit() and int(p.name[1:]) < CACHE_LAYOUT_VERSION
100
+ ]
101
+ for path in stale:
102
+ if path.is_dir():
103
+ logger.info("Removing outdated ENTSO-E cache: %s", path)
104
+ shutil.rmtree(path, ignore_errors=True)
74
105
 
75
106
  # -- Path resolution -------------------------------------------------------
76
107
 
77
108
  def _parquet_path(self, domain: str, topic: str, partition: str) -> Path:
78
- """Data file: {cache_dir}/{domain}/{topic}/{partition}/data.parquet"""
79
- return self.config.cache_dir / domain / topic / partition / "data.parquet"
109
+ """Data file: {root}/{domain}/{topic}/{partition}/data.parquet"""
110
+ return self.root / domain / topic / partition / "data.parquet"
80
111
 
81
112
  def _meta_path(self, domain: str, topic: str, partition: str) -> Path:
82
- """Metadata file: {cache_dir}/{domain}/{topic}/{partition}/meta.json"""
83
- return self.config.cache_dir / domain / topic / partition / "meta.json"
113
+ """Metadata file: {root}/{domain}/{topic}/{partition}/meta.json"""
114
+ return self.root / domain / topic / partition / "meta.json"
84
115
 
85
116
  # -- Data Read / Write -----------------------------------------------------
86
117
 
@@ -291,13 +322,13 @@ class CacheStore:
291
322
  count = 0
292
323
 
293
324
  if domain and topic and partition:
294
- target = self.config.cache_dir / domain / topic / partition
325
+ target = self.root / domain / topic / partition
295
326
  elif domain and topic:
296
- target = self.config.cache_dir / domain / topic
327
+ target = self.root / domain / topic
297
328
  elif domain:
298
- target = self.config.cache_dir / domain
329
+ target = self.root / domain
299
330
  else:
300
- target = self.config.cache_dir
331
+ target = self.root
301
332
 
302
333
  if target.exists():
303
334
  count = sum(1 for f in target.rglob("*") if f.is_file())
@@ -307,7 +338,7 @@ class CacheStore:
307
338
 
308
339
  def status(self) -> dict:
309
340
  """Return cache statistics."""
310
- cache_dir = self.config.cache_dir
341
+ cache_dir = self.root
311
342
  if not cache_dir.exists():
312
343
  return {"path": str(cache_dir), "files": 0, "size_mb": 0.0, "domains": {}}
313
344
 
entsoe/cli/_resolve.py CHANGED
@@ -100,11 +100,11 @@ def _expand_period(period: str, today: date) -> tuple[date, date]:
100
100
 
101
101
  p = period.lower().strip()
102
102
 
103
+ # The library's end is exclusive, so a single day ends on the next one.
103
104
  if p == "today":
104
- return today, today
105
+ return today, today + timedelta(days=1)
105
106
  if p == "yesterday":
106
- yesterday = today - timedelta(days=1)
107
- return yesterday, yesterday
107
+ return today - timedelta(days=1), today
108
108
  if p == "week":
109
109
  monday = today - timedelta(days=today.weekday())
110
110
  return monday, today
entsoe/cli/prices.py CHANGED
@@ -18,6 +18,7 @@ def day_ahead(
18
18
  end: Optional[str] = typer.Option(None, "--end", "-e", help="End date (YYYY-MM-DD)"),
19
19
  period: Optional[str] = typer.Option(None, "--period", "-P", help="Period shorthand: today, yesterday, week, month, ytd, <N>d"),
20
20
  country: list[str] = typer.Option(..., "--country", "-c", help="Country code(s), comma-separated or repeated (e.g. ES,FR,DE_LU)"),
21
+ sequence: int = typer.Option(1, "--sequence", help="Auction: 1 = SDAC (default), 2 = EXAA (DE_LU, AT)"),
21
22
  format: str = typer.Option("table", "--format", "-f", help="Output format: table, csv, json"),
22
23
  output_path: Optional[str] = typer.Option(None, "--output", "-o", help="Output file path"),
23
24
  api_key: Optional[str] = typer.Option(None, "--api-key", help="ENTSO-E API key"),
@@ -28,7 +29,7 @@ def day_ahead(
28
29
  s, e = resolve_dates(start, end, period)
29
30
  client = get_client(api_key)
30
31
  countries = resolve_many_required(country)
31
- df = client.prices.day_ahead(s, e, country=countries)
32
+ df = client.prices.day_ahead(s, e, country=countries, sequence=sequence)
32
33
  output(df, format, title="Day-Ahead Prices", output_path=output_path)
33
34
 
34
35
 
@@ -3,14 +3,16 @@
3
3
  from __future__ import annotations
4
4
 
5
5
  import logging
6
- from typing import TYPE_CHECKING, Callable, Union
6
+ from typing import TYPE_CHECKING, Callable, Optional, Union
7
7
 
8
8
  import pandas as pd
9
9
 
10
- from ..exceptions import InvalidParameterError, NoDataError
10
+ from ..exceptions import InvalidParameterError
11
11
  from .._mappings import country_name, lookup_area
12
12
 
13
13
  if TYPE_CHECKING:
14
+ import xml.etree.ElementTree as ET
15
+
14
16
  from .._http import HttpClient
15
17
  from ..cache import CacheStore
16
18
 
@@ -22,6 +24,9 @@ Timestamp = Union[str, pd.Timestamp]
22
24
  #: Parameters that accept a single value or a list.
23
25
  OneOrMany = Union[str, list[str]]
24
26
 
27
+ #: Predicate deciding which TimeSeries of a response to keep.
28
+ TimeSeriesFilter = Optional[Callable[["ET.Element"], bool]]
29
+
25
30
 
26
31
  class BaseNamespace:
27
32
  """Base class for domain namespaces.
@@ -61,6 +66,8 @@ class BaseNamespace:
61
66
  params: dict,
62
67
  start: Timestamp,
63
68
  end: Timestamp,
69
+ *,
70
+ ts_filter: TimeSeriesFilter = None,
64
71
  ) -> pd.DataFrame:
65
72
  """Execute a query and parse the XML response into a DataFrame."""
66
73
  from .._xml import parse_timeseries
@@ -71,10 +78,10 @@ class BaseNamespace:
71
78
 
72
79
  # Handle multi-chunk responses (year-splitting)
73
80
  if isinstance(result, list):
74
- dfs = [parse_timeseries(xml) for xml in result]
81
+ dfs = [parse_timeseries(xml, ts_filter) for xml in result]
75
82
  return pd.concat(dfs, ignore_index=True).sort_values("timestamp").reset_index(drop=True)
76
83
 
77
- return parse_timeseries(result)
84
+ return parse_timeseries(result, ts_filter)
78
85
 
79
86
  def _query_multi(
80
87
  self,
@@ -85,6 +92,7 @@ class BaseNamespace:
85
92
  *,
86
93
  label_fn: Callable[[str], str] = country_name,
87
94
  label_col: str = "country",
95
+ ts_filter: TimeSeriesFilter = None,
88
96
  ) -> pd.DataFrame:
89
97
  """Execute a query for one or many values, concatenating results.
90
98
 
@@ -110,11 +118,11 @@ class BaseNamespace:
110
118
  queries with an additional label column.
111
119
  """
112
120
  if isinstance(values, str):
113
- return self._query(build_params(values), start, end)
121
+ return self._query(build_params(values), start, end, ts_filter=ts_filter)
114
122
 
115
123
  frames = []
116
124
  for val in values:
117
- df = self._query(build_params(val), start, end)
125
+ df = self._query(build_params(val), start, end, ts_filter=ts_filter)
118
126
  df[label_col] = label_fn(val)
119
127
  frames.append(df)
120
128
  return pd.concat(frames, ignore_index=True)
@@ -134,6 +142,7 @@ class BaseNamespace:
134
142
  *,
135
143
  pivot_col: str | None = None,
136
144
  value_col: str = "value",
145
+ ts_filter: TimeSeriesFilter = None,
137
146
  ) -> pd.DataFrame:
138
147
  """Execute a query with parquet cache support.
139
148
 
@@ -174,7 +183,7 @@ class BaseNamespace:
174
183
  raise InvalidParameterError("start must be before end.")
175
184
 
176
185
  if self._cache is None:
177
- return self._query(params, start_ts, end_ts)
186
+ return self._query(params, start_ts, end_ts, ts_filter=ts_filter)
178
187
 
179
188
  # 1. Read cached wide data
180
189
  cached_wide = self._cache.read(domain, topic, partition, start_ts, end_ts)
@@ -223,17 +232,14 @@ class BaseNamespace:
223
232
  )
224
233
  new_wide_frames = []
225
234
  gap_meta: dict = {}
235
+ # A failed request propagates: returning the cache without the gap
236
+ # would silently hand back partial or empty data.
226
237
  for gap in valid_gaps:
227
- try:
228
- raw_df = self._query(params, gap.start, gap.end)
229
- wide, meta = self._to_wide(raw_df, pivot_col, value_col)
230
- new_wide_frames.append(wide)
231
- if meta:
232
- gap_meta.update(meta)
233
- except (InvalidParameterError, NoDataError):
234
- raise
235
- except Exception as exc:
236
- logger.warning("Failed to fetch gap %s→%s: %s", gap.start, gap.end, exc)
238
+ raw_df = self._query(params, gap.start, gap.end, ts_filter=ts_filter)
239
+ wide, meta = self._to_wide(raw_df, pivot_col, value_col)
240
+ new_wide_frames.append(wide)
241
+ if meta:
242
+ gap_meta.update(meta)
237
243
 
238
244
  # 4. Merge new data with cache and persist
239
245
  if new_wide_frames:
@@ -279,27 +285,30 @@ class BaseNamespace:
279
285
  value_col: str = "value",
280
286
  label_fn: Callable[[str], str] = country_name,
281
287
  label_col: str = "country",
288
+ ts_filter: TimeSeriesFilter = None,
289
+ partition_fn: Callable[[str], str] = str,
282
290
  ) -> pd.DataFrame:
283
291
  """Execute a cached query for one or many values.
284
292
 
285
- Each value is its own cache partition. Multi-value queries add
286
- a label column, same as :meth:`_query_multi`.
293
+ Each value is its own cache partition, named by *partition_fn(value)*.
294
+ Multi-value queries add a label column, same as :meth:`_query_multi`.
287
295
  """
288
296
  if self._cache is None:
289
297
  return self._query_multi(build_params, values, start, end,
290
- label_fn=label_fn, label_col=label_col)
298
+ label_fn=label_fn, label_col=label_col,
299
+ ts_filter=ts_filter)
291
300
 
292
301
  if isinstance(values, str):
293
302
  return self._query_cached(
294
- domain, topic, values, build_params(values), start, end,
295
- pivot_col=pivot_col, value_col=value_col,
303
+ domain, topic, partition_fn(values), build_params(values), start, end,
304
+ pivot_col=pivot_col, value_col=value_col, ts_filter=ts_filter,
296
305
  )
297
306
 
298
307
  frames = []
299
308
  for val in values:
300
309
  df = self._query_cached(
301
- domain, topic, val, build_params(val), start, end,
302
- pivot_col=pivot_col, value_col=value_col,
310
+ domain, topic, partition_fn(val), build_params(val), start, end,
311
+ pivot_col=pivot_col, value_col=value_col, ts_filter=ts_filter,
303
312
  )
304
313
  df[label_col] = label_fn(val)
305
314
  frames.append(df)
@@ -2,11 +2,13 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
+ import xml.etree.ElementTree as ET
6
+
5
7
  import pandas as pd
6
8
 
9
+ from .._xml import timeseries_contract_type, timeseries_sequence
7
10
  from ._base import BaseNamespace, OneOrMany, Timestamp
8
11
 
9
-
10
12
  class PricesNamespace(BaseNamespace):
11
13
  """Access electricity price data.
12
14
 
@@ -19,14 +21,24 @@ class PricesNamespace(BaseNamespace):
19
21
  start: Timestamp,
20
22
  end: Timestamp,
21
23
  country: OneOrMany,
24
+ sequence: int = 1,
22
25
  ) -> pd.DataFrame:
23
26
  """Query day-ahead electricity prices.
24
27
 
28
+ The A44 document mixes several auctions. Only daily contracts are
29
+ kept (intraday auctions such as the Spanish IDAs are dropped), and
30
+ among them the one with the requested classification sequence.
31
+
25
32
  Args:
26
33
  start: Period start — date string or tz-aware Timestamp.
27
34
  end: Period end — date string or tz-aware Timestamp.
28
35
  country: Country code or list of codes (e.g., "FR" or ["FR", "ES"]).
29
36
  When a list is passed, results include a ``country`` column.
37
+ sequence: Which day-ahead auction to return. ``1`` (default) is
38
+ the Single Day-Ahead Coupling (SDAC, gate closure 12:00 CET).
39
+ ``2`` is the separate EXAA auction (10:15 CET) published for
40
+ DE_LU and AT. Zones that publish a single auction without a
41
+ sequence count as ``1``.
30
42
 
31
43
  Returns:
32
44
  DataFrame with columns: timestamp, value (EUR/MWh).
@@ -41,6 +53,13 @@ class PricesNamespace(BaseNamespace):
41
53
  "out_Domain": area,
42
54
  }
43
55
 
56
+ def _keep(ts: ET.Element) -> bool:
57
+ if timeseries_contract_type(ts) not in (None, "A01"):
58
+ return False
59
+ return (timeseries_sequence(ts) or 1) == sequence
60
+
44
61
  return self._query_multi_cached(
45
62
  "prices", "day_ahead", _params, country, start, end,
63
+ ts_filter=_keep,
64
+ partition_fn=lambda code: code if sequence == 1 else f"{code}.seq{sequence}",
46
65
  )
@@ -1,11 +1,11 @@
1
- Metadata-Version: 2.4
1
+ Metadata-Version: 2.5
2
2
  Name: python-entsoe
3
- Version: 0.6.1
3
+ Version: 0.6.3
4
4
  Summary: Python client for the ENTSO-E Transparency Platform API
5
- Project-URL: Homepage, https://github.com/datons/python-entsoe
6
- Project-URL: Repository, https://github.com/datons/python-entsoe
7
- Project-URL: Issues, https://github.com/datons/python-entsoe/issues
8
- Project-URL: Changelog, https://github.com/datons/python-entsoe/releases
5
+ Project-URL: Homepage, https://gitlab.com/datons.com/libraries/python-entsoe
6
+ Project-URL: Repository, https://gitlab.com/datons.com/libraries/python-entsoe
7
+ Project-URL: Issues, https://gitlab.com/datons.com/libraries/python-entsoe/-/issues
8
+ Project-URL: Changelog, https://gitlab.com/datons.com/libraries/python-entsoe/-/releases
9
9
  Author-email: Jesús López <jesus.lopez@datons.com>
10
10
  License-Expression: MIT
11
11
  Keywords: api,electricity,energy,entsoe,transparency
@@ -93,11 +93,14 @@ df = client.load.forecast(start, end, country="FR")
93
93
 
94
94
  | Method | Description | Parameters |
95
95
  |--------|-------------|------------|
96
- | `day_ahead(start, end, country)` | Day-ahead market prices (EUR/MWh) | `country`: ISO code |
96
+ | `day_ahead(start, end, country, sequence=1)` | Day-ahead market prices (EUR/MWh) | `country`: ISO code; `sequence`: `1` SDAC, `2` EXAA |
97
97
 
98
98
  ```python
99
99
  df = client.prices.day_ahead(start, end, country="FR")
100
100
  # Returns: timestamp, value, currency, price_unit
101
+
102
+ # DE_LU and AT also publish the separate EXAA auction (10:15 CET)
103
+ exaa = client.prices.day_ahead(start, end, country="DE_LU", sequence=2)
101
104
  ```
102
105
 
103
106
  ### `client.generation`
@@ -251,7 +254,7 @@ See the [`examples/`](examples/) directory for Jupyter notebooks with plotly vis
251
254
  ## Development
252
255
 
253
256
  ```bash
254
- git clone https://github.com/jsulopzs/python-entsoe.git
257
+ git clone git@gitlab.com:datons.com/libraries/python-entsoe.git
255
258
  cd python-entsoe
256
259
  uv sync
257
260
 
@@ -1,8 +1,8 @@
1
1
  entsoe/__init__.py,sha256=9qzvMUzoD-CRfX1vTzWIBfpXBMdJ2MgRwJEgQQsw1fA,529
2
2
  entsoe/_http.py,sha256=XhZZy059XHh8uAP2Vsm1e7BfRwQcmGLEYdREcgaF3Tk,6608
3
3
  entsoe/_mappings.py,sha256=6-IKLtwChvM7_YG90oSRDxo3IfQUuz3Gnv17TmQgPjM,15534
4
- entsoe/_xml.py,sha256=222kgi8lStU0qQIU-oxiciO2WtplqKySi6qBZXbyiEc,6393
5
- entsoe/cache.py,sha256=rRkuQPGYg05Uo3xFW7gVltNE56M-1_E5mdEvgLoWhpM,13356
4
+ entsoe/_xml.py,sha256=cJa4_nVIk27O9bCXkp2w-QR2fV3UrH-A80mX54KReVU,8439
5
+ entsoe/cache.py,sha256=3UIuhaSH9LVGk9Ony5eMsk_qOmRzzMEyskQS_cmY020,14547
6
6
  entsoe/catalog.py,sha256=FUPg_WqLBkfl5sUgT9m8Bua7IP10NvBsakcndpUOBa0,9733
7
7
  entsoe/client.py,sha256=zHB9y2TbCRjSNe9d5c9XVt_BNZ7b8KsvJDORc5V-ypE,3542
8
8
  entsoe/exceptions.py,sha256=vqeu6_LxAtDvJziPnjbH52KV0fm63F8n2Y1lzSNp2Bs,1017
@@ -10,7 +10,7 @@ entsoe/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
10
  entsoe/.agents/skills/entsoe/SKILL.md,sha256=JsFECSkfnxyR6iFx55WBBcMJjAOaMu84vhcsPsTVWC0,6452
11
11
  entsoe/cli/__init__.py,sha256=qUGXx4zdi8dCQkq3PPPa1sgD3Q6KIhJwWeBfTub4suM,139
12
12
  entsoe/cli/_output.py,sha256=aV_3CLmOHSxTAVuYdccTWYahqTNPunCbSeoq3YZL-4A,2943
13
- entsoe/cli/_resolve.py,sha256=vqsJJSBCht06HlToKW47ATrQesCl2Uy851KRVjE1kFk,4737
13
+ entsoe/cli/_resolve.py,sha256=oIUgZ2BF-p3AD2wQQBhkVCBHg8fbhIVFdrvll2sesD8,4799
14
14
  entsoe/cli/app.py,sha256=_dQsejLncSFJTgOy-26Bvl7pIMXve_YD3gxP-gRVsG4,2069
15
15
  entsoe/cli/balancing.py,sha256=ZXcjTEdbx00MUL4L6116G7MwBfpffB02DgazYexq-dc,2752
16
16
  entsoe/cli/cache_cmd.py,sha256=ozbQ5apxeLBIjbPsH-Cs5rDOVBVfrzJfDPKv1anLFgY,2255
@@ -20,16 +20,16 @@ entsoe/cli/config_cmd.py,sha256=HfpMMv8S1kDUIid6kxX-cNirCvhDby2lSPNSD8o3qX8,923
20
20
  entsoe/cli/exec_cmd.py,sha256=KiGwOTIjYQQPEg7v51oRbpk3Cj9-7hDDCbEYXfZ_lfQ,11308
21
21
  entsoe/cli/generation.py,sha256=wSQUyZJ3vuhcHss4R8g__2BMkTSik6rYkr4FvwWvvrs,5681
22
22
  entsoe/cli/load.py,sha256=wC8ZYGi8ce_b5OBBC7fdUPLCgUN_ssC79A0eZJuXGSQ,2685
23
- entsoe/cli/prices.py,sha256=BSUhPKw-K2hw7GrgPnmCtdR7iAo9tMMoKNSuqscPT5o,1601
23
+ entsoe/cli/prices.py,sha256=Gj_Irw4i5KJ7lUUUChkm9FqBDCHorP9tN4fFMnc5v0c,1729
24
24
  entsoe/cli/transmission.py,sha256=nQMQwxNcvxHEdlldHnVY02oL2aUKONKRpz2M3bFKM1U,5592
25
25
  entsoe/namespaces/__init__.py,sha256=ZVd80s5OVxegLo3A6nI64tHlBA1Iwe2ejqQilGNod5E,399
26
- entsoe/namespaces/_base.py,sha256=iVUVYYeYz3qAvyjzWLV_4ewUGiS63WpbyIKLTaWIFsU,14366
26
+ entsoe/namespaces/_base.py,sha256=Mxsdix1FiYXilVoI1tapoIkgMmXY9XPCQ6NKFUy5xkI,14918
27
27
  entsoe/namespaces/balancing.py,sha256=210Ft6dE7WXEuxtTJqyEvCIL960n-sDHT7tsqpSbXIw,2143
28
28
  entsoe/namespaces/generation.py,sha256=V4DkvV5ai7aWYYSdZKwWyxTEv1ed4nCCq7DYyVwvc6M,6729
29
29
  entsoe/namespaces/load.py,sha256=fbkwKWZifb8DOf5Rc_7c4_eFAXiqT_562r9WTMQwsuo,2160
30
- entsoe/namespaces/prices.py,sha256=5-hVmpxytyxPKx0eBRN7mjKDhfPUK0ZZi1nnF5zOE9A,1295
30
+ entsoe/namespaces/prices.py,sha256=Dr1y5Y9wVdTOzTTWXlx11eiQLQc75chua3UoRpBYfxw,2311
31
31
  entsoe/namespaces/transmission.py,sha256=V8zrs2CQXf1WPjJRqz7wc-ztnkfriIKXPLfYHBDJD9M,8067
32
- python_entsoe-0.6.1.dist-info/METADATA,sha256=YTJB_o6J02O8cxj5izGnykIZ8uZk-SrXdkasOyze2Qo,8612
33
- python_entsoe-0.6.1.dist-info/WHEEL,sha256=QccIxa26bgl1E6uMy58deGWi-0aeIkkangHcxk2kWfw,87
34
- python_entsoe-0.6.1.dist-info/entry_points.txt,sha256=tYyCheggCsGRKOq2vIjpAxBksEM7K_iGI6vHkkQLmYg,42
35
- python_entsoe-0.6.1.dist-info/RECORD,,
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,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: hatchling 1.29.0
2
+ Generator: hatchling 1.32.4
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any