myelectricaldatapy 2.4.2__tar.gz → 2.4.4__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 (50) hide show
  1. {myelectricaldatapy-2.4.2 → myelectricaldatapy-2.4.4}/PKG-INFO +1 -1
  2. {myelectricaldatapy-2.4.2 → myelectricaldatapy-2.4.4}/myelectricaldatapy/api.py +6 -6
  3. {myelectricaldatapy-2.4.2 → myelectricaldatapy-2.4.4}/myelectricaldatapy/auth.py +1 -1
  4. {myelectricaldatapy-2.4.2 → myelectricaldatapy-2.4.4}/myelectricaldatapy/mypdl.py +9 -15
  5. {myelectricaldatapy-2.4.2 → myelectricaldatapy-2.4.4}/myelectricaldatapy/types.py +10 -1
  6. {myelectricaldatapy-2.4.2 → myelectricaldatapy-2.4.4}/myelectricaldatapy.egg-info/PKG-INFO +1 -1
  7. myelectricaldatapy-2.4.4/myelectricaldatapy.egg-info/scm_version.json +8 -0
  8. {myelectricaldatapy-2.4.2 → myelectricaldatapy-2.4.4}/tests/test_analytics.py +7 -2
  9. {myelectricaldatapy-2.4.2 → myelectricaldatapy-2.4.4}/tests/test_load_data.py +22 -10
  10. myelectricaldatapy-2.4.2/myelectricaldatapy.egg-info/scm_version.json +0 -8
  11. {myelectricaldatapy-2.4.2 → myelectricaldatapy-2.4.4}/.devcontainer/devcontainer-lock.json +0 -0
  12. {myelectricaldatapy-2.4.2 → myelectricaldatapy-2.4.4}/.devcontainer/devcontainer.json +0 -0
  13. {myelectricaldatapy-2.4.2 → myelectricaldatapy-2.4.4}/.github/dependabot.yml +0 -0
  14. {myelectricaldatapy-2.4.2 → myelectricaldatapy-2.4.4}/.github/workflows/auto-approve.yml +0 -0
  15. {myelectricaldatapy-2.4.2 → myelectricaldatapy-2.4.4}/.github/workflows/python-lint.yml +0 -0
  16. {myelectricaldatapy-2.4.2 → myelectricaldatapy-2.4.4}/.github/workflows/python-publish.yml +0 -0
  17. {myelectricaldatapy-2.4.2 → myelectricaldatapy-2.4.4}/.github/workflows/release.yml +0 -0
  18. {myelectricaldatapy-2.4.2 → myelectricaldatapy-2.4.4}/.gitignore +0 -0
  19. {myelectricaldatapy-2.4.2 → myelectricaldatapy-2.4.4}/.pre-commit-config.yaml +0 -0
  20. {myelectricaldatapy-2.4.2 → myelectricaldatapy-2.4.4}/.vscode/settings.json +0 -0
  21. {myelectricaldatapy-2.4.2 → myelectricaldatapy-2.4.4}/LICENSE +0 -0
  22. {myelectricaldatapy-2.4.2 → myelectricaldatapy-2.4.4}/README.md +0 -0
  23. {myelectricaldatapy-2.4.2 → myelectricaldatapy-2.4.4}/_secrets.yaml +0 -0
  24. {myelectricaldatapy-2.4.2 → myelectricaldatapy-2.4.4}/example.py +0 -0
  25. {myelectricaldatapy-2.4.2 → myelectricaldatapy-2.4.4}/myelectricaldatapy/__init__.py +0 -0
  26. {myelectricaldatapy-2.4.2 → myelectricaldatapy-2.4.4}/myelectricaldatapy/analytics.py +0 -0
  27. {myelectricaldatapy-2.4.2 → myelectricaldatapy-2.4.4}/myelectricaldatapy/const.py +0 -0
  28. {myelectricaldatapy-2.4.2 → myelectricaldatapy-2.4.4}/myelectricaldatapy/exceptions.py +0 -0
  29. {myelectricaldatapy-2.4.2 → myelectricaldatapy-2.4.4}/myelectricaldatapy/py.typed +0 -0
  30. {myelectricaldatapy-2.4.2 → myelectricaldatapy-2.4.4}/myelectricaldatapy/tz.py +0 -0
  31. {myelectricaldatapy-2.4.2 → myelectricaldatapy-2.4.4}/myelectricaldatapy.egg-info/SOURCES.txt +0 -0
  32. {myelectricaldatapy-2.4.2 → myelectricaldatapy-2.4.4}/myelectricaldatapy.egg-info/dependency_links.txt +0 -0
  33. {myelectricaldatapy-2.4.2 → myelectricaldatapy-2.4.4}/myelectricaldatapy.egg-info/requires.txt +0 -0
  34. {myelectricaldatapy-2.4.2 → myelectricaldatapy-2.4.4}/myelectricaldatapy.egg-info/scm_file_list.json +0 -0
  35. {myelectricaldatapy-2.4.2 → myelectricaldatapy-2.4.4}/myelectricaldatapy.egg-info/top_level.txt +0 -0
  36. {myelectricaldatapy-2.4.2 → myelectricaldatapy-2.4.4}/pyproject.toml +0 -0
  37. {myelectricaldatapy-2.4.2 → myelectricaldatapy-2.4.4}/setup.cfg +0 -0
  38. {myelectricaldatapy-2.4.2 → myelectricaldatapy-2.4.4}/tests/__init__.py +0 -0
  39. {myelectricaldatapy-2.4.2 → myelectricaldatapy-2.4.4}/tests/conftest.py +0 -0
  40. {myelectricaldatapy-2.4.2 → myelectricaldatapy-2.4.4}/tests/consts.py +0 -0
  41. {myelectricaldatapy-2.4.2 → myelectricaldatapy-2.4.4}/tests/fixtures/access.json +0 -0
  42. {myelectricaldatapy-2.4.2 → myelectricaldatapy-2.4.4}/tests/fixtures/address.json +0 -0
  43. {myelectricaldatapy-2.4.2 → myelectricaldatapy-2.4.4}/tests/fixtures/contract.json +0 -0
  44. {myelectricaldatapy-2.4.2 → myelectricaldatapy-2.4.4}/tests/fixtures/daily.json +0 -0
  45. {myelectricaldatapy-2.4.2 → myelectricaldatapy-2.4.4}/tests/fixtures/detail.json +0 -0
  46. {myelectricaldatapy-2.4.2 → myelectricaldatapy-2.4.4}/tests/fixtures/ecowatt.json +0 -0
  47. {myelectricaldatapy-2.4.2 → myelectricaldatapy-2.4.4}/tests/fixtures/identity.json +0 -0
  48. {myelectricaldatapy-2.4.2 → myelectricaldatapy-2.4.4}/tests/fixtures/invalid_access.json +0 -0
  49. {myelectricaldatapy-2.4.2 → myelectricaldatapy-2.4.4}/tests/fixtures/tempo.json +0 -0
  50. {myelectricaldatapy-2.4.2 → myelectricaldatapy-2.4.4}/uv.lock +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: myelectricaldatapy
