s2-python 0.6.0__tar.gz → 0.7.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 (165) hide show
  1. {s2_python-0.6.0/src/s2_python.egg-info → s2_python-0.7.0}/PKG-INFO +1 -3
  2. {s2_python-0.6.0 → s2_python-0.7.0}/README.rst +0 -2
  3. {s2_python-0.6.0 → s2_python-0.7.0/src/s2_python.egg-info}/PKG-INFO +1 -3
  4. {s2_python-0.6.0 → s2_python-0.7.0}/src/s2_python.egg-info/SOURCES.txt +1 -0
  5. {s2_python-0.6.0 → s2_python-0.7.0}/src/s2python/common/power_forecast_element.py +2 -2
  6. {s2_python-0.6.0 → s2_python-0.7.0}/src/s2python/common/power_measurement.py +2 -2
  7. {s2_python-0.6.0 → s2_python-0.7.0}/src/s2python/ombc/ombc_operation_mode.py +1 -1
  8. {s2_python-0.6.0 → s2_python-0.7.0}/src/s2python/ombc/ombc_system_description.py +1 -1
  9. {s2_python-0.6.0 → s2_python-0.7.0}/src/s2python/s2_parser.py +1 -2
  10. s2_python-0.7.0/src/s2python/s2_validation_error.py +9 -0
  11. {s2_python-0.6.0 → s2_python-0.7.0}/src/s2python/validate_values_mixin.py +23 -12
  12. s2_python-0.7.0/tests/unit/inheritance_test.py +51 -0
  13. s2_python-0.6.0/src/s2python/s2_validation_error.py +0 -15
  14. {s2_python-0.6.0 → s2_python-0.7.0}/.github/workflows/ci.yml +0 -0
  15. {s2_python-0.6.0 → s2_python-0.7.0}/.gitignore +0 -0
  16. {s2_python-0.6.0 → s2_python-0.7.0}/.pre-commit-config.yaml +0 -0
  17. {s2_python-0.6.0 → s2_python-0.7.0}/.pylintrc +0 -0
  18. {s2_python-0.6.0 → s2_python-0.7.0}/LICENSE +0 -0
  19. {s2_python-0.6.0 → s2_python-0.7.0}/ci/clean.sh +0 -0
  20. {s2_python-0.6.0 → s2_python-0.7.0}/ci/distribute.sh +0 -0
  21. {s2_python-0.6.0 → s2_python-0.7.0}/ci/generate_s2.sh +0 -0
  22. {s2_python-0.6.0 → s2_python-0.7.0}/ci/install_dependencies.sh +0 -0
  23. {s2_python-0.6.0 → s2_python-0.7.0}/ci/lint.sh +0 -0
  24. {s2_python-0.6.0 → s2_python-0.7.0}/ci/setup_dev_environment.sh +0 -0
  25. {s2_python-0.6.0 → s2_python-0.7.0}/ci/test_unit.sh +0 -0
  26. {s2_python-0.6.0 → s2_python-0.7.0}/ci/typecheck.sh +0 -0
  27. {s2_python-0.6.0 → s2_python-0.7.0}/ci/update_dependencies.sh +0 -0
  28. {s2_python-0.6.0 → s2_python-0.7.0}/dev-requirements.txt +0 -0
  29. {s2_python-0.6.0 → s2_python-0.7.0}/development_utilities/gen_templates.py +0 -0
  30. {s2_python-0.6.0 → s2_python-0.7.0}/development_utilities/gen_unit_test_template.py +0 -0
  31. {s2_python-0.6.0 → s2_python-0.7.0}/development_utilities/generate_s2_message_type_to_class.py +0 -0
  32. {s2_python-0.6.0 → s2_python-0.7.0}/development_utilities/get_all_messages.py +0 -0
  33. {s2_python-0.6.0 → s2_python-0.7.0}/examples/example_frbc_rm.py +0 -0
  34. {s2_python-0.6.0 → s2_python-0.7.0}/mypy.ini +0 -0
  35. {s2_python-0.6.0 → s2_python-0.7.0}/pyproject.toml +0 -0
  36. {s2_python-0.6.0 → s2_python-0.7.0}/pyrightconfig.json +0 -0
  37. {s2_python-0.6.0 → s2_python-0.7.0}/pytest.ini +0 -0
  38. {s2_python-0.6.0 → s2_python-0.7.0}/setup.cfg +0 -0
  39. {s2_python-0.6.0 → s2_python-0.7.0}/setup.py +0 -0
  40. {s2_python-0.6.0 → s2_python-0.7.0}/specification/openapi.yml +0 -0
  41. {s2_python-0.6.0 → s2_python-0.7.0}/src/s2_python.egg-info/dependency_links.txt +0 -0
  42. {s2_python-0.6.0 → s2_python-0.7.0}/src/s2_python.egg-info/entry_points.txt +0 -0
  43. {s2_python-0.6.0 → s2_python-0.7.0}/src/s2_python.egg-info/not-zip-safe +0 -0
  44. {s2_python-0.6.0 → s2_python-0.7.0}/src/s2_python.egg-info/requires.txt +0 -0
  45. {s2_python-0.6.0 → s2_python-0.7.0}/src/s2_python.egg-info/top_level.txt +0 -0
  46. {s2_python-0.6.0 → s2_python-0.7.0}/src/s2python/__init__.py +0 -0
  47. {s2_python-0.6.0 → s2_python-0.7.0}/src/s2python/common/__init__.py +0 -0
  48. {s2_python-0.6.0 → s2_python-0.7.0}/src/s2python/common/duration.py +0 -0
  49. {s2_python-0.6.0 → s2_python-0.7.0}/src/s2python/common/handshake.py +0 -0
  50. {s2_python-0.6.0 → s2_python-0.7.0}/src/s2python/common/handshake_response.py +0 -0
  51. {s2_python-0.6.0 → s2_python-0.7.0}/src/s2python/common/instruction_status_update.py +0 -0
  52. {s2_python-0.6.0 → s2_python-0.7.0}/src/s2python/common/number_range.py +0 -0
  53. {s2_python-0.6.0 → s2_python-0.7.0}/src/s2python/common/power_forecast.py +0 -0
  54. {s2_python-0.6.0 → s2_python-0.7.0}/src/s2python/common/power_forecast_value.py +0 -0
  55. {s2_python-0.6.0 → s2_python-0.7.0}/src/s2python/common/power_range.py +0 -0
  56. {s2_python-0.6.0 → s2_python-0.7.0}/src/s2python/common/power_value.py +0 -0
  57. {s2_python-0.6.0 → s2_python-0.7.0}/src/s2python/common/reception_status.py +0 -0
  58. {s2_python-0.6.0 → s2_python-0.7.0}/src/s2python/common/resource_manager_details.py +0 -0
  59. {s2_python-0.6.0 → s2_python-0.7.0}/src/s2python/common/revoke_object.py +0 -0
  60. {s2_python-0.6.0 → s2_python-0.7.0}/src/s2python/common/role.py +0 -0
  61. {s2_python-0.6.0 → s2_python-0.7.0}/src/s2python/common/select_control_type.py +0 -0
  62. {s2_python-0.6.0 → s2_python-0.7.0}/src/s2python/common/session_request.py +0 -0
  63. {s2_python-0.6.0 → s2_python-0.7.0}/src/s2python/common/support.py +0 -0
  64. {s2_python-0.6.0 → s2_python-0.7.0}/src/s2python/common/timer.py +0 -0
  65. {s2_python-0.6.0 → s2_python-0.7.0}/src/s2python/common/transition.py +0 -0
  66. {s2_python-0.6.0 → s2_python-0.7.0}/src/s2python/ddbc/__init__.py +0 -0
  67. {s2_python-0.6.0 → s2_python-0.7.0}/src/s2python/ddbc/ddbc_actuator_description.py +0 -0
  68. {s2_python-0.6.0 → s2_python-0.7.0}/src/s2python/ddbc/ddbc_actuator_status.py +0 -0
  69. {s2_python-0.6.0 → s2_python-0.7.0}/src/s2python/ddbc/ddbc_average_demand_rate_forecast.py +0 -0
  70. {s2_python-0.6.0 → s2_python-0.7.0}/src/s2python/ddbc/ddbc_average_demand_rate_forecast_element.py +0 -0
  71. {s2_python-0.6.0 → s2_python-0.7.0}/src/s2python/ddbc/ddbc_instruction.py +0 -0
  72. {s2_python-0.6.0 → s2_python-0.7.0}/src/s2python/ddbc/ddbc_operation_mode.py +0 -0
  73. {s2_python-0.6.0 → s2_python-0.7.0}/src/s2python/ddbc/ddbc_system_description.py +0 -0
  74. {s2_python-0.6.0 → s2_python-0.7.0}/src/s2python/ddbc/ddbc_timer_status.py +0 -0
  75. {s2_python-0.6.0 → s2_python-0.7.0}/src/s2python/frbc/__init__.py +0 -0
  76. {s2_python-0.6.0 → s2_python-0.7.0}/src/s2python/frbc/frbc_actuator_description.py +0 -0
  77. {s2_python-0.6.0 → s2_python-0.7.0}/src/s2python/frbc/frbc_actuator_status.py +0 -0
  78. {s2_python-0.6.0 → s2_python-0.7.0}/src/s2python/frbc/frbc_fill_level_target_profile.py +0 -0
  79. {s2_python-0.6.0 → s2_python-0.7.0}/src/s2python/frbc/frbc_fill_level_target_profile_element.py +0 -0
  80. {s2_python-0.6.0 → s2_python-0.7.0}/src/s2python/frbc/frbc_instruction.py +0 -0
  81. {s2_python-0.6.0 → s2_python-0.7.0}/src/s2python/frbc/frbc_leakage_behaviour.py +0 -0
  82. {s2_python-0.6.0 → s2_python-0.7.0}/src/s2python/frbc/frbc_leakage_behaviour_element.py +0 -0
  83. {s2_python-0.6.0 → s2_python-0.7.0}/src/s2python/frbc/frbc_operation_mode.py +0 -0
  84. {s2_python-0.6.0 → s2_python-0.7.0}/src/s2python/frbc/frbc_operation_mode_element.py +0 -0
  85. {s2_python-0.6.0 → s2_python-0.7.0}/src/s2python/frbc/frbc_storage_description.py +0 -0
  86. {s2_python-0.6.0 → s2_python-0.7.0}/src/s2python/frbc/frbc_storage_status.py +0 -0
  87. {s2_python-0.6.0 → s2_python-0.7.0}/src/s2python/frbc/frbc_system_description.py +0 -0
  88. {s2_python-0.6.0 → s2_python-0.7.0}/src/s2python/frbc/frbc_timer_status.py +0 -0
  89. {s2_python-0.6.0 → s2_python-0.7.0}/src/s2python/frbc/frbc_usage_forecast.py +0 -0
  90. {s2_python-0.6.0 → s2_python-0.7.0}/src/s2python/frbc/frbc_usage_forecast_element.py +0 -0
  91. {s2_python-0.6.0 → s2_python-0.7.0}/src/s2python/frbc/rm.py +0 -0
  92. {s2_python-0.6.0 → s2_python-0.7.0}/src/s2python/generated/__init__.py +0 -0
  93. {s2_python-0.6.0 → s2_python-0.7.0}/src/s2python/generated/gen_s2.py +0 -0
  94. {s2_python-0.6.0 → s2_python-0.7.0}/src/s2python/message.py +0 -0
  95. {s2_python-0.6.0 → s2_python-0.7.0}/src/s2python/ombc/__init__.py +0 -0
  96. {s2_python-0.6.0 → s2_python-0.7.0}/src/s2python/ombc/ombc_instruction.py +0 -0
  97. {s2_python-0.6.0 → s2_python-0.7.0}/src/s2python/ombc/ombc_status.py +0 -0
  98. {s2_python-0.6.0 → s2_python-0.7.0}/src/s2python/ombc/ombc_timer_status.py +0 -0
  99. {s2_python-0.6.0 → s2_python-0.7.0}/src/s2python/pebc/__init__.py +0 -0
  100. {s2_python-0.6.0 → s2_python-0.7.0}/src/s2python/pebc/pebc_allowed_limit_range.py +0 -0
  101. {s2_python-0.6.0 → s2_python-0.7.0}/src/s2python/pebc/pebc_energy_constraint.py +0 -0
  102. {s2_python-0.6.0 → s2_python-0.7.0}/src/s2python/pebc/pebc_instruction.py +0 -0
  103. {s2_python-0.6.0 → s2_python-0.7.0}/src/s2python/pebc/pebc_power_constraints.py +0 -0
  104. {s2_python-0.6.0 → s2_python-0.7.0}/src/s2python/pebc/pebc_power_envelope.py +0 -0
  105. {s2_python-0.6.0 → s2_python-0.7.0}/src/s2python/pebc/pebc_power_envelope_element.py +0 -0
  106. {s2_python-0.6.0 → s2_python-0.7.0}/src/s2python/ppbc/__init__.py +0 -0
  107. {s2_python-0.6.0 → s2_python-0.7.0}/src/s2python/ppbc/ppbc_end_interruption_instruction.py +0 -0
  108. {s2_python-0.6.0 → s2_python-0.7.0}/src/s2python/ppbc/ppbc_power_profile_definition.py +0 -0
  109. {s2_python-0.6.0 → s2_python-0.7.0}/src/s2python/ppbc/ppbc_power_profile_status.py +0 -0
  110. {s2_python-0.6.0 → s2_python-0.7.0}/src/s2python/ppbc/ppbc_power_sequence.py +0 -0
  111. {s2_python-0.6.0 → s2_python-0.7.0}/src/s2python/ppbc/ppbc_power_sequence_container.py +0 -0
  112. {s2_python-0.6.0 → s2_python-0.7.0}/src/s2python/ppbc/ppbc_power_sequence_container_status.py +0 -0
  113. {s2_python-0.6.0 → s2_python-0.7.0}/src/s2python/ppbc/ppbc_power_sequence_element.py +0 -0
  114. {s2_python-0.6.0 → s2_python-0.7.0}/src/s2python/ppbc/ppbc_schedule_instruction.py +0 -0
  115. {s2_python-0.6.0 → s2_python-0.7.0}/src/s2python/ppbc/ppbc_start_interruption_instruction.py +0 -0
  116. {s2_python-0.6.0 → s2_python-0.7.0}/src/s2python/py.typed +0 -0
  117. {s2_python-0.6.0 → s2_python-0.7.0}/src/s2python/reception_status_awaiter.py +0 -0
  118. {s2_python-0.6.0 → s2_python-0.7.0}/src/s2python/s2_connection.py +0 -0
  119. {s2_python-0.6.0 → s2_python-0.7.0}/src/s2python/s2_control_type.py +0 -0
  120. {s2_python-0.6.0 → s2_python-0.7.0}/src/s2python/utils.py +0 -0
  121. {s2_python-0.6.0 → s2_python-0.7.0}/src/s2python/version.py +0 -0
  122. {s2_python-0.6.0 → s2_python-0.7.0}/tests/unit/__init__.py +0 -0
  123. {s2_python-0.6.0 → s2_python-0.7.0}/tests/unit/common/__init__.py +0 -0
  124. {s2_python-0.6.0 → s2_python-0.7.0}/tests/unit/common/duration_test.py +0 -0
  125. {s2_python-0.6.0 → s2_python-0.7.0}/tests/unit/common/handshake_response_test.py +0 -0
  126. {s2_python-0.6.0 → s2_python-0.7.0}/tests/unit/common/handshake_test.py +0 -0
  127. {s2_python-0.6.0 → s2_python-0.7.0}/tests/unit/common/instruction_status_update_test.py +0 -0
  128. {s2_python-0.6.0 → s2_python-0.7.0}/tests/unit/common/number_range_test.py +0 -0
  129. {s2_python-0.6.0 → s2_python-0.7.0}/tests/unit/common/power_forecast_element_test.py +0 -0
  130. {s2_python-0.6.0 → s2_python-0.7.0}/tests/unit/common/power_forecast_test.py +0 -0
  131. {s2_python-0.6.0 → s2_python-0.7.0}/tests/unit/common/power_forecast_value_test.py +0 -0
  132. {s2_python-0.6.0 → s2_python-0.7.0}/tests/unit/common/power_measurement_test.py +0 -0
  133. {s2_python-0.6.0 → s2_python-0.7.0}/tests/unit/common/power_range_test.py +0 -0
  134. {s2_python-0.6.0 → s2_python-0.7.0}/tests/unit/common/power_value_test.py +0 -0
  135. {s2_python-0.6.0 → s2_python-0.7.0}/tests/unit/common/reception_status_test.py +0 -0
  136. {s2_python-0.6.0 → s2_python-0.7.0}/tests/unit/common/resource_manager_details_test.py +0 -0
  137. {s2_python-0.6.0 → s2_python-0.7.0}/tests/unit/common/revoke_object_test.py +0 -0
  138. {s2_python-0.6.0 → s2_python-0.7.0}/tests/unit/common/role_test.py +0 -0
  139. {s2_python-0.6.0 → s2_python-0.7.0}/tests/unit/common/select_control_type_test.py +0 -0
  140. {s2_python-0.6.0 → s2_python-0.7.0}/tests/unit/common/session_request_test.py +0 -0
  141. {s2_python-0.6.0 → s2_python-0.7.0}/tests/unit/common/timer_test.py +0 -0
  142. {s2_python-0.6.0 → s2_python-0.7.0}/tests/unit/common/transition_test.py +0 -0
  143. {s2_python-0.6.0 → s2_python-0.7.0}/tests/unit/frbc/frbc_actuator_description_test.py +0 -0
  144. {s2_python-0.6.0 → s2_python-0.7.0}/tests/unit/frbc/frbc_actuator_status_test.py +0 -0
  145. {s2_python-0.6.0 → s2_python-0.7.0}/tests/unit/frbc/frbc_fill_level_target_profile_element_test.py +0 -0
  146. {s2_python-0.6.0 → s2_python-0.7.0}/tests/unit/frbc/frbc_fill_level_target_profile_test.py +0 -0
  147. {s2_python-0.6.0 → s2_python-0.7.0}/tests/unit/frbc/frbc_instruction_test.py +0 -0
  148. {s2_python-0.6.0 → s2_python-0.7.0}/tests/unit/frbc/frbc_leakage_behaviour_element_test.py +0 -0
  149. {s2_python-0.6.0 → s2_python-0.7.0}/tests/unit/frbc/frbc_leakage_behaviour_test.py +0 -0
  150. {s2_python-0.6.0 → s2_python-0.7.0}/tests/unit/frbc/frbc_operation_mode_element_test.py +0 -0
  151. {s2_python-0.6.0 → s2_python-0.7.0}/tests/unit/frbc/frbc_operation_mode_test.py +0 -0
  152. {s2_python-0.6.0 → s2_python-0.7.0}/tests/unit/frbc/frbc_storage_description_test.py +0 -0
  153. {s2_python-0.6.0 → s2_python-0.7.0}/tests/unit/frbc/frbc_storage_status_test.py +0 -0
  154. {s2_python-0.6.0 → s2_python-0.7.0}/tests/unit/frbc/frbc_system_description_test.py +0 -0
  155. {s2_python-0.6.0 → s2_python-0.7.0}/tests/unit/frbc/frbc_timer_status_test.py +0 -0
  156. {s2_python-0.6.0 → s2_python-0.7.0}/tests/unit/frbc/frbc_usage_forecast_element_test.py +0 -0
  157. {s2_python-0.6.0 → s2_python-0.7.0}/tests/unit/frbc/frbc_usage_forecast_test.py +0 -0
  158. {s2_python-0.6.0 → s2_python-0.7.0}/tests/unit/message_test.py +0 -0
  159. {s2_python-0.6.0 → s2_python-0.7.0}/tests/unit/pebc/pebc_allowed_limit_range_test.py +0 -0
  160. {s2_python-0.6.0 → s2_python-0.7.0}/tests/unit/pebc/pebc_power_constraints_test.py +0 -0
  161. {s2_python-0.6.0 → s2_python-0.7.0}/tests/unit/reception_status_awaiter_test.py +0 -0
  162. {s2_python-0.6.0 → s2_python-0.7.0}/tests/unit/s2_connection_test.py +0 -0
  163. {s2_python-0.6.0 → s2_python-0.7.0}/tests/unit/s2_parser_test.py +0 -0
  164. {s2_python-0.6.0 → s2_python-0.7.0}/tests/unit/utils_test.py +0 -0
  165. {s2_python-0.6.0 → s2_python-0.7.0}/tox.ini +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: s2-python
