e-data 2.0.1.dev131__tar.gz → 2.0.1.dev132__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 (38) hide show
  1. {e_data-2.0.1.dev131/e_data.egg-info → e_data-2.0.1.dev132}/PKG-INFO +1 -1
  2. {e_data-2.0.1.dev131 → e_data-2.0.1.dev132/e_data.egg-info}/PKG-INFO +1 -1
  3. {e_data-2.0.1.dev131 → e_data-2.0.1.dev132}/edata/providers/datadis.py +10 -3
  4. {e_data-2.0.1.dev131 → e_data-2.0.1.dev132}/edata/tests/test_datadis_connector.py +62 -0
  5. {e_data-2.0.1.dev131 → e_data-2.0.1.dev132}/pyproject.toml +1 -1
  6. {e_data-2.0.1.dev131 → e_data-2.0.1.dev132}/LICENSE +0 -0
  7. {e_data-2.0.1.dev131 → e_data-2.0.1.dev132}/MANIFEST.in +0 -0
  8. {e_data-2.0.1.dev131 → e_data-2.0.1.dev132}/README.md +0 -0
  9. {e_data-2.0.1.dev131 → e_data-2.0.1.dev132}/e_data.egg-info/SOURCES.txt +0 -0
  10. {e_data-2.0.1.dev131 → e_data-2.0.1.dev132}/e_data.egg-info/dependency_links.txt +0 -0
  11. {e_data-2.0.1.dev131 → e_data-2.0.1.dev132}/e_data.egg-info/requires.txt +0 -0
  12. {e_data-2.0.1.dev131 → e_data-2.0.1.dev132}/e_data.egg-info/top_level.txt +0 -0
  13. {e_data-2.0.1.dev131 → e_data-2.0.1.dev132}/edata/__init__.py +0 -0
  14. {e_data-2.0.1.dev131 → e_data-2.0.1.dev132}/edata/cli.py +0 -0
  15. {e_data-2.0.1.dev131 → e_data-2.0.1.dev132}/edata/core/__init__.py +0 -0
  16. {e_data-2.0.1.dev131 → e_data-2.0.1.dev132}/edata/core/completion.py +0 -0
  17. {e_data-2.0.1.dev131 → e_data-2.0.1.dev132}/edata/core/const.py +0 -0
  18. {e_data-2.0.1.dev131 → e_data-2.0.1.dev132}/edata/core/utils.py +0 -0
  19. {e_data-2.0.1.dev131 → e_data-2.0.1.dev132}/edata/database/__init__.py +0 -0
  20. {e_data-2.0.1.dev131 → e_data-2.0.1.dev132}/edata/database/controller.py +0 -0
  21. {e_data-2.0.1.dev131 → e_data-2.0.1.dev132}/edata/database/models.py +0 -0
  22. {e_data-2.0.1.dev131 → e_data-2.0.1.dev132}/edata/database/queries.py +0 -0
  23. {e_data-2.0.1.dev131 → e_data-2.0.1.dev132}/edata/database/utils.py +0 -0
  24. {e_data-2.0.1.dev131 → e_data-2.0.1.dev132}/edata/models/__init__.py +0 -0
  25. {e_data-2.0.1.dev131 → e_data-2.0.1.dev132}/edata/models/bill.py +0 -0
  26. {e_data-2.0.1.dev131 → e_data-2.0.1.dev132}/edata/models/data.py +0 -0
  27. {e_data-2.0.1.dev131 → e_data-2.0.1.dev132}/edata/models/supply.py +0 -0
  28. {e_data-2.0.1.dev131 → e_data-2.0.1.dev132}/edata/providers/__init__.py +0 -0
  29. {e_data-2.0.1.dev131 → e_data-2.0.1.dev132}/edata/providers/redata.py +0 -0
  30. {e_data-2.0.1.dev131 → e_data-2.0.1.dev132}/edata/services/bill_service.py +0 -0
  31. {e_data-2.0.1.dev131 → e_data-2.0.1.dev132}/edata/services/data_service.py +0 -0
  32. {e_data-2.0.1.dev131 → e_data-2.0.1.dev132}/edata/tests/__init__.py +0 -0
  33. {e_data-2.0.1.dev131 → e_data-2.0.1.dev132}/edata/tests/test_completion.py +0 -0
  34. {e_data-2.0.1.dev131 → e_data-2.0.1.dev132}/edata/tests/test_incremental.py +0 -0
  35. {e_data-2.0.1.dev131 → e_data-2.0.1.dev132}/edata/tests/test_redata_connector.py +0 -0
  36. {e_data-2.0.1.dev131 → e_data-2.0.1.dev132}/edata/tests/test_services.py +0 -0
  37. {e_data-2.0.1.dev131 → e_data-2.0.1.dev132}/edata/tests/test_utils.py +0 -0
  38. {e_data-2.0.1.dev131 → e_data-2.0.1.dev132}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: e-data
3
- Version: 2.0.1.dev131
3
+ Version: 2.0.1.dev132
4
4
  Summary: Python library for managing spanish energy data from various web providers
5
5
  Author-email: VMG <vmayorg@outlook.es>
6
6
  License: GNU GENERAL PUBLIC LICENSE
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: e-data
3
- Version: 2.0.1.dev131
3
+ Version: 2.0.1.dev132
4
4
  Summary: Python library for managing spanish energy data from various web providers
5
5
  Author-email: VMG <vmayorg@outlook.es>
6
6
  License: GNU GENERAL PUBLIC LICENSE
@@ -403,10 +403,17 @@ class DatadisConnector:
403
403
  for i in response.get("timeCurve", []):
404
404
  if "consumptionKWh" in i:
405
405
  if all(k in i for k in GET_CONSUMPTION_DATA_MANDATORY_FIELDS):
406
- hour = str(int(i["time"].split(":")[0]) - 1)
406
+ raw_hour = int(i["time"].split(":")[0])
407
+ # Datadis delivers hours 1..24 (end-of-interval). A sporadic
408
+ # i-DE glitch emits an extra "00:00" row on a day already
409
+ # carrying its full 24 hours, so drop it -- 01:00..24:00
410
+ # already covers the day -- instead of remapping onto 23:00
411
+ # and overlapping that day's 24:00 slot.
412
+ if raw_hour == 0:
413
+ continue
407
414
  date_as_dt = datetime.strptime(
408
- f"{i['date']} {hour.zfill(2)}:00", "%Y/%m/%d %H:%M"
409
- )
415
+ i["date"], "%Y/%m/%d"
416
+ ) + timedelta(hours=raw_hour - 1)
410
417
  if not (start_date <= date_as_dt <= end_date):
411
418
  continue # skip element if dt is out of range
412
419
 
@@ -56,6 +56,34 @@ CONSUMPTIONS_RESPONSE = {
56
56
  ]
57
57
  }
58
58
 
59
+ CONSUMPTIONS_RESPONSE_WITH_ZERO_HOUR = {
60
+ "timeCurve": [
61
+ {
62
+ "date": "2022/10/22",
63
+ "time": "01:00",
64
+ "consumptionKWh": 0.203,
65
+ "surplusEnergyKWh": 0,
66
+ "obtainMethod": "Real",
67
+ },
68
+ {
69
+ "date": "2022/10/22",
70
+ "time": "02:00",
71
+ "consumptionKWh": 0.163,
72
+ "surplusEnergyKWh": 0,
73
+ "obtainMethod": "Real",
74
+ },
75
+ # Sporadic i-DE glitch: an extra "00:00" row on a day that already
76
+ # carries its full 24 hours. Must be dropped, not remapped to 23:00.
77
+ {
78
+ "date": "2022/10/22",
79
+ "time": "00:00",
80
+ "consumptionKWh": 0.999,
81
+ "surplusEnergyKWh": 0,
82
+ "obtainMethod": "Real",
83
+ },
84
+ ]
85
+ }
86
+
59
87
  MAXIMETER_RESPONSE = {
60
88
  "maxPower": [
61
89
  {
@@ -132,6 +160,40 @@ def test_get_consumption_data(mock_token, mock_get, snapshot):
132
160
  )
133
161
 
134
162
 
163
+ @patch("aiohttp.ClientSession.get")
164
+ @patch.object(
165
+ DatadisConnector, "_async_get_token", new_callable=AsyncMock, return_value=True
166
+ )
167
+ def test_get_consumption_data_skips_zero_hour(mock_token, mock_get):
168
+ """A stray "00:00" row is dropped, not remapped, and never aborts the fetch."""
169
+ mock_response = MagicMock()
170
+ mock_response.status = 200
171
+ mock_response.text = AsyncMock(return_value="text")
172
+ mock_response.json = AsyncMock(
173
+ return_value=CONSUMPTIONS_RESPONSE_WITH_ZERO_HOUR
174
+ )
175
+ mock_get.return_value.__aenter__.return_value = mock_response
176
+ connector = DatadisConnector(MOCK_USERNAME, MOCK_PASSWORD)
177
+
178
+ # Range spans the previous day, so a remapped "00:00" -> 2022/10/21 23:00
179
+ # would fall inside it; its absence proves the explicit skip, not the filter.
180
+ result = connector.get_consumption_data(
181
+ "ESXXXXXXXXXXXXXXXXTEST",
182
+ "2",
183
+ datetime.datetime(2022, 10, 21, 0, 0, 0),
184
+ datetime.datetime(2022, 10, 22, 23, 59, 59),
185
+ "0",
186
+ 5,
187
+ )
188
+
189
+ datetimes = [x.datetime for x in result]
190
+ assert datetimes == [
191
+ datetime.datetime(2022, 10, 22, 0, 0),
192
+ datetime.datetime(2022, 10, 22, 1, 0),
193
+ ]
194
+ assert datetime.datetime(2022, 10, 21, 23, 0) not in datetimes
195
+
196
+
135
197
  @patch("aiohttp.ClientSession.get")
136
198
  @patch.object(
137
199
  DatadisConnector, "_async_get_token", new_callable=AsyncMock, return_value=True
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "e-data"
7
- version = "2.0.1.dev131"
7
+ version = "2.0.1.dev132"
8
8
  description = "Python library for managing spanish energy data from various web providers"
9
9
  readme = "README.md"
10
10
  authors = [
File without changes
File without changes
File without changes
File without changes