s2-python 0.2.1__tar.gz → 0.3.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 (65) hide show
  1. {s2_python-0.2.1 → s2_python-0.3.0}/PKG-INFO +14 -2
  2. {s2_python-0.2.1 → s2_python-0.3.0}/README.rst +12 -0
  3. {s2_python-0.2.1 → s2_python-0.3.0}/setup.cfg +2 -2
  4. {s2_python-0.2.1 → s2_python-0.3.0}/src/s2_python.egg-info/PKG-INFO +14 -2
  5. {s2_python-0.2.1 → s2_python-0.3.0}/src/s2_python.egg-info/SOURCES.txt +1 -0
  6. {s2_python-0.2.1 → s2_python-0.3.0}/src/s2_python.egg-info/requires.txt +1 -1
  7. s2_python-0.3.0/src/s2python/common/number_range.py +22 -0
  8. s2_python-0.3.0/src/s2python/frbc/frbc_fill_level_target_profile_element.py +34 -0
  9. s2_python-0.3.0/src/s2python/frbc/frbc_leakage_behaviour_element.py +30 -0
  10. s2_python-0.3.0/src/s2python/py.typed +0 -0
  11. {s2_python-0.2.1 → s2_python-0.3.0}/src/s2python/s2_connection.py +81 -38
  12. s2_python-0.2.1/src/s2python/common/number_range.py +0 -32
  13. s2_python-0.2.1/src/s2python/frbc/frbc_fill_level_target_profile_element.py +0 -23
  14. s2_python-0.2.1/src/s2python/frbc/frbc_leakage_behaviour_element.py +0 -18
  15. {s2_python-0.2.1 → s2_python-0.3.0}/pyproject.toml +0 -0
  16. {s2_python-0.2.1 → s2_python-0.3.0}/setup.py +0 -0
  17. {s2_python-0.2.1 → s2_python-0.3.0}/src/s2_python.egg-info/dependency_links.txt +0 -0
  18. {s2_python-0.2.1 → s2_python-0.3.0}/src/s2_python.egg-info/entry_points.txt +0 -0
  19. {s2_python-0.2.1 → s2_python-0.3.0}/src/s2_python.egg-info/not-zip-safe +0 -0
  20. {s2_python-0.2.1 → s2_python-0.3.0}/src/s2_python.egg-info/top_level.txt +0 -0
  21. {s2_python-0.2.1 → s2_python-0.3.0}/src/s2python/__init__.py +0 -0
  22. {s2_python-0.2.1 → s2_python-0.3.0}/src/s2python/common/__init__.py +0 -0
  23. {s2_python-0.2.1 → s2_python-0.3.0}/src/s2python/common/duration.py +0 -0
  24. {s2_python-0.2.1 → s2_python-0.3.0}/src/s2python/common/handshake.py +0 -0
  25. {s2_python-0.2.1 → s2_python-0.3.0}/src/s2python/common/handshake_response.py +0 -0
  26. {s2_python-0.2.1 → s2_python-0.3.0}/src/s2python/common/instruction_status_update.py +0 -0
  27. {s2_python-0.2.1 → s2_python-0.3.0}/src/s2python/common/power_forecast.py +0 -0
  28. {s2_python-0.2.1 → s2_python-0.3.0}/src/s2python/common/power_forecast_element.py +0 -0
  29. {s2_python-0.2.1 → s2_python-0.3.0}/src/s2python/common/power_forecast_value.py +0 -0
  30. {s2_python-0.2.1 → s2_python-0.3.0}/src/s2python/common/power_measurement.py +0 -0
  31. {s2_python-0.2.1 → s2_python-0.3.0}/src/s2python/common/power_range.py +0 -0
  32. {s2_python-0.2.1 → s2_python-0.3.0}/src/s2python/common/power_value.py +0 -0
  33. {s2_python-0.2.1 → s2_python-0.3.0}/src/s2python/common/reception_status.py +0 -0
  34. {s2_python-0.2.1 → s2_python-0.3.0}/src/s2python/common/resource_manager_details.py +0 -0
  35. {s2_python-0.2.1 → s2_python-0.3.0}/src/s2python/common/revoke_object.py +0 -0
  36. {s2_python-0.2.1 → s2_python-0.3.0}/src/s2python/common/role.py +0 -0
  37. {s2_python-0.2.1 → s2_python-0.3.0}/src/s2python/common/select_control_type.py +0 -0
  38. {s2_python-0.2.1 → s2_python-0.3.0}/src/s2python/common/session_request.py +0 -0
  39. {s2_python-0.2.1 → s2_python-0.3.0}/src/s2python/common/support.py +0 -0
  40. {s2_python-0.2.1 → s2_python-0.3.0}/src/s2python/common/timer.py +0 -0
  41. {s2_python-0.2.1 → s2_python-0.3.0}/src/s2python/common/transition.py +0 -0
  42. {s2_python-0.2.1 → s2_python-0.3.0}/src/s2python/frbc/__init__.py +0 -0
  43. {s2_python-0.2.1 → s2_python-0.3.0}/src/s2python/frbc/frbc_actuator_description.py +0 -0
  44. {s2_python-0.2.1 → s2_python-0.3.0}/src/s2python/frbc/frbc_actuator_status.py +0 -0
  45. {s2_python-0.2.1 → s2_python-0.3.0}/src/s2python/frbc/frbc_fill_level_target_profile.py +0 -0
  46. {s2_python-0.2.1 → s2_python-0.3.0}/src/s2python/frbc/frbc_instruction.py +0 -0
  47. {s2_python-0.2.1 → s2_python-0.3.0}/src/s2python/frbc/frbc_leakage_behaviour.py +0 -0
  48. {s2_python-0.2.1 → s2_python-0.3.0}/src/s2python/frbc/frbc_operation_mode.py +0 -0
  49. {s2_python-0.2.1 → s2_python-0.3.0}/src/s2python/frbc/frbc_operation_mode_element.py +0 -0
  50. {s2_python-0.2.1 → s2_python-0.3.0}/src/s2python/frbc/frbc_storage_description.py +0 -0
  51. {s2_python-0.2.1 → s2_python-0.3.0}/src/s2python/frbc/frbc_storage_status.py +0 -0
  52. {s2_python-0.2.1 → s2_python-0.3.0}/src/s2python/frbc/frbc_system_description.py +0 -0
  53. {s2_python-0.2.1 → s2_python-0.3.0}/src/s2python/frbc/frbc_timer_status.py +0 -0
  54. {s2_python-0.2.1 → s2_python-0.3.0}/src/s2python/frbc/frbc_usage_forecast.py +0 -0
  55. {s2_python-0.2.1 → s2_python-0.3.0}/src/s2python/frbc/frbc_usage_forecast_element.py +0 -0
  56. {s2_python-0.2.1 → s2_python-0.3.0}/src/s2python/frbc/rm.py +0 -0
  57. {s2_python-0.2.1 → s2_python-0.3.0}/src/s2python/generated/__init__.py +0 -0
  58. {s2_python-0.2.1 → s2_python-0.3.0}/src/s2python/generated/gen_s2.py +0 -0
  59. {s2_python-0.2.1 → s2_python-0.3.0}/src/s2python/reception_status_awaiter.py +0 -0
  60. {s2_python-0.2.1 → s2_python-0.3.0}/src/s2python/s2_control_type.py +0 -0
  61. {s2_python-0.2.1 → s2_python-0.3.0}/src/s2python/s2_parser.py +0 -0
  62. {s2_python-0.2.1 → s2_python-0.3.0}/src/s2python/s2_validation_error.py +0 -0
  63. {s2_python-0.2.1 → s2_python-0.3.0}/src/s2python/utils.py +0 -0
  64. {s2_python-0.2.1 → s2_python-0.3.0}/src/s2python/validate_values_mixin.py +0 -0
  65. {s2_python-0.2.1 → s2_python-0.3.0}/src/s2python/version.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: s2-python