3
- Version: 0.6.0
3
+ Version: 0.7.0
4
4
  Summary: S2 Protocol Python Wrapper
5
5
  Author-email: Flexiblepower <info@info.nl>
6
6
  License-Expression: Apache-2.0
@@ -54,8 +54,6 @@ Python Wrapper for S2 Flexibility Protocol
54
54
  This Python package implements the message validation for the EN50491-12-2 "S2" standard for home and building energy management. This implementation
55
55
  is based on the asyncapi description of the protocol provided in the `s2-ws-json <https://github.com/flexiblepower/s2-ws-json/>`_ repository.
56
56
 
57
- Currently, the package supports the *common* and *FILL RATE BASED CONTROL* types and messages.
58
-
59
57
  To Install
60
58
  -----------
61
59
  You can install this package using pip or any Python dependency manager that collects the packages from PyPI:
@@ -10,8 +10,6 @@ Python Wrapper for S2 Flexibility Protocol
10
10
  This Python package implements the message validation for the EN50491-12-2 "S2" standard for home and building energy management. This implementation
11
11
  is based on the asyncapi description of the protocol provided in the `s2-ws-json <https://github.com/flexiblepower/s2-ws-json/>`_ repository.
12
12
 
13
- Currently, the package supports the *common* and *FILL RATE BASED CONTROL* types and messages.
14
-
15
13
  To Install