3
- Version: 2.4.2
3
+ Version: 2.4.4
4
4
  Summary: Fetch Linky data from myelectricaldata.fr
5
5
  Author-email: Cyr-ius <cyr-ius@ipocus.net>
6
6
  License-Expression: GPL-3.0-or-later
@@ -58,7 +58,7 @@ class Enedis:
58
58
  session = session or ClientSession()
59
59
  self.auth = EnedisAuth(session, token, timeout)
60
60
  self.async_request = self.auth.async_request
61
- self.offpeaks: list[str] = []
61
+ self.offpeaks: list[tuple[str, str]] = []
62
62
  self.last_access: date | None = None
63
63
 
64
64
  async def async_fetch_datas(
@@ -72,7 +72,7 @@ class Enedis:
72
72
  start_date = start.strftime("%Y-%m-%d")
73
73
  end_date = end.strftime("%Y-%m-%d")
74
74
  path_range = f"/start/{start_date}/end/{end_date}"
75
- path = f"{service}/{pdl}{path_range}"
75
+ path = f"/{service}/{pdl}{path_range}"
76
76
  return await self.async_request(path=path)
77
77
 
78
78
  async def async_valid_access(self, pdl: str) -> AccessResponse:
@@ -132,7 +132,7 @@ class Enedis:
132
132
  if end
133
133
  else (local_now() + timedelta(days=1)).strftime("%Y-%m-%d")
134
134
  )
135
- raw = await self.auth.async_request(path=f"rte/tempo/{str_start}/{str_end}")
135
+ raw = await self.auth.async_request(path=f"/rte/tempo/{str_start}/{str_end}")
136
136
  try:
137
137
  return TempoResponse.validate_python(raw)
138
138
  except ValidationError as error:
@@ -141,7 +141,7 @@ class Enedis:
141
141
 
142
142
  async def async_get_tempo_days(self) -> TempoDays | None:
143
143
  """Summary Tempo days before the end of year."""
144
- raw = await self.auth.async_request(path="edf/tempo/days")
144
+ raw = await self.auth.async_request(path="/edf/tempo/days")
145
145
  try:
146
146
  return TempoDays.model_validate(raw)
147
147
  except ValidationError as error:
@@ -150,7 +150,7 @@ class Enedis:
150
150
 
151
151
  async def async_get_tempo_prices(self) -> Prices | None:
152
152
  """Return Tempo prices as a :class:`Prices` model, one value per colour."""
153
- raw = await self.auth.async_request(path="edf/tempo/price")
153
+ raw = await self.auth.async_request(path="/edf/tempo/price")
154
154
  try:
155
155
  return Prices(
156
156
  standard=TempoPrice(
@@ -180,7 +180,7 @@ class Enedis:
180
180
  if end
181
181
  else (local_now() + timedelta(days=1)).strftime("%Y-%m-%d")
182
182
  )
183
- raw = await self.async_request(path=f"rte/ecowatt/{str_start}/{str_end}")
183
+ raw = await self.async_request(path=f"/rte/ecowatt/{str_start}/{str_end}")
184
184
  try:
185
185
  return EcowattResponse.validate_python(raw)
186
186
  except ValidationError as error:
@@ -41,7 +41,7 @@ class EnedisAuth:
41
41
  try:
42
42
  async with asyncio.timeout(self.timeout):
43
43
  _LOGGER.debug("Request: %s (%s) - %s", path, method, kwargs.get("json"))
44
- response = await self.session.request(method, f"{URL}/{path}", **kwargs)
44
+ response = await self.session.request(method, f"{URL}{path}", **kwargs)
45
45
  contents = await response.read()
46
46
  response.raise_for_status()
47
47
  except (TimeoutError, asyncio.CancelledError) as error:
@@ -17,21 +17,16 @@ from .const import (
17
17
  ATTR_CUM_VALUE,
18
18
  ATTR_END,
19
19
  ATTR_FN,
20
- ATTR_HPHC,
21
20
  ATTR_INTERVALS,
22
21
  ATTR_PRICE,
23
22
  ATTR_PRICES,
24
23
  ATTR_PROD,
25
- ATTR_STANDARD,
26
24
  ATTR_START,
27
- ATTR_TEMPO,
28
25
  CONF_VALUE,
29
26
  DAILY_CONSUM,
30
27
  DAILY_PROD,
31
- DEFAULT_SUBSCRIPTION,
32
28
  DETAIL_CONSUM,
33
29
  DETAIL_PROD,
34
- SUBSCRIPTIONS,
35
30
  )
36
31
  from .exceptions import EnedisException, LimitReached
37
32
  from .types import (
@@ -74,7 +69,7 @@ class EnedisByPDL:
74
69
  self,
75
70
  pdl: str,
76
71
  token: str,
77
- subscription: Subscription = "standard",
72
+ subscription: Subscription = Subscription.STANDARD,
78
73
  session: ClientSession | None = None,
79
74
  timeout: int = 30,
80
75
  timezone: _tzinfo | None = None,
@@ -94,16 +89,14 @@ class EnedisByPDL:
94
89
  self._ecowatt_subs: bool = False
95
90
  self._maxpower_subs: bool = False
96
91
  self._params: dict[Mode, dict[str, Any]] = {}
97
- self._subscription: Subscription = (
98
- subscription if subscription in SUBSCRIPTIONS else DEFAULT_SUBSCRIPTION
99
- )
92
+ self.subscription: Subscription = subscription
100
93
  self.access: AccessResponse | None = None
101
94
  self.address: UsagePoint | None = None
102
95
  self.contract: Contract | None = None
103
96
  self.ecowatt: EcowattMapping | None = None
104
97
  self.has_collected: bool = False
105
98
  self.has_parameters: bool = False
106
- self.intervals: list[tuple[str, str]] = []
99
+ self.offpeak_intervals: list[tuple[str, str]] = []
107
100
  self.last_access: dt = local_now()
108
101
  self._update_lock = asyncio.Lock()
109
102
  self.last_refresh: date | None = None
@@ -123,22 +116,22 @@ class EnedisByPDL:
123
116
  @property
124
117
  def has_intervals(self) -> bool:
125
118
  """Intervals exist."""
126
- return len(self.intervals) > 0
119
+ return len(self.offpeak_intervals) > 0
127
120
 
128
121
  @property
129
122
  def has_tempo_subscription(self) -> bool:
130
123
  """Tempo subscription status."""
131
- return self._subscription == ATTR_TEMPO
124
+ return self.subscription == Subscription.TEMPO
132
125
 
133
126
  @property
134
127
  def has_offpeak_hours_subscription(self) -> bool:
135
128
  """Offpeak hours subscription status."""
136
- return self._subscription == ATTR_HPHC
129
+ return self.subscription == Subscription.HPHC
137
130
 
138
131
  @property
139
132
  def has_standard_subscription(self) -> bool:
140
133
  """Offpeak hours subscription status."""
141
- return self._subscription == ATTR_STANDARD
134
+ return self.subscription == Subscription.STANDARD
142
135
 
143
136
  @property
144
137
  def has_ecowatt_subscription(self) -> bool:
@@ -239,6 +232,7 @@ class EnedisByPDL:
239
232
  if self.contract is None and self.has_collected is False:
240
233
  try:
241
234
  self.contract = await self._api.async_get_contract(self.pdl)
235
+ self.offpeak_intervals = self._api.offpeaks
242
236
  except EnedisException as error:
243
237
  _LOGGER.warning(error)
244
238
 
@@ -282,7 +276,7 @@ class EnedisByPDL:
282
276
  def _set_intervals(self, mode: Mode, intervals: list[tuple[str, str]]) -> None:
283
277
  """Set intervals."""
284
278
  if isinstance(intervals, list):
285
- self.intervals = intervals
279
+ self.offpeak_intervals = intervals
286
280
  self._params[mode].update({ATTR_INTERVALS: intervals})
287
281
 
288
282
  def _set_prices(self, mode: Mode, prices: Prices | Mapping[str, Any]) -> None:
@@ -10,11 +10,12 @@ payloads coming from the API::
10
10
  """
11
11
 
12
12
  from datetime import datetime
13
+ from enum import IntFlag
13
14
  from typing import Annotated, Any, Literal
14
15
 
15
16
  from pydantic import AfterValidator, BaseModel, ConfigDict, TypeAdapter, model_validator
16
17
 
17
- type Subscription = Literal["hphc", "tempo", "standard"]
18
+ # type Subscription = Literal["hphc", "tempo", "standard"]
18
19
  type ProductionCollect = Literal["production_load_curve", "daily_production"]
19
20
  type ConsumptionCollect = Literal["consumption_load_curve", "daily_consumption"]
20
21
  type EnergyCollect = ProductionCollect | ConsumptionCollect
@@ -226,6 +227,14 @@ class TempoDays(_ApiModel):
226
227
  red: int = 0
227
228
 
228
229
 
230
+ class Subscription(IntFlag):
231
+ """Subscription."""
232
+
233
+ STANDARD = 1
234
+ HPHC = 2
235
+ TEMPO = 4
236
+
237
+
229
238
  def _check_iso_date(value: str) -> str:
230
239
  """Ensure a mapping key is a real, zero-padded ``YYYY-MM-DD`` calendar date."""
231
240
  try:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: myelectricaldatapy
3
- Version: 2.4.2
3
+ Version: 2.4.4
4
4
  Summary: Fetch Linky data from myelectricaldata.fr
5
5
  Author-email: Cyr-ius <cyr-ius@ipocus.net>
6
6
  License-Expression: GPL-3.0-or-later
@@ -0,0 +1,8 @@
1
+ {
2
+ "tag": "2.4.4",
3
+ "distance": 0,
4
+ "node": "g9a87ed2706824a82c1926e6396d5602827511a4a",
5
+ "dirty": false,
6
+ "branch": "HEAD",
7
+ "node_date": "2026-08-31"
8
+ }
@@ -14,6 +14,7 @@ from myelectricaldatapy import (
14
14
  DETAIL_CONSUM,
15
15
  EnedisByPDL,
16
16
  LimitReached,
17
+ Subscription,
17
18
  )
18
19
  from myelectricaldatapy.tz import LOCAL_TIMEZONE
19
20
 
@@ -235,7 +236,9 @@ async def test_hphc_cumsum_range(mock_enedis: Mock, session) -> None: # pylint:
235
236
  @freeze_time("2023-3-1")
236
237
  async def test_tempo_detail_comsumption(mock_enedis: Mock, session) -> None:
237
238
  """Test tempo pricings."""
238
- api = EnedisByPDL(pdl=PDL, token=TOKEN, session=session, subscription="tempo")
239
+ api = EnedisByPDL(
240
+ pdl=PDL, token=TOKEN, session=session, subscription=Subscription.TEMPO
241
+ )
239
242
  api.set_data_fetch(
240
243
  DETAIL_CONSUM,
241
244
  intervals=OFFPEAK_INTERVALS,
@@ -255,7 +258,9 @@ async def test_tempo_detail_comsumption(mock_enedis: Mock, session) -> None:
255
258
  @freeze_time("2023-3-1")
256
259
  async def test_tempo_detail_comsumption_with_price(mock_enedis: Mock, session) -> None:
257
260
  """Test tempo pricings."""
258
- api = EnedisByPDL(pdl=PDL, token=TOKEN, session=session, subscription="tempo")
261
+ api = EnedisByPDL(
262
+ pdl=PDL, token=TOKEN, session=session, subscription=Subscription.TEMPO
263
+ )
259
264
  api.set_data_fetch(
260
265
  DETAIL_CONSUM,
261
266
  prices=TEMPO_PRICE,
@@ -15,6 +15,7 @@ from myelectricaldatapy import (
15
15
  EnedisByPDL,
16
16
  EnedisException,
17
17
  LimitReached,
18
+ Subscription,
18
19
  )
19
20
  from myelectricaldatapy.tz import LOCAL_TIMEZONE
20
21
 
@@ -24,17 +25,12 @@ from .consts import PDL, TOKEN
24
25
  @freeze_time("2023-01-23")
25
26
  async def test_subscription(mock_enedis: Mock, session) -> None:
26
27
  """Test subscription compute."""
27
- api = EnedisByPDL(pdl=PDL, token=TOKEN, session=session, subscription="hphc")
28
+ api = EnedisByPDL(
29
+ pdl=PDL, token=TOKEN, session=session, subscription=Subscription.HPHC
30
+ )
28
31
  assert api.has_offpeak_hours_subscription is True
29
32
 
30
33
 
31
- @freeze_time("2023-01-23")
32
- async def test_subscription_error(mock_enedis: Mock, session) -> None:
33
- """Test subscription msiconfiguration value."""
34
- api = EnedisByPDL(pdl=PDL, token=TOKEN, session=session, subscription="toto")
35
- assert api.has_standard_subscription is True
36
-
37
-
38
34
  @freeze_time("2023-01-23")
39
35
  async def test_address(mock_enedis: Mock, session) -> None:
40
36
  """Test subscription compute."""
@@ -51,6 +47,18 @@ async def test_contract(mock_enedis: Mock, session) -> None:
51
47
  assert api.contract.segment == "C5"
52
48
 
53
49
 
50
+ @freeze_time("2023-01-23")
51
+ async def test_offpeak_intervals(mock_enedis: Mock, session) -> None:
52
+ """Test subscription compute."""
53
+ api = Enedis(token=TOKEN, session=session)
54
+ await api.async_get_contract(PDL)
55
+ assert isinstance(api.offpeaks[0], tuple)
56
+
57
+ api = EnedisByPDL(pdl=PDL, token=TOKEN, session=session)
58
+ await api.async_update()
59
+ assert isinstance(api.offpeak_intervals[0], tuple)
60
+
61
+
54
62
  @freeze_time("2023-01-23")
55
63
  async def test_ecowatt(mock_enedis: Mock, session) -> None:
56
64
  """Test get ecowatt."""
@@ -80,7 +88,9 @@ async def test_tempoday(mock_enedis: Mock, session) -> None:
80
88
  resultat = await api.async_get_tempo()
81
89
  assert resultat["2023-03-01"] == "blue"
82
90
 
83
- mypdl = EnedisByPDL(pdl=PDL, token=TOKEN, session=session, subscription="tempo")
91
+ mypdl = EnedisByPDL(
92
+ pdl=PDL, token=TOKEN, session=session, subscription=Subscription.TEMPO
93
+ )
84
94
  mypdl.set_data_fetch(DETAIL_CONSUM)
85
95
  await mypdl.async_update()
86
96
  resultat = mypdl.stats["consumption"]
@@ -90,7 +100,9 @@ async def test_tempoday(mock_enedis: Mock, session) -> None:
90
100
  @freeze_time("2023-3-3")
91
101
  async def test_tempo_infos(mock_enedis: Mock, session) -> None:
92
102
  """Test get tempo day."""
93
- api = EnedisByPDL(pdl=PDL, token=TOKEN, session=session, subscription="tempo")
103
+ api = EnedisByPDL(
104
+ pdl=PDL, token=TOKEN, session=session, subscription=Subscription.TEMPO
105
+ )
94
106
  await api.async_update()
95
107
  assert api.tempo_days.red == 5
96
108
  assert api.tempo_prices.standard.blue == 0.1654
@@ -1,8 +0,0 @@
1
- {
2
- "tag": "2.4.2",
3
- "distance": 0,
4
- "node": "g9cc30e1b79e821e698039046f59932119b5fd3ca",
5
- "dirty": false,
6
- "branch": "HEAD",
7
- "node_date": "2026-08-30"
8
- }