3
- Version: 0.2.1
3
+ Version: 0.3.0
4
4
  Summary: S2 Protocol Python Wrapper
5
5
  Home-page: https://github.com/flexiblepower/s2-ws-json-python
6
6
  Author: Flexiblepower
@@ -17,7 +17,7 @@ Description-Content-Type: text/x-rst; charset=UTF-8
17
17
  Requires-Dist: pydantic~=2.8.2
18
18
  Requires-Dist: pytz
19
19
  Requires-Dist: click
20
- Requires-Dist: websockets~=13.0.1
20
+ Requires-Dist: websockets~=13.1
21
21
  Provides-Extra: testing
22
22
  Requires-Dist: pytest; extra == "testing"
23
23
  Requires-Dist: pytest-coverage; extra == "testing"
@@ -62,6 +62,18 @@ You can install this package using pip or any Python dependency manager that col
62
62
 
63
63
  The packages on Pypi may be found `here <https://pypi.org/project/s2-python/>`_
64
64
 
65
+ Mypy support
66
+ ------------
67
+ s2-python uses pydantic at its core to define the various S2 messages. As such, the pydantic mypy plugin is required
68
+ for type checking to succeed.
69
+
70
+ Add to your pyproject.toml:
71
+
72
+ .. code-block:: toml
73
+
74
+ [tool.mypy]
75
+ plugins = ['pydantic.mypy']
76
+
65
77
  Example
66
78
  ---------
67
79
 
@@ -22,6 +22,18 @@ You can install this package using pip or any Python dependency manager that col
22
22
 
23
23
  The packages on Pypi may be found `here <https://pypi.org/project/s2-python/>`_
24
24
 
25
+ Mypy support
26
+ ------------
27
+ s2-python uses pydantic at its core to define the various S2 messages. As such, the pydantic mypy plugin is required
28
+ for type checking to succeed.
29
+
30
+ Add to your pyproject.toml:
31
+
32
+ .. code-block:: toml
33
+
34
+ [tool.mypy]
35
+ plugins = ['pydantic.mypy']
36
+
25
37
  Example
26
38
  ---------
27
39
 
@@ -8,7 +8,7 @@ license_files = LICENSE.txt
8
8
  long_description = file: README.rst
9
9
  long_description_content_type = text/x-rst; charset=UTF-8
10
10
  url = https://github.com/flexiblepower/s2-ws-json-python
11
- version = 0.2.1
11
+ version = 0.3.0
12
12
  platforms = Linux
13
13
  classifiers =
14
14
  Development Status :: 4 - Beta
@@ -29,7 +29,7 @@ install_requires =
29
29
  pydantic~=2.8.2
30
30
  pytz
31
31
  click
32
- websockets~=13.0.1
32
+ websockets~=13.1
33
33
 
34
34
  [options.packages.find]
35
35
  where = src
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: s2-python
3
- Version: 0.2.1
3
+ Version: 0.3.0
4
4
  Summary: S2 Protocol Python Wrapper
5
5
  Home-page: https://github.com/flexiblepower/s2-ws-json-python
6
6
  Author: Flexiblepower
@@ -17,7 +17,7 @@ Description-Content-Type: text/x-rst; charset=UTF-8
17
17
  Requires-Dist: pydantic~=2.8.2
18
18
  Requires-Dist: pytz
19
19
  Requires-Dist: click
20
- Requires-Dist: websockets~=13.0.1
20
+ Requires-Dist: websockets~=13.1
21
21
  Provides-Extra: testing
22
22
  Requires-Dist: pytest; extra == "testing"
23
23
  Requires-Dist: pytest-coverage; extra == "testing"
@@ -62,6 +62,18 @@ You can install this package using pip or any Python dependency manager that col
62
62
 
63
63
  The packages on Pypi may be found `here <https://pypi.org/project/s2-python/>`_
64
64
 
65
+ Mypy support
66
+ ------------
67
+ s2-python uses pydantic at its core to define the various S2 messages. As such, the pydantic mypy plugin is required
68
+ for type checking to succeed.
69
+
70
+ Add to your pyproject.toml:
71
+
72
+ .. code-block:: toml
73
+
74
+ [tool.mypy]
75
+ plugins = ['pydantic.mypy']
76
+
65
77
  Example
66
78
  ---------
67
79
 
@@ -10,6 +10,7 @@ src/s2_python.egg-info/not-zip-safe
10
10
  src/s2_python.egg-info/requires.txt
11
11
  src/s2_python.egg-info/top_level.txt
12
12
  src/s2python/__init__.py
13
+ src/s2python/py.typed
13
14
  src/s2python/reception_status_awaiter.py
14
15
  src/s2python/s2_connection.py
15
16
  src/s2python/s2_control_type.py
@@ -1,7 +1,7 @@
1
1
  pydantic~=2.8.2
2
2
  pytz
3
3
  click
4
- websockets~=13.0.1
4
+ websockets~=13.1
5
5
 
6
6
  [development]
7
7
  pip-tools
@@ -0,0 +1,22 @@
1
+ from typing import Any
2
+
3
+ from s2python.validate_values_mixin import S2Message, catch_and_convert_exceptions
4
+ from s2python.generated.gen_s2 import NumberRange as GenNumberRange
5
+
6
+
7
+ @catch_and_convert_exceptions
8
+ class NumberRange(GenNumberRange, S2Message["NumberRange"]):
9
+ model_config = GenNumberRange.model_config
10
+ model_config["validate_assignment"] = True
11
+
12
+ def __hash__(self) -> int:
13
+ return hash(f"{self.start_of_range}|{self.end_of_range}")
14
+
15
+ def __eq__(self, other: Any) -> bool:
16
+ if isinstance(other, NumberRange):
17
+ return (
18
+ self.start_of_range == other.start_of_range
19
+ and self.end_of_range == other.end_of_range
20
+ )
21
+
22
+ return False
@@ -0,0 +1,34 @@
1
+ # pylint: disable=duplicate-code
2
+
3
+ from typing_extensions import Self
4
+
5
+ from pydantic import model_validator
6
+
7
+ from s2python.common import Duration, NumberRange
8
+ from s2python.generated.gen_s2 import (
9
+ FRBCFillLevelTargetProfileElement as GenFRBCFillLevelTargetProfileElement,
10
+ )
11
+ from s2python.validate_values_mixin import catch_and_convert_exceptions, S2Message
12
+
13
+
14
+ @catch_and_convert_exceptions
15
+ class FRBCFillLevelTargetProfileElement(
16
+ GenFRBCFillLevelTargetProfileElement, S2Message["FRBCFillLevelTargetProfileElement"]
17
+ ):
18
+ model_config = GenFRBCFillLevelTargetProfileElement.model_config
19
+ model_config["validate_assignment"] = True
20
+
21
+ duration: Duration = GenFRBCFillLevelTargetProfileElement.model_fields["duration"] # type: ignore[assignment]
22
+ fill_level_range: NumberRange = GenFRBCFillLevelTargetProfileElement.model_fields[
23
+ "fill_level_range"
24
+ ] # type: ignore[assignment]
25
+
26
+ @model_validator(mode="after")
27
+ def validate_start_end_order(self) -> Self:
28
+ if self.fill_level_range.start_of_range > self.fill_level_range.end_of_range:
29
+ raise ValueError(
30
+ self,
31
+ "start_of_range should not be higher than end_of_range for the fill_level_range",
32
+ )
33
+
34
+ return self
@@ -0,0 +1,30 @@
1
+ # pylint: disable=duplicate-code
2
+
3
+ from pydantic import model_validator
4
+ from typing_extensions import Self
5
+
6
+ from s2python.common import NumberRange
7
+ from s2python.generated.gen_s2 import FRBCLeakageBehaviourElement as GenFRBCLeakageBehaviourElement
8
+ from s2python.validate_values_mixin import catch_and_convert_exceptions, S2Message
9
+
10
+
11
+ @catch_and_convert_exceptions
12
+ class FRBCLeakageBehaviourElement(
13
+ GenFRBCLeakageBehaviourElement, S2Message["FRBCLeakageBehaviourElement"]
14
+ ):
15
+ model_config = GenFRBCLeakageBehaviourElement.model_config
16
+ model_config["validate_assignment"] = True
17
+
18
+ fill_level_range: NumberRange = GenFRBCLeakageBehaviourElement.model_fields[
19
+ "fill_level_range"
20
+ ] # type: ignore[assignment]
21
+
22
+ @model_validator(mode="after")
23
+ def validate_start_end_order(self) -> Self:
24
+ if self.fill_level_range.start_of_range > self.fill_level_range.end_of_range:
25
+ raise ValueError(
26
+ self,
27
+ "start_of_range should not be higher than end_of_range for the fill_level_range",
28
+ )
29
+
30
+ return self
File without changes
@@ -1,6 +1,7 @@
1
1
  import asyncio
2
2
  import json
3
3
  import logging
4
+ import time
4
5
  import threading
5
6
  import uuid
6
7
  from dataclasses import dataclass
@@ -180,6 +181,7 @@ class MessageHandlers:
180
181
 
181
182
  class S2Connection: # pylint: disable=too-many-instance-attributes
182
183
  url: str
184
+ reconnect: bool
183
185
  reception_status_awaiter: ReceptionStatusAwaiter
184
186
  ws: Optional[WSConnection]
185
187
  s2_parser: S2Parser
@@ -195,16 +197,20 @@ class S2Connection: # pylint: disable=too-many-instance-attributes
195
197
 
196
198
  _eventloop: asyncio.AbstractEventLoop
197
199
  _stop_event: asyncio.Event
200
+ _restart_connection_event: asyncio.Event
198
201
 
199
- def __init__(
202
+ def __init__( # pylint: disable=too-many-arguments
200
203
  self,
201
204
  url: str,
202
205
  role: EnergyManagementRole,
203
206
  control_types: List[S2ControlType],
204
207
  asset_details: AssetDetails,
208
+ reconnect: bool = False,
205
209
  ) -> None:
206
210
  self.url = url
211
+ self.reconnect = reconnect
207
212
  self.reception_status_awaiter = ReceptionStatusAwaiter()
213
+ self.ws = None
208
214
  self.s2_parser = S2Parser()
209
215
 
210
216
  self._handlers = MessageHandlers()
@@ -221,14 +227,13 @@ class S2Connection: # pylint: disable=too-many-instance-attributes
221
227
  self._handlers.register_handler(HandshakeResponse, self.handle_handshake_response_as_rm)
222
228
 
223
229
  def start_as_rm(self) -> None:
224
- self._thread = threading.Thread(target=self._run_eventloop, daemon=False)
225
- self._thread.start()
226
- logger.debug("Started eventloop thread!")
230
+ self._run_eventloop(self._run_as_rm())
227
231
 
228
- def _run_eventloop(self) -> None:
232
+ def _run_eventloop(self, main_task: Awaitable[None]) -> None:
233
+ self._thread = threading.current_thread()
229
234
  logger.debug("Starting eventloop")
230
235
  try:
231
- self._eventloop.run_until_complete(self._run_as_rm())
236
+ self._eventloop.run_until_complete(main_task)
232
237
  except asyncio.CancelledError:
233
238
  pass
234
239
  logger.debug("S2 connection thread has stopped.")
@@ -256,45 +261,69 @@ class S2Connection: # pylint: disable=too-many-instance-attributes
256
261
 
257
262
  async def _run_as_rm(self) -> None:
258
263
  logger.debug("Connecting as S2 resource manager.")
259
- self._received_messages = asyncio.Queue()
264
+
260
265
  self._stop_event = asyncio.Event()
261
- await self.connect_ws()
262
266
 
263
- background_tasks = []
264
- background_tasks.append(self._eventloop.create_task(self._receive_messages()))
265
- background_tasks.append(self._eventloop.create_task(self._handle_received_messages()))
267
+ first_run = True
266
268
 
267
- async def wait_till_stop() -> None:
268
- await self._stop_event.wait()
269
+ while (first_run or self.reconnect) and not self._stop_event.is_set():
270
+ first_run = False
271
+ self._restart_connection_event = asyncio.Event()
272
+ await self._connect_and_run()
273
+ time.sleep(1)
269
274
 
270
- background_tasks.append(self._eventloop.create_task(wait_till_stop()))
275
+ logger.debug("Finished S2 connection eventloop.")
271
276
 
272
- await self.connect_as_rm()
273
- (done, pending) = await asyncio.wait(background_tasks, return_when=asyncio.FIRST_COMPLETED)
274
- for task in done:
275
- try:
276
- await task
277
- except asyncio.CancelledError:
278
- pass
279
- except websockets.ConnectionClosedError:
280
- logger.info("The other party closed the websocket connection.c")
277
+ async def _connect_and_run(self) -> None:
278
+ self._received_messages = asyncio.Queue()
279
+ await self._connect_ws()
280
+ if self.ws:
281
281
 
282
- for task in pending:
283
- try:
284
- task.cancel()
285
- await task
286
- except asyncio.CancelledError:
287
- pass
282
+ async def wait_till_stop() -> None:
283
+ await self._stop_event.wait()
284
+
285
+ async def wait_till_connection_restart() -> None:
286
+ await self._restart_connection_event.wait()
287
+
288
+ background_tasks = [
289
+ self._eventloop.create_task(self._receive_messages()),
290
+ self._eventloop.create_task(wait_till_stop()),
291
+ self._eventloop.create_task(self._connect_as_rm()),
292
+ self._eventloop.create_task(wait_till_connection_restart()),
293
+ ]
294
+
295
+ (done, pending) = await asyncio.wait(
296
+ background_tasks, return_when=asyncio.FIRST_COMPLETED
297
+ )
298
+ if self._current_control_type:
299
+ self._current_control_type.deactivate(self)
300
+ self._current_control_type = None
301
+
302
+ for task in done:
303
+ try:
304
+ await task
305
+ except asyncio.CancelledError:
306
+ pass
307
+ except (websockets.ConnectionClosedError, websockets.ConnectionClosedOK):
308
+ logger.info("The other party closed the websocket connection.")
309
+
310
+ for task in pending:
311
+ try:
312
+ task.cancel()
313
+ await task
314
+ except asyncio.CancelledError:
315
+ pass
288
316
 
289
- if self.ws:
290
317
  await self.ws.close()
291
318
  await self.ws.wait_closed()
292
- logger.debug("Finished S2 connection eventloop.")
293
319
 
294
- async def connect_ws(self) -> None:
295
- self.ws = await ws_connect(uri=self.url)
320
+ async def _connect_ws(self) -> None:
321
+ try:
322
+ self.ws = await ws_connect(uri=self.url)
323
+ except (EOFError, OSError) as e:
324
+ logger.info("Could not connect due to: %s", str(e))
296
325
 
297
- async def connect_as_rm(self) -> None:
326
+ async def _connect_as_rm(self) -> None:
298
327
  await self.send_msg_and_await_reception_status_async(
299
328
  Handshake(
300
329
  message_id=uuid.uuid4(), role=self.role, supported_protocol_versions=[S2_VERSION]
@@ -302,6 +331,8 @@ class S2Connection: # pylint: disable=too-many-instance-attributes
302
331
  )
303
332
  logger.debug("Send handshake to CEM. Expecting Handshake and HandshakeResponse from CEM.")
304
333
 
334
+ await self._handle_received_messages()
335
+
305
336
  async def handle_handshake(
306
337
  self, _: "S2Connection", message: S2Message, send_okay: Awaitable[None]
307
338
  ) -> None:
@@ -427,7 +458,11 @@ class S2Connection: # pylint: disable=too-many-instance-attributes
427
458
 
428
459
  json_msg = s2_msg.to_json()
429
460
  logger.debug("Sending message %s", json_msg)
430
- await self.ws.send(json_msg)
461
+ try:
462
+ await self.ws.send(json_msg)
463
+ except websockets.ConnectionClosedError as e:
464
+ logger.error("Unable to send message %s due to %s", s2_msg, str(e))
465
+ self._restart_connection_event.set()
431
466
 
432
467
  async def respond_with_reception_status(
433
468
  self, subject_message_id: str, status: ReceptionStatusValues, diagnostic_label: str
@@ -458,9 +493,17 @@ class S2Connection: # pylint: disable=too-many-instance-attributes
458
493
  s2_msg.message_id, # type: ignore[attr-defined]
459
494
  timeout_reception_status,
460
495
  )
461
- reception_status = await self.reception_status_awaiter.wait_for_reception_status(
462
- s2_msg.message_id, timeout_reception_status # type: ignore[attr-defined]
463
- )
496
+ try:
497
+ reception_status = await self.reception_status_awaiter.wait_for_reception_status(
498
+ s2_msg.message_id, timeout_reception_status # type: ignore[attr-defined]
499
+ )
500
+ except TimeoutError:
501
+ logger.error(
502
+ "Did not receive a reception status on time for %s",
503
+ s2_msg.message_id, # type: ignore[attr-defined]
504
+ )
505
+ self._stop_event.set()
506
+ raise
464
507
 
465
508
  if reception_status.status != ReceptionStatusValues.OK and raise_on_error:
466
509
  raise RuntimeError(f"ReceptionStatus was not OK but rather {reception_status.status}")
@@ -1,32 +0,0 @@
1
- from typing import Any
2
- from typing_extensions import Self
3
-
4
- from pydantic import model_validator
5
-
6
- from s2python.validate_values_mixin import (
7
- S2Message,
8
- catch_and_convert_exceptions,
9
- )
10
- from s2python.generated.gen_s2 import NumberRange as GenNumberRange
11
-
12
-
13
- @catch_and_convert_exceptions
14
- class NumberRange(GenNumberRange, S2Message["NumberRange"]):
15
- model_config = GenNumberRange.model_config
16
- model_config["validate_assignment"] = True
17
-
18
- @model_validator(mode="after")
19
- def validate_start_end_order(self) -> Self: # pylint: disable=duplicate-code
20
- if self.start_of_range > self.end_of_range:
21
- raise ValueError(self, "start_of_range should not be higher than end_of_range")
22
-
23
- return self
24
-
25
- def __hash__(self) -> int:
26
- return hash(f"{self.start_of_range}|{self.end_of_range}")
27
-
28
- def __eq__(self, other: Any) -> bool:
29
- if isinstance(other, NumberRange):
30
- return self.start_of_range == other.start_of_range and self.end_of_range == other.end_of_range
31
-
32
- return False
@@ -1,23 +0,0 @@
1
- from s2python.common import Duration, NumberRange
2
-
3
- from s2python.generated.gen_s2 import (
4
- FRBCFillLevelTargetProfileElement as GenFRBCFillLevelTargetProfileElement,
5
- )
6
- from s2python.validate_values_mixin import (
7
- catch_and_convert_exceptions,
8
- S2Message,
9
- )
10
-
11
-
12
- @catch_and_convert_exceptions
13
- class FRBCFillLevelTargetProfileElement(
14
- GenFRBCFillLevelTargetProfileElement,
15
- S2Message["FRBCFillLevelTargetProfileElement"],
16
- ):
17
- model_config = GenFRBCFillLevelTargetProfileElement.model_config
18
- model_config["validate_assignment"] = True
19
-
20
- duration: Duration = GenFRBCFillLevelTargetProfileElement.model_fields["duration"] # type: ignore[assignment]
21
- fill_level_range: NumberRange = GenFRBCFillLevelTargetProfileElement.model_fields[
22
- "fill_level_range"
23
- ] # type: ignore[assignment]
@@ -1,18 +0,0 @@
1
- from s2python.common import NumberRange
2
- from s2python.generated.gen_s2 import (
3
- FRBCLeakageBehaviourElement as GenFRBCLeakageBehaviourElement,
4
- )
5
- from s2python.validate_values_mixin import (
6
- catch_and_convert_exceptions,
7
- S2Message,
8
- )
9
-
10
-
11
- @catch_and_convert_exceptions
12
- class FRBCLeakageBehaviourElement(GenFRBCLeakageBehaviourElement, S2Message["FRBCLeakageBehaviourElement"]):
13
- model_config = GenFRBCLeakageBehaviourElement.model_config
14
- model_config["validate_assignment"] = True
15
-
16
- fill_level_range: NumberRange = GenFRBCLeakageBehaviourElement.model_fields[
17
- "fill_level_range"
18
- ] # type: ignore[assignment]
File without changes
File without changes