16
14
  -----------
17
15
  You can install this package using pip or any Python dependency manager that collects the packages from PyPI:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: s2-python
3
- Version: 0.6.0
3
+ Version: 0.7.0
4
4
  Summary: S2 Protocol Python Wrapper
5
5
  Author-email: Flexiblepower <info@info.nl>
6
6
  License-Expression: Apache-2.0
@@ -54,8 +54,6 @@ Python Wrapper for S2 Flexibility Protocol
54
54
  This Python package implements the message validation for the EN50491-12-2 "S2" standard for home and building energy management. This implementation
55
55
  is based on the asyncapi description of the protocol provided in the `s2-ws-json <https://github.com/flexiblepower/s2-ws-json/>`_ repository.
56
56
 
57
- Currently, the package supports the *common* and *FILL RATE BASED CONTROL* types and messages.
58
-
59
57
  To Install
60
58
  -----------
61
59
  You can install this package using pip or any Python dependency manager that collects the packages from PyPI:
@@ -118,6 +118,7 @@ src/s2python/ppbc/ppbc_power_sequence_element.py
118
118
  src/s2python/ppbc/ppbc_schedule_instruction.py
119
119
  src/s2python/ppbc/ppbc_start_interruption_instruction.py
120
120
  tests/unit/__init__.py
