Hydro-Quebec-API-Wrapper 4.1.0__tar.gz → 4.2.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (105) hide show
  1. {hydro_quebec_api_wrapper-4.1.0 → hydro_quebec_api_wrapper-4.2.0}/.gitlab-ci.yml +3 -0
  2. {hydro_quebec_api_wrapper-4.1.0 → hydro_quebec_api_wrapper-4.2.0}/.pre-commit-config.yaml +2 -2
  3. {hydro_quebec_api_wrapper-4.1.0 → hydro_quebec_api_wrapper-4.2.0}/Hydro_Quebec_API_Wrapper.egg-info/PKG-INFO +1 -1
  4. {hydro_quebec_api_wrapper-4.1.0 → hydro_quebec_api_wrapper-4.2.0}/PKG-INFO +1 -1
  5. {hydro_quebec_api_wrapper-4.1.0 → hydro_quebec_api_wrapper-4.2.0}/hydroqc/contract/contract_dpc.py +62 -14
  6. {hydro_quebec_api_wrapper-4.1.0 → hydro_quebec_api_wrapper-4.2.0}/hydroqc/hydro_api/client.py +7 -3
  7. {hydro_quebec_api_wrapper-4.1.0 → hydro_quebec_api_wrapper-4.2.0}/hydroqc/hydro_api/consts.py +2 -2
  8. {hydro_quebec_api_wrapper-4.1.0 → hydro_quebec_api_wrapper-4.2.0}/hydroqc/types/__init__.py +2 -2
  9. {hydro_quebec_api_wrapper-4.1.0 → hydro_quebec_api_wrapper-4.2.0}/hydroqc/types/consump.py +0 -17
  10. {hydro_quebec_api_wrapper-4.1.0 → hydro_quebec_api_wrapper-4.2.0}/hydroqc/types/dpc.py +27 -10
  11. hydro_quebec_api_wrapper-4.2.0/hydroqc/types/dt.py +25 -0
  12. {hydro_quebec_api_wrapper-4.1.0 → hydro_quebec_api_wrapper-4.2.0}/test_requirements.txt +2 -2
  13. hydro_quebec_api_wrapper-4.1.0/hydroqc/types/dt.py +0 -15
  14. {hydro_quebec_api_wrapper-4.1.0 → hydro_quebec_api_wrapper-4.2.0}/.coveragerc +0 -0
  15. {hydro_quebec_api_wrapper-4.1.0 → hydro_quebec_api_wrapper-4.2.0}/.devcontainer/Dockerfile +0 -0
  16. {hydro_quebec_api_wrapper-4.1.0 → hydro_quebec_api_wrapper-4.2.0}/.devcontainer/devcontainer.json +0 -0
  17. {hydro_quebec_api_wrapper-4.1.0 → hydro_quebec_api_wrapper-4.2.0}/.flake8 +0 -0
  18. {hydro_quebec_api_wrapper-4.1.0 → hydro_quebec_api_wrapper-4.2.0}/.gitignore +0 -0
  19. {hydro_quebec_api_wrapper-4.1.0 → hydro_quebec_api_wrapper-4.2.0}/.pylintrc +0 -0
  20. {hydro_quebec_api_wrapper-4.1.0 → hydro_quebec_api_wrapper-4.2.0}/Hydro_Quebec_API_Wrapper.egg-info/SOURCES.txt +0 -0
  21. {hydro_quebec_api_wrapper-4.1.0 → hydro_quebec_api_wrapper-4.2.0}/Hydro_Quebec_API_Wrapper.egg-info/dependency_links.txt +0 -0
  22. {hydro_quebec_api_wrapper-4.1.0 → hydro_quebec_api_wrapper-4.2.0}/Hydro_Quebec_API_Wrapper.egg-info/entry_points.txt +0 -0
  23. {hydro_quebec_api_wrapper-4.1.0 → hydro_quebec_api_wrapper-4.2.0}/Hydro_Quebec_API_Wrapper.egg-info/requires.txt +0 -0
  24. {hydro_quebec_api_wrapper-4.1.0 → hydro_quebec_api_wrapper-4.2.0}/Hydro_Quebec_API_Wrapper.egg-info/top_level.txt +0 -0
  25. {hydro_quebec_api_wrapper-4.1.0 → hydro_quebec_api_wrapper-4.2.0}/LICENSE +0 -0
  26. {hydro_quebec_api_wrapper-4.1.0 → hydro_quebec_api_wrapper-4.2.0}/MANIFEST.in +0 -0
  27. {hydro_quebec_api_wrapper-4.1.0 → hydro_quebec_api_wrapper-4.2.0}/README.md +0 -0
  28. {hydro_quebec_api_wrapper-4.1.0 → hydro_quebec_api_wrapper-4.2.0}/config.default.yaml +0 -0
  29. {hydro_quebec_api_wrapper-4.1.0 → hydro_quebec_api_wrapper-4.2.0}/conflict_test_requirements.txt +0 -0
  30. {hydro_quebec_api_wrapper-4.1.0 → hydro_quebec_api_wrapper-4.2.0}/docs/Makefile +0 -0
  31. {hydro_quebec_api_wrapper-4.1.0 → hydro_quebec_api_wrapper-4.2.0}/docs/make.bat +0 -0
  32. {hydro_quebec_api_wrapper-4.1.0 → hydro_quebec_api_wrapper-4.2.0}/docs/source/_static/custom.css +0 -0
  33. {hydro_quebec_api_wrapper-4.1.0 → hydro_quebec_api_wrapper-4.2.0}/docs/source/_static/hydroqc-logo-128.png +0 -0
  34. {hydro_quebec_api_wrapper-4.1.0 → hydro_quebec_api_wrapper-4.2.0}/docs/source/_static/hydroqc-logo.svg +0 -0
  35. {hydro_quebec_api_wrapper-4.1.0 → hydro_quebec_api_wrapper-4.2.0}/docs/source/conf.py +0 -0
  36. {hydro_quebec_api_wrapper-4.1.0 → hydro_quebec_api_wrapper-4.2.0}/docs/source/external/description-des-codes-interruption.pdf +0 -0
  37. {hydro_quebec_api_wrapper-4.1.0 → hydro_quebec_api_wrapper-4.2.0}/docs/source/index.rst +0 -0
  38. {hydro_quebec_api_wrapper-4.1.0 → hydro_quebec_api_wrapper-4.2.0}/docs/source/reference/hydroqc.contract.rst +0 -0
  39. {hydro_quebec_api_wrapper-4.1.0 → hydro_quebec_api_wrapper-4.2.0}/docs/source/reference/hydroqc.hydro_api.rst +0 -0
  40. {hydro_quebec_api_wrapper-4.1.0 → hydro_quebec_api_wrapper-4.2.0}/docs/source/reference/hydroqc.peak.cpc.rst +0 -0
  41. {hydro_quebec_api_wrapper-4.1.0 → hydro_quebec_api_wrapper-4.2.0}/docs/source/reference/hydroqc.peak.dpc.rst +0 -0
  42. {hydro_quebec_api_wrapper-4.1.0 → hydro_quebec_api_wrapper-4.2.0}/docs/source/reference/hydroqc.peak.rst +0 -0
  43. {hydro_quebec_api_wrapper-4.1.0 → hydro_quebec_api_wrapper-4.2.0}/docs/source/reference/hydroqc.rst +0 -0
  44. {hydro_quebec_api_wrapper-4.1.0 → hydro_quebec_api_wrapper-4.2.0}/docs/source/reference/hydroqc.types.rst +0 -0
  45. {hydro_quebec_api_wrapper-4.1.0 → hydro_quebec_api_wrapper-4.2.0}/docs/source/reference/modules.rst +0 -0
  46. {hydro_quebec_api_wrapper-4.1.0 → hydro_quebec_api_wrapper-4.2.0}/docs/source/todo.rst +0 -0
  47. {hydro_quebec_api_wrapper-4.1.0 → hydro_quebec_api_wrapper-4.2.0}/examples/hydro.py +0 -0
  48. {hydro_quebec_api_wrapper-4.1.0 → hydro_quebec_api_wrapper-4.2.0}/hydroqc/__init__.py +0 -0
  49. {hydro_quebec_api_wrapper-4.1.0 → hydro_quebec_api_wrapper-4.2.0}/hydroqc/account.py +0 -0
  50. {hydro_quebec_api_wrapper-4.1.0 → hydro_quebec_api_wrapper-4.2.0}/hydroqc/consts.py +0 -0
  51. {hydro_quebec_api_wrapper-4.1.0 → hydro_quebec_api_wrapper-4.2.0}/hydroqc/contract/__init__.py +0 -0
  52. {hydro_quebec_api_wrapper-4.1.0 → hydro_quebec_api_wrapper-4.2.0}/hydroqc/contract/common.py +0 -0
  53. {hydro_quebec_api_wrapper-4.1.0 → hydro_quebec_api_wrapper-4.2.0}/hydroqc/contract/contract_d.py +0 -0
  54. {hydro_quebec_api_wrapper-4.1.0 → hydro_quebec_api_wrapper-4.2.0}/hydroqc/contract/contract_d_cpc.py +0 -0
  55. {hydro_quebec_api_wrapper-4.1.0 → hydro_quebec_api_wrapper-4.2.0}/hydroqc/contract/contract_dt.py +0 -0
  56. {hydro_quebec_api_wrapper-4.1.0 → hydro_quebec_api_wrapper-4.2.0}/hydroqc/contract/contract_m.py +0 -0
  57. {hydro_quebec_api_wrapper-4.1.0 → hydro_quebec_api_wrapper-4.2.0}/hydroqc/contract/contract_m_gdp.py +0 -0
  58. {hydro_quebec_api_wrapper-4.1.0 → hydro_quebec_api_wrapper-4.2.0}/hydroqc/contract/contract_residential.py +0 -0
  59. {hydro_quebec_api_wrapper-4.1.0 → hydro_quebec_api_wrapper-4.2.0}/hydroqc/contract/outage.py +0 -0
  60. {hydro_quebec_api_wrapper-4.1.0 → hydro_quebec_api_wrapper-4.2.0}/hydroqc/customer.py +0 -0
  61. {hydro_quebec_api_wrapper-4.1.0 → hydro_quebec_api_wrapper-4.2.0}/hydroqc/diagnostic.py +0 -0
  62. {hydro_quebec_api_wrapper-4.1.0 → hydro_quebec_api_wrapper-4.2.0}/hydroqc/error.py +0 -0
  63. {hydro_quebec_api_wrapper-4.1.0 → hydro_quebec_api_wrapper-4.2.0}/hydroqc/hydro_api/__init__.py +0 -0
  64. {hydro_quebec_api_wrapper-4.1.0 → hydro_quebec_api_wrapper-4.2.0}/hydroqc/hydro_api/cache.py +0 -0
  65. {hydro_quebec_api_wrapper-4.1.0 → hydro_quebec_api_wrapper-4.2.0}/hydroqc/logger.py +0 -0
  66. {hydro_quebec_api_wrapper-4.1.0 → hydro_quebec_api_wrapper-4.2.0}/hydroqc/peak/__init__.py +0 -0
  67. {hydro_quebec_api_wrapper-4.1.0 → hydro_quebec_api_wrapper-4.2.0}/hydroqc/peak/basepeak.py +0 -0
  68. {hydro_quebec_api_wrapper-4.1.0 → hydro_quebec_api_wrapper-4.2.0}/hydroqc/peak/basepeakhandler.py +0 -0
  69. {hydro_quebec_api_wrapper-4.1.0 → hydro_quebec_api_wrapper-4.2.0}/hydroqc/peak/consts.py +0 -0
  70. {hydro_quebec_api_wrapper-4.1.0 → hydro_quebec_api_wrapper-4.2.0}/hydroqc/peak/cpc/__init__.py +0 -0
  71. {hydro_quebec_api_wrapper-4.1.0 → hydro_quebec_api_wrapper-4.2.0}/hydroqc/peak/cpc/consts.py +0 -0
  72. {hydro_quebec_api_wrapper-4.1.0 → hydro_quebec_api_wrapper-4.2.0}/hydroqc/peak/cpc/handler.py +0 -0
  73. {hydro_quebec_api_wrapper-4.1.0 → hydro_quebec_api_wrapper-4.2.0}/hydroqc/peak/cpc/peak.py +0 -0
  74. {hydro_quebec_api_wrapper-4.1.0 → hydro_quebec_api_wrapper-4.2.0}/hydroqc/peak/dpc/__init__.py +0 -0
  75. {hydro_quebec_api_wrapper-4.1.0 → hydro_quebec_api_wrapper-4.2.0}/hydroqc/peak/dpc/consts.py +0 -0
  76. {hydro_quebec_api_wrapper-4.1.0 → hydro_quebec_api_wrapper-4.2.0}/hydroqc/peak/dpc/handler.py +0 -0
  77. {hydro_quebec_api_wrapper-4.1.0 → hydro_quebec_api_wrapper-4.2.0}/hydroqc/peak/dpc/peak.py +0 -0
  78. {hydro_quebec_api_wrapper-4.1.0 → hydro_quebec_api_wrapper-4.2.0}/hydroqc/public_client.py +0 -0
  79. {hydro_quebec_api_wrapper-4.1.0 → hydro_quebec_api_wrapper-4.2.0}/hydroqc/py.typed +0 -0
  80. {hydro_quebec_api_wrapper-4.1.0 → hydro_quebec_api_wrapper-4.2.0}/hydroqc/timerange.py +0 -0
  81. {hydro_quebec_api_wrapper-4.1.0 → hydro_quebec_api_wrapper-4.2.0}/hydroqc/types/account.py +0 -0
  82. {hydro_quebec_api_wrapper-4.1.0 → hydro_quebec_api_wrapper-4.2.0}/hydroqc/types/common.py +0 -0
  83. {hydro_quebec_api_wrapper-4.1.0 → hydro_quebec_api_wrapper-4.2.0}/hydroqc/types/contract.py +0 -0
  84. {hydro_quebec_api_wrapper-4.1.0 → hydro_quebec_api_wrapper-4.2.0}/hydroqc/types/cpc.py +0 -0
  85. {hydro_quebec_api_wrapper-4.1.0 → hydro_quebec_api_wrapper-4.2.0}/hydroqc/types/outage.py +0 -0
  86. {hydro_quebec_api_wrapper-4.1.0 → hydro_quebec_api_wrapper-4.2.0}/hydroqc/utils.py +0 -0
  87. {hydro_quebec_api_wrapper-4.1.0 → hydro_quebec_api_wrapper-4.2.0}/hydroqc/webuser.py +0 -0
  88. {hydro_quebec_api_wrapper-4.1.0 → hydro_quebec_api_wrapper-4.2.0}/logo/hydroqc-logo-128.png +0 -0
  89. {hydro_quebec_api_wrapper-4.1.0 → hydro_quebec_api_wrapper-4.2.0}/logo/hydroqc-logo.svg +0 -0
  90. {hydro_quebec_api_wrapper-4.1.0 → hydro_quebec_api_wrapper-4.2.0}/pyproject.toml +0 -0
  91. {hydro_quebec_api_wrapper-4.1.0 → hydro_quebec_api_wrapper-4.2.0}/renovate.json5 +0 -0
  92. {hydro_quebec_api_wrapper-4.1.0 → hydro_quebec_api_wrapper-4.2.0}/setup.cfg +0 -0
  93. {hydro_quebec_api_wrapper-4.1.0 → hydro_quebec_api_wrapper-4.2.0}/tests/__init__.py +0 -0
  94. {hydro_quebec_api_wrapper-4.1.0 → hydro_quebec_api_wrapper-4.2.0}/tests/conftest.py +0 -0
  95. {hydro_quebec_api_wrapper-4.1.0 → hydro_quebec_api_wrapper-4.2.0}/tests/subtest_common.py +0 -0
  96. {hydro_quebec_api_wrapper-4.1.0 → hydro_quebec_api_wrapper-4.2.0}/tests/subtest_contract_d.py +0 -0
  97. {hydro_quebec_api_wrapper-4.1.0 → hydro_quebec_api_wrapper-4.2.0}/tests/subtest_contract_d_cpc.py +0 -0
  98. {hydro_quebec_api_wrapper-4.1.0 → hydro_quebec_api_wrapper-4.2.0}/tests/subtest_contract_dpc.py +0 -0
  99. {hydro_quebec_api_wrapper-4.1.0 → hydro_quebec_api_wrapper-4.2.0}/tests/subtest_contract_dt.py +0 -0
  100. {hydro_quebec_api_wrapper-4.1.0 → hydro_quebec_api_wrapper-4.2.0}/tests/subtest_contract_m.py +0 -0
  101. {hydro_quebec_api_wrapper-4.1.0 → hydro_quebec_api_wrapper-4.2.0}/tests/subtest_contract_m_gdp.py +0 -0
  102. {hydro_quebec_api_wrapper-4.1.0 → hydro_quebec_api_wrapper-4.2.0}/tests/test_basic.py +0 -0
  103. {hydro_quebec_api_wrapper-4.1.0 → hydro_quebec_api_wrapper-4.2.0}/tests/test_timerange.py +0 -0
  104. {hydro_quebec_api_wrapper-4.1.0 → hydro_quebec_api_wrapper-4.2.0}/tests/tools.py +0 -0
  105. {hydro_quebec_api_wrapper-4.1.0 → hydro_quebec_api_wrapper-4.2.0}/tox.ini +0 -0
@@ -314,6 +314,9 @@ package:
314
314
  # Disable if it's a tag pipeline
315
315
  - if: "$CI_COMMIT_TAG"
316
316
  when: never
317
+ # Disable if it's a scheduled pipeline
318
+ - if: "$CI_PIPELINE_SOURCE == 'schedule'"
319
+ when: never
317
320
  # Enabled for main branch
318
321
  - if: "$CI_COMMIT_REF_NAME == $CI_DEFAULT_BRANCH"
319
322
  when: on_success
@@ -16,7 +16,7 @@ repos:
16
16
  - id: check-ast
17
17
 
18
18
  - repo: https://github.com/psf/black
19
- rev: 25.9.0
19
+ rev: 25.11.0
20
20
  hooks:
21
21
  - id: black
22
22
  language_version: python3
@@ -52,4 +52,4 @@ repos:
52
52
  - "aiohttp==3.13.2"
53
53
  - "aiocache==0.12.3"
54
54
  - "pkce==1.0.3"
55
- - "pytest-asyncio==1.2.0"
55
+ - "pytest-asyncio==1.3.0"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: Hydro-Quebec-API-Wrapper
3
- Version: 4.1.0
3
+ Version: 4.2.0
4
4
  Summary: A wrapper library to access hydro quebec API and more
5
5
  Home-page: https://hydroqc.ca
6
6
  Author-email: Hydroqc Team <info@hydroqc.ca>
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: Hydro-Quebec-API-Wrapper
3
- Version: 4.1.0
3
+ Version: 4.2.0
4
4
  Summary: A wrapper library to access hydro quebec API and more
5
5
  Home-page: https://hydroqc.ca
6
6
  Author-email: Hydroqc Team <info@hydroqc.ca>
@@ -1,7 +1,8 @@
1
1
  """Hydroquebec contract module."""
2
2
 
3
3
  from collections.abc import Callable
4
- from datetime import date
4
+ from datetime import date, datetime
5
+ from enum import Enum
5
6
 
6
7
  from hydroqc.contract.common import check_period_data_present
7
8
  from hydroqc.contract.contract_residential import ContractResidential
@@ -10,6 +11,13 @@ from hydroqc.peak.dpc.handler import DPCPeakHandler
10
11
  from hydroqc.types import DPCDataTyping
11
12
 
12
13
 
14
+ class WinterState(str, Enum):
15
+ """Winter period state."""
16
+
17
+ CURRENT = "C" # Current/Active (within winter period)
18
+ FINISHED = "F" # Finished (past winter period)
19
+
20
+
13
21
  def check_dpc_data_present(
14
22
  method: Callable[..., None | str | bool | float | date],
15
23
  ) -> Callable[..., None | str | bool | float | date]:
@@ -26,6 +34,20 @@ def check_dpc_data_present(
26
34
  "Maybe you did a rate change recently. "
27
35
  "This message should disappear at the beginning of the next bill period."
28
36
  )
37
+ return None
38
+
39
+ # Check if winter period data is available
40
+ if (
41
+ "periodesHiver" not in contract._dpc_data
42
+ or not contract._dpc_data.get("periodesHiver")
43
+ or len(contract._dpc_data["periodesHiver"]) == 0
44
+ ):
45
+ contract._logger.info(
46
+ "DPC data is empty or incomplete. "
47
+ "This may occur outside the winter period or during a rate transition."
48
+ )
49
+ return None
50
+
29
51
  return method(contract)
30
52
 
31
53
  return wrapper
@@ -86,6 +108,13 @@ class ContractDPC(ContractResidential):
86
108
  )
87
109
  return self._dpc_data
88
110
 
111
+ def _get_dpc_field(self, field_name: str) -> str | float | int:
112
+ """Get DPC field from periodesHiver data."""
113
+ winter_period = self._dpc_data["periodesHiver"][0]
114
+ if field_name in winter_period:
115
+ return winter_period[field_name] # type: ignore
116
+ raise KeyError(f"Field {field_name} not found in DPC data")
117
+
89
118
  @property
90
119
  @check_period_data_present
91
120
  def cp_lower_price_consumption(self) -> float:
@@ -111,44 +140,63 @@ class ContractDPC(ContractResidential):
111
140
  @check_dpc_data_present
112
141
  def last_update_date(self) -> date:
113
142
  """DPC data last update."""
114
- return date.fromisoformat(self._dpc_data["results"][0]["dateDernMaj"])
143
+ date_str = str(self._get_dpc_field("dateMaj"))
144
+ # Handle ISO format with timezone
145
+ if "T" in date_str:
146
+ return date.fromisoformat(date_str.split("T", maxsplit=1)[0])
147
+ return date.fromisoformat(date_str)
115
148
 
116
149
  @property
117
150
  @check_dpc_data_present
118
151
  def critical_called_hours(self) -> int:
119
152
  """Get number of critical hours."""
120
- return int(self._dpc_data["results"][0]["hrsCritiquesAppelees"])
153
+ return int(self._get_dpc_field("hrsCritiquesAppelees"))
121
154
 
122
155
  @property
123
156
  @check_dpc_data_present
124
157
  def max_critical_called_hours(self) -> int:
125
158
  """Get max number of critical hours."""
126
- return int(self._dpc_data["results"][0]["hrsCritiquesAppeleesMax"])
159
+ return int(self._get_dpc_field("hrsCritiquesAppeleesMax"))
127
160
 
128
161
  @property
129
162
  @check_dpc_data_present
130
163
  def amount_saved_vs_base_rate(self) -> float:
131
164
  """Amount saved or not versus the base rate."""
132
- return self._dpc_data["results"][0]["montantEconPerteVSTarifBase"]
165
+ return float(self._get_dpc_field("montantEconPerteVSTarifBase"))
133
166
 
134
167
  @property
135
168
  @check_dpc_data_present
136
169
  def winter_total_days(self) -> int:
137
- """Get number of winter days."""
138
- return self._dpc_data["results"][0]["nbJoursTotauxHiver"]
170
+ """Get number of winter days (calculated from period dates)."""
171
+ winter = self._dpc_data["periodesHiver"][0]
172
+ start = datetime.fromisoformat(winter["dateDebut"].replace("Z", "+00:00"))
173
+ end = datetime.fromisoformat(winter["dateFin"].replace("Z", "+00:00"))
174
+ return (end - start).days
139
175
 
140
176
  @property
141
177
  @check_dpc_data_present
142
178
  def winter_total_days_last_update(self) -> int:
143
- """Get number of days since winter starts."""
144
- return self._dpc_data["results"][0]["nbJoursDernMaj"]
179
+ """Get number of days since winter starts (calculated from dates)."""
180
+ winter = self._dpc_data["periodesHiver"][0]
181
+ start = datetime.fromisoformat(winter["dateDebut"].replace("Z", "+00:00"))
182
+ update = datetime.fromisoformat(winter["dateMaj"].replace("Z", "+00:00"))
183
+ return (update - start).days
145
184
 
146
185
  @property
147
186
  @check_dpc_data_present
148
- def winter_state(self) -> str:
149
- """Get winter state.
187
+ def winter_state(self) -> WinterState:
188
+ """Get winter state (computed from dates).
150
189
 
151
- C: started
152
- ?: ???????
190
+ Returns:
191
+ WinterState.CURRENT: Within winter period
192
+ WinterState.FINISHED: Past winter period
153
193
  """
154
- return self._dpc_data["results"][0]["etatHiver"]
194
+ winter = self._dpc_data["periodesHiver"][0]
195
+ now = datetime.now(
196
+ datetime.fromisoformat(winter["dateDebut"].replace("Z", "+00:00")).tzinfo
197
+ )
198
+ start = datetime.fromisoformat(winter["dateDebut"].replace("Z", "+00:00"))
199
+ end = datetime.fromisoformat(winter["dateFin"].replace("Z", "+00:00"))
200
+ if start <= now <= end:
201
+ return WinterState.CURRENT
202
+ return WinterState.FINISHED
@@ -862,12 +862,16 @@ class HydroClient:
862
862
  ) -> DPCDataTyping:
863
863
  """Fetch FlexD data of the current year.
864
864
 
865
- API URL: https://cl-ec-spring.hydroquebec.com/portail/fr/group/clientele/
866
- portrait-de-consommation/resourceObtenirDonneesMoisHiverFlex
865
+ API URL: https://services-cl.solutions.hydroquebec.com/wsapi/web/prive/api/
866
+ v3_0/tarificationDynamique/tarifPointeCritique
867
867
 
868
868
  """
869
869
  await self._select_contract(applicant_id, customer_id, contract_id)
870
- api_call_response = await self.http_request(FLEXD_DATA_URL, "get")
870
+ headers = await self._get_customer_http_headers(applicant_id, customer_id)
871
+ params = {"noContrat": contract_id}
872
+ api_call_response = await self.http_request(
873
+ FLEXD_DATA_URL, "get", params=params, headers=headers
874
+ )
871
875
  # We can not use res.json() because the response header are not application/json
872
876
  data: DPCDataTyping = self._load_json(await api_call_response.text())
873
877
  return data
@@ -57,8 +57,8 @@ OPEN_DATA_PEAK_URL = (
57
57
  RELATION_URL = f"{HOST_SERVICES}/wsapi/web/prive/api/v1_0/relations"
58
58
 
59
59
  FLEXD_DATA_URL = (
60
- f"{HOST_SERVICES}/lsw/portail/fr/group/clientele/portrait-de-consommation/"
61
- "resourceObtenirDonneesMoisHiverFlex"
60
+ f"{HOST_SERVICES}/wsapi/web/prive/api/v3_0/"
61
+ "tarificationDynamique/tarifPointeCritique"
62
62
  )
63
63
  FLEXD_PEAK_URL = f"{HOST_SERVICES}/conso/portraitweb/api/v3_0/conso"
64
64
  CONSO_CSV_URL = (
@@ -17,13 +17,13 @@ from hydroqc.types.consump import (
17
17
  ConsumpDailyTyping,
18
18
  ConsumpHourlyTyping,
19
19
  ConsumpMonthlyTyping,
20
- DPCDataTyping,
21
20
  DPCPeakDataTyping,
22
21
  DPCPeakListDataTyping,
23
- DTDataTyping,
24
22
  )
25
23
  from hydroqc.types.contract import ContractTyping, ListContractsTyping
26
24
  from hydroqc.types.cpc import CPCDataTyping, CriticalPeakDataTyping, PeriodDataTyping
25
+ from hydroqc.types.dpc import DPCDataTyping
26
+ from hydroqc.types.dt import DTDataTyping
27
27
  from hydroqc.types.outage import (
28
28
  OutageCause,
29
29
  OutageCode,
@@ -169,23 +169,6 @@ class DPCDataResultsTyping(TypedDict, total=True):
169
169
  etatHiver: str
170
170
 
171
171
 
172
- class DPCDataTyping(TypedDict, total=True):
173
- """FlexD data json output format."""
174
-
175
- success: bool
176
- results: list[DPCDataResultsTyping]
177
-
178
-
179
- DTDataResultsTyping = DPCDataResultsTyping
180
-
181
-
182
- class DTDataTyping(TypedDict, total=True):
183
- """FlexD data json output format."""
184
-
185
- success: bool
186
- results: list[DTDataResultsTyping]
187
-
188
-
189
172
  class DPCPeakDataTyping(TypedDict, total=True):
190
173
  """DPC Peak data json output format."""
191
174
 
@@ -4,25 +4,42 @@
4
4
  from typing import TypedDict
5
5
 
6
6
 
7
- class DPCDataResultsTyping(TypedDict, total=True):
8
- """FlexD data json sub output format."""
7
+ class DPCPeriodeHiverTyping(TypedDict, total=True):
8
+ """FlexD winter period data (API v3_0 format)."""
9
9
 
10
10
  dateDebut: str
11
11
  dateFin: str
12
- dateDernMaj: str
12
+ dateMaj: str
13
13
  hrsCritiquesAppelees: str
14
14
  hrsCritiquesAppeleesMax: str
15
15
  montantEconPerteVSTarifBase: float
16
- nbJoursTotauxHiver: int
17
- nbJoursDernMaj: int
18
- etatHiver: str
19
16
 
20
17
 
21
- class DPCDataTyping(TypedDict, total=True):
22
- """FlexD data json output format."""
18
+ class DPCEvenementPointeTyping(TypedDict, total=True):
19
+ """FlexD peak event data (API v3_0 format)."""
23
20
 
24
- success: bool
25
- results: list[DPCDataResultsTyping]
21
+ dateEvenement: str
22
+ heureDebut: str
23
+ heureFin: str
24
+ consoReelle: float
25
+ codeConso: str
26
+ indFacture: bool
27
+
28
+
29
+ class DPCEvenementsPointeWrapperTyping(TypedDict, total=True):
30
+ """FlexD peak events wrapper (API v3_0 format)."""
31
+
32
+ dateDebutPeriodeHiver: str
33
+ dateFinPeriodeHiver: str
34
+ evenementsPointe: list[DPCEvenementPointeTyping]
35
+
36
+
37
+ class DPCDataTyping(TypedDict, total=False):
38
+ """FlexD data json output format (API v3_0)."""
39
+
40
+ dateTestAffichageWeb: str
41
+ periodesHiver: list[DPCPeriodeHiverTyping]
42
+ evenementsPointe: list[DPCEvenementsPointeWrapperTyping]
26
43
 
27
44
 
28
45
  class DPCPeakDataTyping(TypedDict, total=True):
@@ -0,0 +1,25 @@
1
+ """Hydroqc custom types."""
2
+
3
+ # pylint: disable=invalid-name
4
+ from typing import TypedDict
5
+
6
+
7
+ class DTDataResultsTyping(TypedDict, total=True):
8
+ """DT winter period data (legacy format)."""
9
+
10
+ dateDebut: str
11
+ dateFin: str
12
+ dateDernMaj: str
13
+ hrsCritiquesAppelee: str
14
+ hrsCritiquesAppeleesMax: str
15
+ montantEconPerteVSTarifBase: float
16
+ nbJoursTotauxHiver: int
17
+ nbJoursDernMaj: int
18
+ etatHiver: str
19
+
20
+
21
+ class DTDataTyping(TypedDict, total=True):
22
+ """FlexD data json output format."""
23
+
24
+ success: bool
25
+ results: list[DTDataResultsTyping]
@@ -4,8 +4,8 @@ parameterized==0.9.0
4
4
  pylint==4.0.2
5
5
  pytest==8.4.2
6
6
  pytest-cov==7.0.0
7
- pytest-asyncio==1.2.0
8
- black==25.9.0
7
+ pytest-asyncio==1.3.0
8
+ black==25.11.0
9
9
  mypy==1.18.2
10
10
  types-pytz==2025.2.0.20251108
11
11
  types-PyYAML==6.0.12.20250915
@@ -1,15 +0,0 @@
1
- """Hydroqc custom types."""
2
-
3
- # pylint: disable=invalid-name
4
- from typing import TypedDict
5
-
6
- from hydroqc.types.dpc import DPCDataResultsTyping
7
-
8
- DTDataResultsTyping = DPCDataResultsTyping
9
-
10
-
11
- class DTDataTyping(TypedDict, total=True):
12
- """FlexD data json output format."""
13
-
14
- success: bool
15
- results: list[DTDataResultsTyping]