121
+ tests/unit/inheritance_test.py
121
122
  tests/unit/message_test.py
122
123
  tests/unit/reception_status_awaiter_test.py
123
124
  tests/unit/s2_connection_test.py
@@ -1,4 +1,4 @@
1
- from typing import List
1
+ from typing import List, Dict
2
2
  from typing_extensions import Self
3
3
 
4
4
  from pydantic import model_validator
@@ -29,7 +29,7 @@ class PowerForecastElement(GenPowerForecastElement, S2MessageComponent):
29
29
  def validate_values_at_most_one_per_commodity_quantity(self) -> Self:
30
30
  """Validates the power measurement values to check that there is at most 1 PowerValue per CommodityQuantity."""
31
31
 
32
- has_value: dict[CommodityQuantity, bool] = {}
32
+ has_value: Dict[CommodityQuantity, bool] = {}
33
33
 
34
34
  for value in self.power_values:
35
35
  if has_value.get(value.commodity_quantity, False):
@@ -1,5 +1,5 @@
1
1
  import uuid
2
- from typing import List
2
+ from typing import List, Dict
3
3
  from typing_extensions import Self
4
4
 
5
5
  from pydantic import model_validator
@@ -26,7 +26,7 @@ class PowerMeasurement(GenPowerMeasurement, S2MessageComponent):
26
26
  def validate_values_at_most_one_per_commodity_quantity(self) -> Self:
27
27
  """Validates the power measurement values to check that there is at most 1 PowerValue per CommodityQuantity."""
28
28
 
29
- has_value: dict[CommodityQuantity, bool] = {}
29
+ has_value: Dict[CommodityQuantity, bool] = {}
30
30
 
31
31
  for value in self.values:
32
32
  if has_value.get(value.commodity_quantity, False):
@@ -17,7 +17,7 @@ class OMBCOperationMode(GenOMBCOperationMode, S2MessageComponent):
17
17
  model_config["validate_assignment"] = True
18
18
 
19
19
  id: uuid.UUID = GenOMBCOperationMode.model_fields["id"] # type: ignore[assignment]
20
- power_ranges: List[PowerRange] = GenOMBCOperationMode.model_fields[
20
+ power_ranges: List[PowerRange] = GenOMBCOperationMode.model_fields[ # type: ignore[reportIncompatibleVariableOverride]
21
21
  "power_ranges"
22
22
  ] # type: ignore[assignment]
23
23
  abnormal_condition_only: bool = GenOMBCOperationMode.model_fields[
@@ -18,7 +18,7 @@ class OMBCSystemDescription(GenOMBCSystemDescription, S2MessageComponent):
18
18
  model_config["validate_assignment"] = True
19
19
 
20
20
  message_id: uuid.UUID = GenOMBCSystemDescription.model_fields["message_id"] # type: ignore[assignment]
21
- operation_modes: List[OMBCOperationMode] = GenOMBCSystemDescription.model_fields[
21
+ operation_modes: List[OMBCOperationMode] = GenOMBCSystemDescription.model_fields[ # type: ignore[reportIncompatibleVariableOverride]
22
22
  "operation_modes"
23
23
  ] # type: ignore[assignment]
24
24
  transitions: List[Transition] = GenOMBCSystemDescription.model_fields["transitions"] # type: ignore[assignment]
@@ -88,10 +88,9 @@ class S2Parser:
88
88
  None,
89
89
  message_json,
90
90
  f"Unable to parse {message_type} as an S2 message. Type unknown.",
91
- None,
92
91
  )
93
92
 
94
- return TYPE_TO_MESSAGE_CLASS[message_type].model_validate(message_json)
93
+ return TYPE_TO_MESSAGE_CLASS[message_type].from_dict(message_json)
95
94
 
96
95
  @staticmethod
97
96
  def parse_as_message(
@@ -0,0 +1,9 @@
1
+ from dataclasses import dataclass
2
+ from typing import Type, Optional
3
+
4
+
5
+ @dataclass
6
+ class S2ValidationError(Exception):
7
+ class_: Optional[Type]
8
+ obj: object
9
+ msg: str
@@ -12,8 +12,6 @@ from typing import (
12
12
 
13
13
  from typing_extensions import Self
14
14
 
15
- from pydantic.v1.error_wrappers import display_errors # pylint: disable=no-name-in-module
16
-
17
15
  from pydantic import ( # pylint: disable=no-name-in-module
18
16
  BaseModel,
19
17
  ValidationError,
@@ -28,12 +26,20 @@ MappingIntStrAny = Mapping[IntStr, Any]
28
26
 
29
27
 
30
28
  class S2MessageComponent(BaseModel):
29
+ def __setattr__(self, name: str, value: Any) -> None:
30
+ try:
31
+ super().__setattr__(name, value)
32
+ except (ValidationError, TypeError) as e:
33
+ raise S2ValidationError(
34
+ type(self), self, "Pydantic raised a validation error.",
35
+ ) from e
36
+
31
37
  def to_json(self) -> str:
32
38
  try:
33
39
  return self.model_dump_json(by_alias=True, exclude_none=True)
34
40
  except (ValidationError, TypeError) as e:
35
41
  raise S2ValidationError(
36
- type(self), self, "Pydantic raised a format validation error.", e
42
+ type(self), self, "Pydantic raised a validation error.",
37
43
  ) from e
38
44
 
39
45
  def to_dict(self) -> Dict[str, Any]:
@@ -41,12 +47,22 @@ class S2MessageComponent(BaseModel):
41
47
 
42
48
  @classmethod
43
49
  def from_json(cls, json_str: str) -> Self:
44
- gen_model = cls.model_validate_json(json_str)
50
+ try:
51
+ gen_model = cls.model_validate_json(json_str)
52
+ except (ValidationError, TypeError) as e:
53
+ raise S2ValidationError(
54
+ type(cls), cls, "Pydantic raised a validation error.",
55
+ ) from e
45
56
  return gen_model
46
57
 
47
58
  @classmethod
48
59
  def from_dict(cls, json_dict: Dict[str, Any]) -> Self:
49
- gen_model = cls.model_validate(json_dict)
60
+ try:
61
+ gen_model = cls.model_validate(json_dict)
62
+ except (ValidationError, TypeError) as e:
63
+ raise S2ValidationError(
64
+ type(cls), cls, "Pydantic raised a validation error.",
65
+ ) from e
50
66
  return gen_model
51
67
 
52
68
 
@@ -61,9 +77,9 @@ def convert_to_s2exception(f: Callable) -> Callable:
61
77
  else:
62
78
  class_type = None
63
79
 
64
- raise S2ValidationError(class_type, args, display_errors(e.errors()), e) from e # type: ignore[arg-type]
80
+ raise S2ValidationError(class_type, args, str(e)) from e
65
81
  except TypeError as e:
66
- raise S2ValidationError(None, args, str(e), e) from e
82
+ raise S2ValidationError(None, args, str(e)) from e
67
83
 
68
84
  inner.__doc__ = f.__doc__
69
85
  inner.__annotations__ = f.__annotations__
@@ -76,10 +92,5 @@ S = TypeVar("S", bound=S2MessageComponent)
76
92
 
77
93
  def catch_and_convert_exceptions(input_class: Type[S]) -> Type[S]:
78
94
  input_class.__init__ = convert_to_s2exception(input_class.__init__) # type: ignore[method-assign]
79
- input_class.__setattr__ = convert_to_s2exception(input_class.__setattr__) # type: ignore[method-assign]
80
- input_class.model_validate_json = convert_to_s2exception( # type: ignore[method-assign]
81
- input_class.model_validate_json
82
- )
83
- input_class.model_validate = convert_to_s2exception(input_class.model_validate) # type: ignore[method-assign]
84
95
 
85
96
  return input_class
@@ -0,0 +1,51 @@
1
+ import datetime
2
+ import unittest
3
+ import uuid
4
+ from typing import Optional
5
+
6
+ from pydantic import Field
7
+
8
+ from s2python.frbc import FRBCStorageStatus as FRBCStorageStatusOfficial
9
+ from s2python.s2_validation_error import S2ValidationError
10
+
11
+
12
+ class FRBCStorageStatus(FRBCStorageStatusOfficial):
13
+ measurement_timestamp: Optional[datetime.datetime] = Field(
14
+ default=None, description="Timestamp when fill level was measured."
15
+ )
16
+
17
+
18
+ class InheritanceTest(unittest.TestCase):
19
+ def test__inheritance__init(self):
20
+ # Arrange / Act
21
+ frbc_storage_status = FRBCStorageStatus(message_id=uuid.uuid4(),
22
+ present_fill_level=0.0,
23
+ measurement_timestamp=None)
24
+
25
+ # Assert
26
+ self.assertIsInstance(frbc_storage_status, FRBCStorageStatus)
27
+ self.assertIsNone(frbc_storage_status.measurement_timestamp)
28
+
29
+ def test__inheritance__init_wrong(self):
30
+ # Arrange / Act / Assert
31
+ with self.assertRaises(S2ValidationError):
32
+ FRBCStorageStatus(message_id=uuid.uuid4(),
33
+ present_fill_level=0.0,
34
+ measurement_timestamp=False) # pyright: ignore [reportArgumentType]
35
+
36
+ def test__inheritance__from_json(self):
37
+ # Arrange
38
+ json_str = """
39
+ {
40
+ "message_id": "6bad8186-9ebf-4647-ac45-1c6856511a2f",
41
+ "message_type": "FRBC.StorageStatus",
42
+ "present_fill_level": 2443.939298819414,
43
+ "measurement_timestamp": "2025-01-01T00:00:00Z"
44
+ }"""
45
+
46
+ # Act
47
+ frbc_storage_status = FRBCStorageStatus.from_json(json_str)
48
+
49
+ # Assert
50
+ self.assertIsInstance(frbc_storage_status, FRBCStorageStatus)
51
+ self.assertEqual(frbc_storage_status.measurement_timestamp, datetime.datetime.fromisoformat("2025-01-01T00:00:00+00:00"))
@@ -1,15 +0,0 @@
1
- from dataclasses import dataclass
2
- from typing import Union, Type, Optional
3
-
4
- from pydantic import ValidationError
5
- from pydantic.v1.error_wrappers import ValidationError as ValidationErrorV1
6
-
7
-
8
- @dataclass
9
- class S2ValidationError(Exception):
10
- class_: Optional[Type]
11
- obj: object
12
- msg: str
13
- pydantic_validation_error: Union[
14
- ValidationErrorV1, ValidationError, TypeError, None
15
- ]
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes