zepben.ewb 1.0.0__py3-none-any.whl

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 (641) hide show
  1. zepben/ewb/__init__.py +601 -0
  2. zepben/ewb/auth/__init__.py +10 -0
  3. zepben/ewb/auth/client/__init__.py +5 -0
  4. zepben/ewb/auth/client/zepben_token_fetcher.py +273 -0
  5. zepben/ewb/auth/common/__init__.py +5 -0
  6. zepben/ewb/auth/common/auth_exception.py +16 -0
  7. zepben/ewb/auth/common/auth_method.py +28 -0
  8. zepben/ewb/auth/common/auth_provider_config.py +96 -0
  9. zepben/ewb/database/__init__.py +4 -0
  10. zepben/ewb/database/paths/__init__.py +4 -0
  11. zepben/ewb/database/paths/database_type.py +34 -0
  12. zepben/ewb/database/paths/ewb_data_file_paths.py +237 -0
  13. zepben/ewb/database/sql/__init__.py +4 -0
  14. zepben/ewb/database/sql/column.py +37 -0
  15. zepben/ewb/database/sql/sql_table.py +142 -0
  16. zepben/ewb/database/sqlite/__init__.py +4 -0
  17. zepben/ewb/database/sqlite/common/__init__.py +4 -0
  18. zepben/ewb/database/sqlite/common/base_cim_reader.py +212 -0
  19. zepben/ewb/database/sqlite/common/base_cim_writer.py +159 -0
  20. zepben/ewb/database/sqlite/common/base_collection_reader.py +96 -0
  21. zepben/ewb/database/sqlite/common/base_collection_writer.py +73 -0
  22. zepben/ewb/database/sqlite/common/base_database_reader.py +127 -0
  23. zepben/ewb/database/sqlite/common/base_database_tables.py +137 -0
  24. zepben/ewb/database/sqlite/common/base_database_writer.py +195 -0
  25. zepben/ewb/database/sqlite/common/base_entry_writer.py +34 -0
  26. zepben/ewb/database/sqlite/common/base_service_reader.py +50 -0
  27. zepben/ewb/database/sqlite/common/base_service_writer.py +104 -0
  28. zepben/ewb/database/sqlite/common/metadata_collection_reader.py +39 -0
  29. zepben/ewb/database/sqlite/common/metadata_collection_writer.py +38 -0
  30. zepben/ewb/database/sqlite/common/metadata_entry_reader.py +45 -0
  31. zepben/ewb/database/sqlite/common/metadata_entry_writer.py +41 -0
  32. zepben/ewb/database/sqlite/common/reader_exceptions.py +30 -0
  33. zepben/ewb/database/sqlite/customer/__init__.py +4 -0
  34. zepben/ewb/database/sqlite/customer/customer_cim_reader.py +169 -0
  35. zepben/ewb/database/sqlite/customer/customer_cim_writer.py +137 -0
  36. zepben/ewb/database/sqlite/customer/customer_database_reader.py +44 -0
  37. zepben/ewb/database/sqlite/customer/customer_database_tables.py +37 -0
  38. zepben/ewb/database/sqlite/customer/customer_database_writer.py +45 -0
  39. zepben/ewb/database/sqlite/customer/customer_service_reader.py +57 -0
  40. zepben/ewb/database/sqlite/customer/customer_service_writer.py +47 -0
  41. zepben/ewb/database/sqlite/diagram/__init__.py +4 -0
  42. zepben/ewb/database/sqlite/diagram/diagram_cim_reader.py +105 -0
  43. zepben/ewb/database/sqlite/diagram/diagram_cim_writer.py +81 -0
  44. zepben/ewb/database/sqlite/diagram/diagram_database_reader.py +45 -0
  45. zepben/ewb/database/sqlite/diagram/diagram_database_tables.py +29 -0
  46. zepben/ewb/database/sqlite/diagram/diagram_database_writer.py +44 -0
  47. zepben/ewb/database/sqlite/diagram/diagram_service_reader.py +49 -0
  48. zepben/ewb/database/sqlite/diagram/diagram_service_writer.py +41 -0
  49. zepben/ewb/database/sqlite/extensions/__init__.py +4 -0
  50. zepben/ewb/database/sqlite/extensions/prepared_statement.py +112 -0
  51. zepben/ewb/database/sqlite/extensions/result_set.py +153 -0
  52. zepben/ewb/database/sqlite/network/__init__.py +4 -0
  53. zepben/ewb/database/sqlite/network/network_cim_reader.py +3167 -0
  54. zepben/ewb/database/sqlite/network/network_cim_writer.py +2561 -0
  55. zepben/ewb/database/sqlite/network/network_database_reader.py +175 -0
  56. zepben/ewb/database/sqlite/network/network_database_tables.py +242 -0
  57. zepben/ewb/database/sqlite/network/network_database_writer.py +43 -0
  58. zepben/ewb/database/sqlite/network/network_service_reader.py +265 -0
  59. zepben/ewb/database/sqlite/network/network_service_writer.py +209 -0
  60. zepben/ewb/database/sqlite/tables/__init__.py +4 -0
  61. zepben/ewb/database/sqlite/tables/associations/__init__.py +4 -0
  62. zepben/ewb/database/sqlite/tables/associations/loop_substation_relationship.py +17 -0
  63. zepben/ewb/database/sqlite/tables/associations/table_asset_organisation_roles_assets.py +40 -0
  64. zepben/ewb/database/sqlite/tables/associations/table_assets_power_system_resources.py +41 -0
  65. zepben/ewb/database/sqlite/tables/associations/table_battery_units_battery_controls.py +40 -0
  66. zepben/ewb/database/sqlite/tables/associations/table_circuits_substations.py +40 -0
  67. zepben/ewb/database/sqlite/tables/associations/table_circuits_terminals.py +40 -0
  68. zepben/ewb/database/sqlite/tables/associations/table_customer_agreements_pricing_structures.py +40 -0
  69. zepben/ewb/database/sqlite/tables/associations/table_end_devices_end_device_functions.py +40 -0
  70. zepben/ewb/database/sqlite/tables/associations/table_equipment_equipment_containers.py +40 -0
  71. zepben/ewb/database/sqlite/tables/associations/table_equipment_operational_restrictions.py +40 -0
  72. zepben/ewb/database/sqlite/tables/associations/table_equipment_usage_points.py +40 -0
  73. zepben/ewb/database/sqlite/tables/associations/table_loops_substations.py +43 -0
  74. zepben/ewb/database/sqlite/tables/associations/table_pricing_structures_tariffs.py +40 -0
  75. zepben/ewb/database/sqlite/tables/associations/table_protection_relay_functions_protected_switches.py +40 -0
  76. zepben/ewb/database/sqlite/tables/associations/table_protection_relay_functions_sensors.py +40 -0
  77. zepben/ewb/database/sqlite/tables/associations/table_protection_relay_schemes_protection_relay_functions.py +40 -0
  78. zepben/ewb/database/sqlite/tables/associations/table_synchronous_machines_reactive_capability_curves.py +39 -0
  79. zepben/ewb/database/sqlite/tables/associations/table_usage_points_end_devices.py +40 -0
  80. zepben/ewb/database/sqlite/tables/exceptions.py +10 -0
  81. zepben/ewb/database/sqlite/tables/extensions/__init__.py +4 -0
  82. zepben/ewb/database/sqlite/tables/extensions/iec61968/__init__.py +4 -0
  83. zepben/ewb/database/sqlite/tables/extensions/iec61968/assetinfo/__init__.py +4 -0
  84. zepben/ewb/database/sqlite/tables/extensions/iec61968/assetinfo/table_reclose_delays.py +38 -0
  85. zepben/ewb/database/sqlite/tables/extensions/iec61968/assetinfo/table_relay_info.py +21 -0
  86. zepben/ewb/database/sqlite/tables/extensions/iec61968/metering/__init__.py +4 -0
  87. zepben/ewb/database/sqlite/tables/extensions/iec61968/metering/table_pan_demand_response_functions.py +21 -0
  88. zepben/ewb/database/sqlite/tables/extensions/iec61970/__init__.py +4 -0
  89. zepben/ewb/database/sqlite/tables/extensions/iec61970/base/__init__.py +4 -0
  90. zepben/ewb/database/sqlite/tables/extensions/iec61970/base/core/__init__.py +4 -0
  91. zepben/ewb/database/sqlite/tables/extensions/iec61970/base/core/table_sites.py +15 -0
  92. zepben/ewb/database/sqlite/tables/extensions/iec61970/base/feeder/__init__.py +4 -0
  93. zepben/ewb/database/sqlite/tables/extensions/iec61970/base/feeder/table_loops.py +15 -0
  94. zepben/ewb/database/sqlite/tables/extensions/iec61970/base/feeder/table_lv_feeders.py +20 -0
  95. zepben/ewb/database/sqlite/tables/extensions/iec61970/base/generation/__init__.py +4 -0
  96. zepben/ewb/database/sqlite/tables/extensions/iec61970/base/generation/production/__init__.py +4 -0
  97. zepben/ewb/database/sqlite/tables/extensions/iec61970/base/generation/production/table_ev_charging_units.py +15 -0
  98. zepben/ewb/database/sqlite/tables/extensions/iec61970/base/protection/__init__.py +4 -0
  99. zepben/ewb/database/sqlite/tables/extensions/iec61970/base/protection/table_distance_relays.py +28 -0
  100. zepben/ewb/database/sqlite/tables/extensions/iec61970/base/protection/table_protection_relay_function_thresholds.py +36 -0
  101. zepben/ewb/database/sqlite/tables/extensions/iec61970/base/protection/table_protection_relay_function_time_limits.py +34 -0
  102. zepben/ewb/database/sqlite/tables/extensions/iec61970/base/protection/table_protection_relay_functions.py +24 -0
  103. zepben/ewb/database/sqlite/tables/extensions/iec61970/base/protection/table_protection_relay_schemes.py +20 -0
  104. zepben/ewb/database/sqlite/tables/extensions/iec61970/base/protection/table_protection_relay_systems.py +20 -0
  105. zepben/ewb/database/sqlite/tables/extensions/iec61970/base/protection/table_voltage_relays.py +15 -0
  106. zepben/ewb/database/sqlite/tables/extensions/iec61970/base/wires/__init__.py +4 -0
  107. zepben/ewb/database/sqlite/tables/extensions/iec61970/base/wires/table_battery_controls.py +23 -0
  108. zepben/ewb/database/sqlite/tables/extensions/iec61970/base/wires/table_power_transformer_end_ratings.py +34 -0
  109. zepben/ewb/database/sqlite/tables/iec61968/__init__.py +4 -0
  110. zepben/ewb/database/sqlite/tables/iec61968/assetinfo/__init__.py +4 -0
  111. zepben/ewb/database/sqlite/tables/iec61968/assetinfo/table_cable_info.py +15 -0
  112. zepben/ewb/database/sqlite/tables/iec61968/assetinfo/table_no_load_tests.py +24 -0
  113. zepben/ewb/database/sqlite/tables/iec61968/assetinfo/table_open_circuit_tests.py +24 -0
  114. zepben/ewb/database/sqlite/tables/iec61968/assetinfo/table_overhead_wire_info.py +15 -0
  115. zepben/ewb/database/sqlite/tables/iec61968/assetinfo/table_power_transformer_info.py +15 -0
  116. zepben/ewb/database/sqlite/tables/iec61968/assetinfo/table_short_circuit_tests.py +29 -0
  117. zepben/ewb/database/sqlite/tables/iec61968/assetinfo/table_shunt_compensator_info.py +23 -0
  118. zepben/ewb/database/sqlite/tables/iec61968/assetinfo/table_switch_info.py +20 -0
  119. zepben/ewb/database/sqlite/tables/iec61968/assetinfo/table_transformer_end_info.py +46 -0
  120. zepben/ewb/database/sqlite/tables/iec61968/assetinfo/table_transformer_tank_info.py +27 -0
  121. zepben/ewb/database/sqlite/tables/iec61968/assetinfo/table_transformer_test.py +19 -0
  122. zepben/ewb/database/sqlite/tables/iec61968/assetinfo/table_wire_info.py +19 -0
  123. zepben/ewb/database/sqlite/tables/iec61968/assets/__init__.py +4 -0
  124. zepben/ewb/database/sqlite/tables/iec61968/assets/table_asset_containers.py +14 -0
  125. zepben/ewb/database/sqlite/tables/iec61968/assets/table_asset_functions.py +14 -0
  126. zepben/ewb/database/sqlite/tables/iec61968/assets/table_asset_info.py +14 -0
  127. zepben/ewb/database/sqlite/tables/iec61968/assets/table_asset_organisation_roles.py +14 -0
  128. zepben/ewb/database/sqlite/tables/iec61968/assets/table_asset_owners.py +15 -0
  129. zepben/ewb/database/sqlite/tables/iec61968/assets/table_assets.py +18 -0
  130. zepben/ewb/database/sqlite/tables/iec61968/assets/table_streetlights.py +22 -0
  131. zepben/ewb/database/sqlite/tables/iec61968/assets/table_structures.py +14 -0
  132. zepben/ewb/database/sqlite/tables/iec61968/common/__init__.py +4 -0
  133. zepben/ewb/database/sqlite/tables/iec61968/common/table_agreements.py +14 -0
  134. zepben/ewb/database/sqlite/tables/iec61968/common/table_documents.py +23 -0
  135. zepben/ewb/database/sqlite/tables/iec61968/common/table_location_street_address_field.py +18 -0
  136. zepben/ewb/database/sqlite/tables/iec61968/common/table_location_street_addresses.py +33 -0
  137. zepben/ewb/database/sqlite/tables/iec61968/common/table_locations.py +15 -0
  138. zepben/ewb/database/sqlite/tables/iec61968/common/table_organisation_roles.py +18 -0
  139. zepben/ewb/database/sqlite/tables/iec61968/common/table_organisations.py +15 -0
  140. zepben/ewb/database/sqlite/tables/iec61968/common/table_position_points.py +30 -0
  141. zepben/ewb/database/sqlite/tables/iec61968/common/table_street_addresses.py +26 -0
  142. zepben/ewb/database/sqlite/tables/iec61968/common/table_town_details.py +19 -0
  143. zepben/ewb/database/sqlite/tables/iec61968/customers/__init__.py +4 -0
  144. zepben/ewb/database/sqlite/tables/iec61968/customers/table_customer_agreements.py +27 -0
  145. zepben/ewb/database/sqlite/tables/iec61968/customers/table_customers.py +22 -0
  146. zepben/ewb/database/sqlite/tables/iec61968/customers/table_pricing_structures.py +15 -0
  147. zepben/ewb/database/sqlite/tables/iec61968/customers/table_tariffs.py +15 -0
  148. zepben/ewb/database/sqlite/tables/iec61968/infiec61968/__init__.py +4 -0
  149. zepben/ewb/database/sqlite/tables/iec61968/infiec61968/infassetinfo/__init__.py +4 -0
  150. zepben/ewb/database/sqlite/tables/iec61968/infiec61968/infassetinfo/table_current_transformer_info.py +33 -0
  151. zepben/ewb/database/sqlite/tables/iec61968/infiec61968/infassetinfo/table_potential_transformer_info.py +26 -0
  152. zepben/ewb/database/sqlite/tables/iec61968/infiec61968/infassets/__init__.py +4 -0
  153. zepben/ewb/database/sqlite/tables/iec61968/infiec61968/infassets/table_poles.py +20 -0
  154. zepben/ewb/database/sqlite/tables/iec61968/metering/__init__.py +4 -0
  155. zepben/ewb/database/sqlite/tables/iec61968/metering/table_end_device_functions.py +18 -0
  156. zepben/ewb/database/sqlite/tables/iec61968/metering/table_end_devices.py +19 -0
  157. zepben/ewb/database/sqlite/tables/iec61968/metering/table_meters.py +15 -0
  158. zepben/ewb/database/sqlite/tables/iec61968/metering/table_usage_points.py +23 -0
  159. zepben/ewb/database/sqlite/tables/iec61968/operations/__init__.py +4 -0
  160. zepben/ewb/database/sqlite/tables/iec61968/operations/table_operational_restrictions.py +15 -0
  161. zepben/ewb/database/sqlite/tables/iec61970/__init__.py +4 -0
  162. zepben/ewb/database/sqlite/tables/iec61970/base/__init__.py +4 -0
  163. zepben/ewb/database/sqlite/tables/iec61970/base/auxiliaryequipment/__init__.py +4 -0
  164. zepben/ewb/database/sqlite/tables/iec61970/base/auxiliaryequipment/table_auxiliary_equipment.py +18 -0
  165. zepben/ewb/database/sqlite/tables/iec61970/base/auxiliaryequipment/table_current_transformers.py +21 -0
  166. zepben/ewb/database/sqlite/tables/iec61970/base/auxiliaryequipment/table_fault_indicators.py +15 -0
  167. zepben/ewb/database/sqlite/tables/iec61970/base/auxiliaryequipment/table_potential_transformers.py +21 -0
  168. zepben/ewb/database/sqlite/tables/iec61970/base/auxiliaryequipment/table_sensors.py +14 -0
  169. zepben/ewb/database/sqlite/tables/iec61970/base/core/__init__.py +4 -0
  170. zepben/ewb/database/sqlite/tables/iec61970/base/core/table_ac_dc_terminals.py +14 -0
  171. zepben/ewb/database/sqlite/tables/iec61970/base/core/table_base_voltages.py +20 -0
  172. zepben/ewb/database/sqlite/tables/iec61970/base/core/table_conducting_equipment.py +18 -0
  173. zepben/ewb/database/sqlite/tables/iec61970/base/core/table_connectivity_node_containers.py +14 -0
  174. zepben/ewb/database/sqlite/tables/iec61970/base/core/table_connectivity_nodes.py +15 -0
  175. zepben/ewb/database/sqlite/tables/iec61970/base/core/table_curve_data.py +46 -0
  176. zepben/ewb/database/sqlite/tables/iec61970/base/core/table_curves.py +17 -0
  177. zepben/ewb/database/sqlite/tables/iec61970/base/core/table_equipment.py +20 -0
  178. zepben/ewb/database/sqlite/tables/iec61970/base/core/table_equipment_containers.py +14 -0
  179. zepben/ewb/database/sqlite/tables/iec61970/base/core/table_feeders.py +28 -0
  180. zepben/ewb/database/sqlite/tables/iec61970/base/core/table_geographical_regions.py +15 -0
  181. zepben/ewb/database/sqlite/tables/iec61970/base/core/table_identified_objects.py +29 -0
  182. zepben/ewb/database/sqlite/tables/iec61970/base/core/table_name_types.py +28 -0
  183. zepben/ewb/database/sqlite/tables/iec61970/base/core/table_names.py +36 -0
  184. zepben/ewb/database/sqlite/tables/iec61970/base/core/table_power_system_resources.py +19 -0
  185. zepben/ewb/database/sqlite/tables/iec61970/base/core/table_sub_geographical_regions.py +27 -0
  186. zepben/ewb/database/sqlite/tables/iec61970/base/core/table_substations.py +27 -0
  187. zepben/ewb/database/sqlite/tables/iec61970/base/core/table_terminals.py +35 -0
  188. zepben/ewb/database/sqlite/tables/iec61970/base/diagramlayout/__init__.py +4 -0
  189. zepben/ewb/database/sqlite/tables/iec61970/base/diagramlayout/table_diagram_object_points.py +35 -0
  190. zepben/ewb/database/sqlite/tables/iec61970/base/diagramlayout/table_diagram_objects.py +31 -0
  191. zepben/ewb/database/sqlite/tables/iec61970/base/diagramlayout/table_diagrams.py +21 -0
  192. zepben/ewb/database/sqlite/tables/iec61970/base/equivalents/__init__.py +4 -0
  193. zepben/ewb/database/sqlite/tables/iec61970/base/equivalents/table_equivalent_branches.py +35 -0
  194. zepben/ewb/database/sqlite/tables/iec61970/base/equivalents/table_equivalent_equipment.py +14 -0
  195. zepben/ewb/database/sqlite/tables/iec61970/base/generation/__init__.py +4 -0
  196. zepben/ewb/database/sqlite/tables/iec61970/base/generation/production/__init__.py +4 -0
  197. zepben/ewb/database/sqlite/tables/iec61970/base/generation/production/table_battery_units.py +22 -0
  198. zepben/ewb/database/sqlite/tables/iec61970/base/generation/production/table_photo_voltaic_units.py +15 -0
  199. zepben/ewb/database/sqlite/tables/iec61970/base/generation/production/table_power_electronics_units.py +26 -0
  200. zepben/ewb/database/sqlite/tables/iec61970/base/generation/production/table_power_electronics_wind_units.py +15 -0
  201. zepben/ewb/database/sqlite/tables/iec61970/base/meas/__init__.py +4 -0
  202. zepben/ewb/database/sqlite/tables/iec61970/base/meas/table_accumulators.py +15 -0
  203. zepben/ewb/database/sqlite/tables/iec61970/base/meas/table_analogs.py +20 -0
  204. zepben/ewb/database/sqlite/tables/iec61970/base/meas/table_controls.py +20 -0
  205. zepben/ewb/database/sqlite/tables/iec61970/base/meas/table_discretes.py +15 -0
  206. zepben/ewb/database/sqlite/tables/iec61970/base/meas/table_io_points.py +14 -0
  207. zepben/ewb/database/sqlite/tables/iec61970/base/meas/table_measurements.py +30 -0
  208. zepben/ewb/database/sqlite/tables/iec61970/base/protection/__init__.py +4 -0
  209. zepben/ewb/database/sqlite/tables/iec61970/base/protection/table_current_relays.py +22 -0
  210. zepben/ewb/database/sqlite/tables/iec61970/base/scada/__init__.py +4 -0
  211. zepben/ewb/database/sqlite/tables/iec61970/base/scada/table_remote_controls.py +20 -0
  212. zepben/ewb/database/sqlite/tables/iec61970/base/scada/table_remote_points.py +14 -0
  213. zepben/ewb/database/sqlite/tables/iec61970/base/scada/table_remote_sources.py +20 -0
  214. zepben/ewb/database/sqlite/tables/iec61970/base/wires/__init__.py +4 -0
  215. zepben/ewb/database/sqlite/tables/iec61970/base/wires/table_ac_line_segments.py +20 -0
  216. zepben/ewb/database/sqlite/tables/iec61970/base/wires/table_breakers.py +20 -0
  217. zepben/ewb/database/sqlite/tables/iec61970/base/wires/table_busbar_sections.py +15 -0
  218. zepben/ewb/database/sqlite/tables/iec61970/base/wires/table_clamps.py +23 -0
  219. zepben/ewb/database/sqlite/tables/iec61970/base/wires/table_conductors.py +21 -0
  220. zepben/ewb/database/sqlite/tables/iec61970/base/wires/table_connectors.py +14 -0
  221. zepben/ewb/database/sqlite/tables/iec61970/base/wires/table_cuts.py +23 -0
  222. zepben/ewb/database/sqlite/tables/iec61970/base/wires/table_disconnectors.py +15 -0
  223. zepben/ewb/database/sqlite/tables/iec61970/base/wires/table_earth_fault_compensators.py +22 -0
  224. zepben/ewb/database/sqlite/tables/iec61970/base/wires/table_energy_connections.py +14 -0
  225. zepben/ewb/database/sqlite/tables/iec61970/base/wires/table_energy_consumer_phases.py +37 -0
  226. zepben/ewb/database/sqlite/tables/iec61970/base/wires/table_energy_consumers.py +26 -0
  227. zepben/ewb/database/sqlite/tables/iec61970/base/wires/table_energy_source_phases.py +33 -0
  228. zepben/ewb/database/sqlite/tables/iec61970/base/wires/table_energy_sources.py +44 -0
  229. zepben/ewb/database/sqlite/tables/iec61970/base/wires/table_fuses.py +20 -0
  230. zepben/ewb/database/sqlite/tables/iec61970/base/wires/table_ground_disconnectors.py +15 -0
  231. zepben/ewb/database/sqlite/tables/iec61970/base/wires/table_grounding_impedances.py +24 -0
  232. zepben/ewb/database/sqlite/tables/iec61970/base/wires/table_grounds.py +15 -0
  233. zepben/ewb/database/sqlite/tables/iec61970/base/wires/table_jumpers.py +15 -0
  234. zepben/ewb/database/sqlite/tables/iec61970/base/wires/table_junctions.py +15 -0
  235. zepben/ewb/database/sqlite/tables/iec61970/base/wires/table_linear_shunt_compensators.py +23 -0
  236. zepben/ewb/database/sqlite/tables/iec61970/base/wires/table_lines.py +14 -0
  237. zepben/ewb/database/sqlite/tables/iec61970/base/wires/table_load_break_switches.py +15 -0
  238. zepben/ewb/database/sqlite/tables/iec61970/base/wires/table_per_length_impedances.py +14 -0
  239. zepben/ewb/database/sqlite/tables/iec61970/base/wires/table_per_length_line_parameters.py +14 -0
  240. zepben/ewb/database/sqlite/tables/iec61970/base/wires/table_per_length_phase_impedances.py +18 -0
  241. zepben/ewb/database/sqlite/tables/iec61970/base/wires/table_per_length_sequence_impedances.py +27 -0
  242. zepben/ewb/database/sqlite/tables/iec61970/base/wires/table_petersen_coils.py +27 -0
  243. zepben/ewb/database/sqlite/tables/iec61970/base/wires/table_phase_impedance_data.py +52 -0
  244. zepben/ewb/database/sqlite/tables/iec61970/base/wires/table_power_electronics_connection_phases.py +30 -0
  245. zepben/ewb/database/sqlite/tables/iec61970/base/wires/table_power_electronics_connections.py +50 -0
  246. zepben/ewb/database/sqlite/tables/iec61970/base/wires/table_power_transformer_ends.py +43 -0
  247. zepben/ewb/database/sqlite/tables/iec61970/base/wires/table_power_transformers.py +24 -0
  248. zepben/ewb/database/sqlite/tables/iec61970/base/wires/table_protected_switches.py +18 -0
  249. zepben/ewb/database/sqlite/tables/iec61970/base/wires/table_ratio_tap_changers.py +28 -0
  250. zepben/ewb/database/sqlite/tables/iec61970/base/wires/table_reactive_capability_curves.py +18 -0
  251. zepben/ewb/database/sqlite/tables/iec61970/base/wires/table_reclosers.py +15 -0
  252. zepben/ewb/database/sqlite/tables/iec61970/base/wires/table_regulating_cond_eq.py +19 -0
  253. zepben/ewb/database/sqlite/tables/iec61970/base/wires/table_regulating_controls.py +29 -0
  254. zepben/ewb/database/sqlite/tables/iec61970/base/wires/table_rotating_machines.py +36 -0
  255. zepben/ewb/database/sqlite/tables/iec61970/base/wires/table_series_compensators.py +25 -0
  256. zepben/ewb/database/sqlite/tables/iec61970/base/wires/table_shunt_compensators.py +22 -0
  257. zepben/ewb/database/sqlite/tables/iec61970/base/wires/table_static_var_compensator.py +24 -0
  258. zepben/ewb/database/sqlite/tables/iec61970/base/wires/table_switches.py +21 -0
  259. zepben/ewb/database/sqlite/tables/iec61970/base/wires/table_synchronous_machines.py +95 -0
  260. zepben/ewb/database/sqlite/tables/iec61970/base/wires/table_tap_changer_controls.py +28 -0
  261. zepben/ewb/database/sqlite/tables/iec61970/base/wires/table_tap_changers.py +25 -0
  262. zepben/ewb/database/sqlite/tables/iec61970/base/wires/table_transformer_ends.py +30 -0
  263. zepben/ewb/database/sqlite/tables/iec61970/base/wires/table_transformer_star_impedances.py +32 -0
  264. zepben/ewb/database/sqlite/tables/iec61970/infiec61970/__init__.py +4 -0
  265. zepben/ewb/database/sqlite/tables/iec61970/infiec61970/feeder/__init__.py +4 -0
  266. zepben/ewb/database/sqlite/tables/iec61970/infiec61970/feeder/table_circuits.py +27 -0
  267. zepben/ewb/database/sqlite/tables/sqlite_table.py +45 -0
  268. zepben/ewb/database/sqlite/tables/table_metadata_data_sources.py +21 -0
  269. zepben/ewb/database/sqlite/tables/table_version.py +39 -0
  270. zepben/ewb/dataclassy/__init__.py +15 -0
  271. zepben/ewb/dataclassy/dataclass.py +192 -0
  272. zepben/ewb/dataclassy/decorator.py +35 -0
  273. zepben/ewb/dataclassy/functions.py +80 -0
  274. zepben/ewb/examples/__init__.py +6 -0
  275. zepben/ewb/examples/simple_test_network.py +158 -0
  276. zepben/ewb/exceptions.py +52 -0
  277. zepben/ewb/model/__init__.py +4 -0
  278. zepben/ewb/model/busbranch/__init__.py +4 -0
  279. zepben/ewb/model/busbranch/bus_branch.py +1051 -0
  280. zepben/ewb/model/cim/__init__.py +4 -0
  281. zepben/ewb/model/cim/extensions/__init__.py +4 -0
  282. zepben/ewb/model/cim/extensions/iec61968/__init__.py +4 -0
  283. zepben/ewb/model/cim/extensions/iec61968/assetinfo/__init__.py +4 -0
  284. zepben/ewb/model/cim/extensions/iec61968/assetinfo/relay_info.py +128 -0
  285. zepben/ewb/model/cim/extensions/iec61968/metering/__init__.py +4 -0
  286. zepben/ewb/model/cim/extensions/iec61968/metering/pan_demand_reponse_function.py +112 -0
  287. zepben/ewb/model/cim/extensions/iec61970/__init__.py +4 -0
  288. zepben/ewb/model/cim/extensions/iec61970/base/__init__.py +4 -0
  289. zepben/ewb/model/cim/extensions/iec61970/base/core/__init__.py +4 -0
  290. zepben/ewb/model/cim/extensions/iec61970/base/core/site.py +37 -0
  291. zepben/ewb/model/cim/extensions/iec61970/base/feeder/__init__.py +4 -0
  292. zepben/ewb/model/cim/extensions/iec61970/base/feeder/loop.py +207 -0
  293. zepben/ewb/model/cim/extensions/iec61970/base/feeder/lv_feeder.py +258 -0
  294. zepben/ewb/model/cim/extensions/iec61970/base/generation/__init__.py +4 -0
  295. zepben/ewb/model/cim/extensions/iec61970/base/generation/production/__init__.py +4 -0
  296. zepben/ewb/model/cim/extensions/iec61970/base/generation/production/ev_charging_unit.py +18 -0
  297. zepben/ewb/model/cim/extensions/iec61970/base/protection/__init__.py +4 -0
  298. zepben/ewb/model/cim/extensions/iec61970/base/protection/distance_relay.py +69 -0
  299. zepben/ewb/model/cim/extensions/iec61970/base/protection/power_direction_kind.py +36 -0
  300. zepben/ewb/model/cim/extensions/iec61970/base/protection/protection_kind.py +112 -0
  301. zepben/ewb/model/cim/extensions/iec61970/base/protection/protection_relay_function.py +448 -0
  302. zepben/ewb/model/cim/extensions/iec61970/base/protection/protection_relay_scheme.py +97 -0
  303. zepben/ewb/model/cim/extensions/iec61970/base/protection/protection_relay_system.py +97 -0
  304. zepben/ewb/model/cim/extensions/iec61970/base/protection/relay_setting.py +35 -0
  305. zepben/ewb/model/cim/extensions/iec61970/base/protection/voltage_relay.py +20 -0
  306. zepben/ewb/model/cim/extensions/iec61970/base/wires/__init__.py +4 -0
  307. zepben/ewb/model/cim/extensions/iec61970/base/wires/battery_control.py +36 -0
  308. zepben/ewb/model/cim/extensions/iec61970/base/wires/battery_control_mode.py +83 -0
  309. zepben/ewb/model/cim/extensions/iec61970/base/wires/transformer_cooling_type.py +57 -0
  310. zepben/ewb/model/cim/extensions/iec61970/base/wires/transformer_end_rated_s.py +26 -0
  311. zepben/ewb/model/cim/extensions/iec61970/base/wires/vector_group.py +293 -0
  312. zepben/ewb/model/cim/extensions/zbex.py +17 -0
  313. zepben/ewb/model/cim/iec61968/__init__.py +4 -0
  314. zepben/ewb/model/cim/iec61968/assetinfo/__init__.py +4 -0
  315. zepben/ewb/model/cim/iec61968/assetinfo/cable_info.py +15 -0
  316. zepben/ewb/model/cim/iec61968/assetinfo/no_load_test.py +42 -0
  317. zepben/ewb/model/cim/iec61968/assetinfo/open_circuit_test.py +42 -0
  318. zepben/ewb/model/cim/iec61968/assetinfo/overhead_wire_info.py +15 -0
  319. zepben/ewb/model/cim/iec61968/assetinfo/power_transformer_info.py +103 -0
  320. zepben/ewb/model/cim/iec61968/assetinfo/short_circuit_test.py +67 -0
  321. zepben/ewb/model/cim/iec61968/assetinfo/shunt_compensator_info.py +26 -0
  322. zepben/ewb/model/cim/iec61968/assetinfo/switch_info.py +17 -0
  323. zepben/ewb/model/cim/iec61968/assetinfo/transformer_end_info.py +137 -0
  324. zepben/ewb/model/cim/iec61968/assetinfo/transformer_tank_info.py +108 -0
  325. zepben/ewb/model/cim/iec61968/assetinfo/transformer_test.py +26 -0
  326. zepben/ewb/model/cim/iec61968/assetinfo/wire_info.py +24 -0
  327. zepben/ewb/model/cim/iec61968/assetinfo/wire_material_kind.py +57 -0
  328. zepben/ewb/model/cim/iec61968/assets/__init__.py +4 -0
  329. zepben/ewb/model/cim/iec61968/assets/asset.py +154 -0
  330. zepben/ewb/model/cim/iec61968/assets/asset_container.py +16 -0
  331. zepben/ewb/model/cim/iec61968/assets/asset_function.py +15 -0
  332. zepben/ewb/model/cim/iec61968/assets/asset_info.py +19 -0
  333. zepben/ewb/model/cim/iec61968/assets/asset_organisation_role.py +13 -0
  334. zepben/ewb/model/cim/iec61968/assets/asset_owner.py +13 -0
  335. zepben/ewb/model/cim/iec61968/assets/streetlight.py +29 -0
  336. zepben/ewb/model/cim/iec61968/assets/structure.py +16 -0
  337. zepben/ewb/model/cim/iec61968/common/__init__.py +4 -0
  338. zepben/ewb/model/cim/iec61968/common/agreement.py +16 -0
  339. zepben/ewb/model/cim/iec61968/common/document.py +36 -0
  340. zepben/ewb/model/cim/iec61968/common/location.py +129 -0
  341. zepben/ewb/model/cim/iec61968/common/organisation.py +15 -0
  342. zepben/ewb/model/cim/iec61968/common/organisation_role.py +22 -0
  343. zepben/ewb/model/cim/iec61968/common/position_point.py +44 -0
  344. zepben/ewb/model/cim/iec61968/common/street_address.py +28 -0
  345. zepben/ewb/model/cim/iec61968/common/street_detail.py +46 -0
  346. zepben/ewb/model/cim/iec61968/common/town_detail.py +25 -0
  347. zepben/ewb/model/cim/iec61968/customers/__init__.py +4 -0
  348. zepben/ewb/model/cim/iec61968/customers/customer.py +93 -0
  349. zepben/ewb/model/cim/iec61968/customers/customer_agreement.py +107 -0
  350. zepben/ewb/model/cim/iec61968/customers/customer_kind.py +69 -0
  351. zepben/ewb/model/cim/iec61968/customers/pricing_structure.py +88 -0
  352. zepben/ewb/model/cim/iec61968/customers/tariff.py +18 -0
  353. zepben/ewb/model/cim/iec61968/infiec61968/__init__.py +4 -0
  354. zepben/ewb/model/cim/iec61968/infiec61968/infassetinfo/__init__.py +4 -0
  355. zepben/ewb/model/cim/iec61968/infiec61968/infassetinfo/current_transformer_info.py +51 -0
  356. zepben/ewb/model/cim/iec61968/infiec61968/infassetinfo/potential_transformer_info.py +33 -0
  357. zepben/ewb/model/cim/iec61968/infiec61968/infassetinfo/transformer_construction_kind.py +69 -0
  358. zepben/ewb/model/cim/iec61968/infiec61968/infassetinfo/transformer_function_kind.py +45 -0
  359. zepben/ewb/model/cim/iec61968/infiec61968/infassets/__init__.py +4 -0
  360. zepben/ewb/model/cim/iec61968/infiec61968/infassets/pole.py +87 -0
  361. zepben/ewb/model/cim/iec61968/infiec61968/infassets/streetlight_lamp_kind.py +27 -0
  362. zepben/ewb/model/cim/iec61968/infiec61968/infcommon/__init__.py +4 -0
  363. zepben/ewb/model/cim/iec61968/infiec61968/infcommon/ratio.py +34 -0
  364. zepben/ewb/model/cim/iec61968/metering/__init__.py +4 -0
  365. zepben/ewb/model/cim/iec61968/metering/controlled_appliance.py +152 -0
  366. zepben/ewb/model/cim/iec61968/metering/end_device.py +165 -0
  367. zepben/ewb/model/cim/iec61968/metering/end_device_function.py +17 -0
  368. zepben/ewb/model/cim/iec61968/metering/end_device_function_kind.py +48 -0
  369. zepben/ewb/model/cim/iec61968/metering/meter.py +28 -0
  370. zepben/ewb/model/cim/iec61968/metering/usage_point.py +186 -0
  371. zepben/ewb/model/cim/iec61968/operations/__init__.py +4 -0
  372. zepben/ewb/model/cim/iec61968/operations/operational_restriction.py +92 -0
  373. zepben/ewb/model/cim/iec61970/__init__.py +4 -0
  374. zepben/ewb/model/cim/iec61970/base/__init__.py +4 -0
  375. zepben/ewb/model/cim/iec61970/base/auxiliaryequipment/__init__.py +4 -0
  376. zepben/ewb/model/cim/iec61970/base/auxiliaryequipment/auxiliary_equipment.py +24 -0
  377. zepben/ewb/model/cim/iec61970/base/auxiliaryequipment/current_transformer.py +37 -0
  378. zepben/ewb/model/cim/iec61970/base/auxiliaryequipment/fault_indicator.py +18 -0
  379. zepben/ewb/model/cim/iec61970/base/auxiliaryequipment/potential_transformer.py +38 -0
  380. zepben/ewb/model/cim/iec61970/base/auxiliaryequipment/potential_transformer_kind.py +30 -0
  381. zepben/ewb/model/cim/iec61970/base/auxiliaryequipment/sensor.py +92 -0
  382. zepben/ewb/model/cim/iec61970/base/core/__init__.py +4 -0
  383. zepben/ewb/model/cim/iec61970/base/core/ac_dc_terminal.py +16 -0
  384. zepben/ewb/model/cim/iec61970/base/core/base_voltage.py +17 -0
  385. zepben/ewb/model/cim/iec61970/base/core/conducting_equipment.py +198 -0
  386. zepben/ewb/model/cim/iec61970/base/core/connectivity_node.py +105 -0
  387. zepben/ewb/model/cim/iec61970/base/core/connectivity_node_container.py +15 -0
  388. zepben/ewb/model/cim/iec61970/base/core/curve.py +125 -0
  389. zepben/ewb/model/cim/iec61970/base/core/curve_data.py +29 -0
  390. zepben/ewb/model/cim/iec61970/base/core/equipment.py +366 -0
  391. zepben/ewb/model/cim/iec61970/base/core/equipment_container.py +199 -0
  392. zepben/ewb/model/cim/iec61970/base/core/feeder.py +260 -0
  393. zepben/ewb/model/cim/iec61970/base/core/geographical_region.py +82 -0
  394. zepben/ewb/model/cim/iec61970/base/core/identified_object.py +239 -0
  395. zepben/ewb/model/cim/iec61970/base/core/name.py +36 -0
  396. zepben/ewb/model/cim/iec61970/base/core/name_type.py +203 -0
  397. zepben/ewb/model/cim/iec61970/base/core/phase_code.py +202 -0
  398. zepben/ewb/model/cim/iec61970/base/core/power_system_resource.py +106 -0
  399. zepben/ewb/model/cim/iec61970/base/core/sub_geographical_region.py +93 -0
  400. zepben/ewb/model/cim/iec61970/base/core/substation.py +277 -0
  401. zepben/ewb/model/cim/iec61970/base/core/terminal.py +171 -0
  402. zepben/ewb/model/cim/iec61970/base/diagramlayout/__init__.py +4 -0
  403. zepben/ewb/model/cim/iec61970/base/diagramlayout/diagram.py +109 -0
  404. zepben/ewb/model/cim/iec61970/base/diagramlayout/diagram_object.py +160 -0
  405. zepben/ewb/model/cim/iec61970/base/diagramlayout/diagram_object_point.py +25 -0
  406. zepben/ewb/model/cim/iec61970/base/diagramlayout/diagram_style.py +28 -0
  407. zepben/ewb/model/cim/iec61970/base/diagramlayout/orientation_kind.py +29 -0
  408. zepben/ewb/model/cim/iec61970/base/domain/__init__.py +4 -0
  409. zepben/ewb/model/cim/iec61970/base/domain/unit_symbol.py +494 -0
  410. zepben/ewb/model/cim/iec61970/base/equivalents/__init__.py +4 -0
  411. zepben/ewb/model/cim/iec61970/base/equivalents/equivalent_branch.py +113 -0
  412. zepben/ewb/model/cim/iec61970/base/equivalents/equivalent_equipment.py +15 -0
  413. zepben/ewb/model/cim/iec61970/base/generation/__init__.py +4 -0
  414. zepben/ewb/model/cim/iec61970/base/generation/production/__init__.py +4 -0
  415. zepben/ewb/model/cim/iec61970/base/generation/production/battery_state_kind.py +39 -0
  416. zepben/ewb/model/cim/iec61970/base/generation/production/battery_unit.py +108 -0
  417. zepben/ewb/model/cim/iec61970/base/generation/production/photo_voltaic_unit.py +13 -0
  418. zepben/ewb/model/cim/iec61970/base/generation/production/power_electronics_unit.py +28 -0
  419. zepben/ewb/model/cim/iec61970/base/generation/production/power_electronics_wind_unit.py +13 -0
  420. zepben/ewb/model/cim/iec61970/base/meas/__init__.py +4 -0
  421. zepben/ewb/model/cim/iec61970/base/meas/accumulator.py +13 -0
  422. zepben/ewb/model/cim/iec61970/base/meas/accumulator_value.py +20 -0
  423. zepben/ewb/model/cim/iec61970/base/meas/analog.py +18 -0
  424. zepben/ewb/model/cim/iec61970/base/meas/analog_value.py +20 -0
  425. zepben/ewb/model/cim/iec61970/base/meas/control.py +26 -0
  426. zepben/ewb/model/cim/iec61970/base/meas/discrete.py +13 -0
  427. zepben/ewb/model/cim/iec61970/base/meas/discrete_value.py +20 -0
  428. zepben/ewb/model/cim/iec61970/base/meas/iopoint.py +16 -0
  429. zepben/ewb/model/cim/iec61970/base/meas/measurement.py +60 -0
  430. zepben/ewb/model/cim/iec61970/base/meas/measurement_value.py +21 -0
  431. zepben/ewb/model/cim/iec61970/base/protection/__init__.py +4 -0
  432. zepben/ewb/model/cim/iec61970/base/protection/current_relay.py +23 -0
  433. zepben/ewb/model/cim/iec61970/base/scada/__init__.py +4 -0
  434. zepben/ewb/model/cim/iec61970/base/scada/remote_control.py +22 -0
  435. zepben/ewb/model/cim/iec61970/base/scada/remote_point.py +16 -0
  436. zepben/ewb/model/cim/iec61970/base/scada/remote_source.py +22 -0
  437. zepben/ewb/model/cim/iec61970/base/wires/__init__.py +4 -0
  438. zepben/ewb/model/cim/iec61970/base/wires/ac_line_segment.py +214 -0
  439. zepben/ewb/model/cim/iec61970/base/wires/breaker.py +32 -0
  440. zepben/ewb/model/cim/iec61970/base/wires/busbar_section.py +19 -0
  441. zepben/ewb/model/cim/iec61970/base/wires/clamp.py +32 -0
  442. zepben/ewb/model/cim/iec61970/base/wires/conductor.py +49 -0
  443. zepben/ewb/model/cim/iec61970/base/wires/connector.py +16 -0
  444. zepben/ewb/model/cim/iec61970/base/wires/cut.py +36 -0
  445. zepben/ewb/model/cim/iec61970/base/wires/disconnector.py +17 -0
  446. zepben/ewb/model/cim/iec61970/base/wires/earth_fault_compensator.py +21 -0
  447. zepben/ewb/model/cim/iec61970/base/wires/energy_connection.py +15 -0
  448. zepben/ewb/model/cim/iec61970/base/wires/energy_consumer.py +107 -0
  449. zepben/ewb/model/cim/iec61970/base/wires/energy_consumer_phase.py +56 -0
  450. zepben/ewb/model/cim/iec61970/base/wires/energy_source.py +172 -0
  451. zepben/ewb/model/cim/iec61970/base/wires/energy_source_phase.py +45 -0
  452. zepben/ewb/model/cim/iec61970/base/wires/fuse.py +23 -0
  453. zepben/ewb/model/cim/iec61970/base/wires/ground.py +15 -0
  454. zepben/ewb/model/cim/iec61970/base/wires/ground_disconnector.py +15 -0
  455. zepben/ewb/model/cim/iec61970/base/wires/grounding_impedance.py +19 -0
  456. zepben/ewb/model/cim/iec61970/base/wires/jumper.py +16 -0
  457. zepben/ewb/model/cim/iec61970/base/wires/junction.py +15 -0
  458. zepben/ewb/model/cim/iec61970/base/wires/line.py +13 -0
  459. zepben/ewb/model/cim/iec61970/base/wires/linear_shunt_compensator.py +26 -0
  460. zepben/ewb/model/cim/iec61970/base/wires/load_break_switch.py +14 -0
  461. zepben/ewb/model/cim/iec61970/base/wires/per_length_impedance.py +13 -0
  462. zepben/ewb/model/cim/iec61970/base/wires/per_length_line_parameter.py +13 -0
  463. zepben/ewb/model/cim/iec61970/base/wires/per_length_phase_impedance.py +99 -0
  464. zepben/ewb/model/cim/iec61970/base/wires/per_length_sequence_impedance.py +43 -0
  465. zepben/ewb/model/cim/iec61970/base/wires/petersen_coil.py +22 -0
  466. zepben/ewb/model/cim/iec61970/base/wires/phase_impedance_data.py +37 -0
  467. zepben/ewb/model/cim/iec61970/base/wires/phase_shunt_connection_kind.py +40 -0
  468. zepben/ewb/model/cim/iec61970/base/wires/power_electronics_connection.py +524 -0
  469. zepben/ewb/model/cim/iec61970/base/wires/power_electronics_connection_phase.py +34 -0
  470. zepben/ewb/model/cim/iec61970/base/wires/power_transformer.py +217 -0
  471. zepben/ewb/model/cim/iec61970/base/wires/power_transformer_end.py +208 -0
  472. zepben/ewb/model/cim/iec61970/base/wires/protected_switch.py +96 -0
  473. zepben/ewb/model/cim/iec61970/base/wires/ratio_tap_changer.py +30 -0
  474. zepben/ewb/model/cim/iec61970/base/wires/reactive_capability_curve.py +16 -0
  475. zepben/ewb/model/cim/iec61970/base/wires/recloser.py +15 -0
  476. zepben/ewb/model/cim/iec61970/base/wires/regulating_cond_eq.py +45 -0
  477. zepben/ewb/model/cim/iec61970/base/wires/regulating_control.py +173 -0
  478. zepben/ewb/model/cim/iec61970/base/wires/regulating_control_mode_kind.py +48 -0
  479. zepben/ewb/model/cim/iec61970/base/wires/rotating_machine.py +36 -0
  480. zepben/ewb/model/cim/iec61970/base/wires/series_compensator.py +42 -0
  481. zepben/ewb/model/cim/iec61970/base/wires/shunt_compensator.py +59 -0
  482. zepben/ewb/model/cim/iec61970/base/wires/single_phase_kind.py +107 -0
  483. zepben/ewb/model/cim/iec61970/base/wires/static_var_compensator.py +40 -0
  484. zepben/ewb/model/cim/iec61970/base/wires/svc_control_mode.py +30 -0
  485. zepben/ewb/model/cim/iec61970/base/wires/switch.py +119 -0
  486. zepben/ewb/model/cim/iec61970/base/wires/synchronous_machine.py +168 -0
  487. zepben/ewb/model/cim/iec61970/base/wires/synchronous_machine_kind.py +46 -0
  488. zepben/ewb/model/cim/iec61970/base/wires/tap_changer.py +150 -0
  489. zepben/ewb/model/cim/iec61970/base/wires/tap_changer_control.py +49 -0
  490. zepben/ewb/model/cim/iec61970/base/wires/transformer_end.py +73 -0
  491. zepben/ewb/model/cim/iec61970/base/wires/transformer_star_impedance.py +48 -0
  492. zepben/ewb/model/cim/iec61970/base/wires/winding_connection.py +45 -0
  493. zepben/ewb/model/cim/iec61970/infiec61970/__init__.py +4 -0
  494. zepben/ewb/model/cim/iec61970/infiec61970/feeder/__init__.py +4 -0
  495. zepben/ewb/model/cim/iec61970/infiec61970/feeder/circuit.py +144 -0
  496. zepben/ewb/model/phases.py +168 -0
  497. zepben/ewb/model/resistance_reactance.py +40 -0
  498. zepben/ewb/services/__init__.py +4 -0
  499. zepben/ewb/services/common/__init__.py +16 -0
  500. zepben/ewb/services/common/base_service.py +383 -0
  501. zepben/ewb/services/common/base_service_comparator.py +394 -0
  502. zepben/ewb/services/common/difference.py +47 -0
  503. zepben/ewb/services/common/enum_mapper.py +55 -0
  504. zepben/ewb/services/common/meta/__init__.py +4 -0
  505. zepben/ewb/services/common/meta/data_source.py +16 -0
  506. zepben/ewb/services/common/meta/metadata_collection.py +28 -0
  507. zepben/ewb/services/common/meta/metadata_translations.py +47 -0
  508. zepben/ewb/services/common/meta/service_info.py +22 -0
  509. zepben/ewb/services/common/reference_resolvers.py +374 -0
  510. zepben/ewb/services/common/resolver.py +597 -0
  511. zepben/ewb/services/common/translator/__init__.py +4 -0
  512. zepben/ewb/services/common/translator/base_cim2proto.py +115 -0
  513. zepben/ewb/services/common/translator/base_proto2cim.py +146 -0
  514. zepben/ewb/services/common/translator/service_differences.py +81 -0
  515. zepben/ewb/services/common/translator/util.py +75 -0
  516. zepben/ewb/services/customer/__init__.py +4 -0
  517. zepben/ewb/services/customer/customer_service_comparator.py +52 -0
  518. zepben/ewb/services/customer/customers.py +23 -0
  519. zepben/ewb/services/customer/translator/__init__.py +21 -0
  520. zepben/ewb/services/customer/translator/customer_cim2proto.py +71 -0
  521. zepben/ewb/services/customer/translator/customer_enum_mappers.py +18 -0
  522. zepben/ewb/services/customer/translator/customer_proto2cim.py +87 -0
  523. zepben/ewb/services/diagram/__init__.py +4 -0
  524. zepben/ewb/services/diagram/diagram_service_comparator.py +39 -0
  525. zepben/ewb/services/diagram/diagrams.py +107 -0
  526. zepben/ewb/services/diagram/translator/__init__.py +11 -0
  527. zepben/ewb/services/diagram/translator/diagram_cim2proto.py +51 -0
  528. zepben/ewb/services/diagram/translator/diagram_enum_mappers.py +21 -0
  529. zepben/ewb/services/diagram/translator/diagram_proto2cim.py +61 -0
  530. zepben/ewb/services/measurement/__init__.py +4 -0
  531. zepben/ewb/services/measurement/measurements.py +35 -0
  532. zepben/ewb/services/measurement/translator/__init__.py +6 -0
  533. zepben/ewb/services/measurement/translator/measurement_cim2proto.py +42 -0
  534. zepben/ewb/services/measurement/translator/measurement_proto2cim.py +52 -0
  535. zepben/ewb/services/network/__init__.py +4 -0
  536. zepben/ewb/services/network/network_extensions.py +119 -0
  537. zepben/ewb/services/network/network_service.py +302 -0
  538. zepben/ewb/services/network/network_service_comparator.py +1322 -0
  539. zepben/ewb/services/network/network_state.py +36 -0
  540. zepben/ewb/services/network/tracing/__init__.py +4 -0
  541. zepben/ewb/services/network/tracing/busbranch_trace.py +36 -0
  542. zepben/ewb/services/network/tracing/connectivity/__init__.py +4 -0
  543. zepben/ewb/services/network/tracing/connectivity/connectivity_result.py +105 -0
  544. zepben/ewb/services/network/tracing/connectivity/nominal_phase_path.py +23 -0
  545. zepben/ewb/services/network/tracing/connectivity/phase_paths.py +70 -0
  546. zepben/ewb/services/network/tracing/connectivity/terminal_connectivity_connected.py +226 -0
  547. zepben/ewb/services/network/tracing/connectivity/terminal_connectivity_internal.py +64 -0
  548. zepben/ewb/services/network/tracing/connectivity/transformer_phase_paths.py +202 -0
  549. zepben/ewb/services/network/tracing/connectivity/xy_candidate_phase_paths.py +235 -0
  550. zepben/ewb/services/network/tracing/connectivity/xy_phase_step.py +24 -0
  551. zepben/ewb/services/network/tracing/feeder/__init__.py +4 -0
  552. zepben/ewb/services/network/tracing/feeder/assign_to_feeders.py +202 -0
  553. zepben/ewb/services/network/tracing/feeder/assign_to_lv_feeders.py +202 -0
  554. zepben/ewb/services/network/tracing/feeder/clear_direction.py +80 -0
  555. zepben/ewb/services/network/tracing/feeder/direction_status.py +133 -0
  556. zepben/ewb/services/network/tracing/feeder/feeder_direction.py +107 -0
  557. zepben/ewb/services/network/tracing/feeder/set_direction.py +143 -0
  558. zepben/ewb/services/network/tracing/find_swer_equipment.py +175 -0
  559. zepben/ewb/services/network/tracing/networktrace/__init__.py +4 -0
  560. zepben/ewb/services/network/tracing/networktrace/actions/__init__.py +4 -0
  561. zepben/ewb/services/network/tracing/networktrace/actions/equipment_tree_builder.py +104 -0
  562. zepben/ewb/services/network/tracing/networktrace/actions/tree_node.py +35 -0
  563. zepben/ewb/services/network/tracing/networktrace/compute_data.py +60 -0
  564. zepben/ewb/services/network/tracing/networktrace/conditions/__init__.py +4 -0
  565. zepben/ewb/services/network/tracing/networktrace/conditions/conditions.py +73 -0
  566. zepben/ewb/services/network/tracing/networktrace/conditions/direction_condition.py +63 -0
  567. zepben/ewb/services/network/tracing/networktrace/conditions/equipment_step_limit_condition.py +26 -0
  568. zepben/ewb/services/network/tracing/networktrace/conditions/equipment_type_step_limit_condition.py +44 -0
  569. zepben/ewb/services/network/tracing/networktrace/conditions/network_trace_queue_condition.py +67 -0
  570. zepben/ewb/services/network/tracing/networktrace/conditions/network_trace_stop_condition.py +65 -0
  571. zepben/ewb/services/network/tracing/networktrace/conditions/open_condition.py +39 -0
  572. zepben/ewb/services/network/tracing/networktrace/network_trace.py +433 -0
  573. zepben/ewb/services/network/tracing/networktrace/network_trace_action_type.py +42 -0
  574. zepben/ewb/services/network/tracing/networktrace/network_trace_queue_next.py +84 -0
  575. zepben/ewb/services/network/tracing/networktrace/network_trace_step.py +128 -0
  576. zepben/ewb/services/network/tracing/networktrace/network_trace_step_path_provider.py +351 -0
  577. zepben/ewb/services/network/tracing/networktrace/network_trace_tracker.py +39 -0
  578. zepben/ewb/services/network/tracing/networktrace/operators/__init__.py +14 -0
  579. zepben/ewb/services/network/tracing/networktrace/operators/equipment_container_state_operators.py +264 -0
  580. zepben/ewb/services/network/tracing/networktrace/operators/feeder_direction_state_operations.py +181 -0
  581. zepben/ewb/services/network/tracing/networktrace/operators/in_service_state_operators.py +76 -0
  582. zepben/ewb/services/network/tracing/networktrace/operators/network_state_operators.py +120 -0
  583. zepben/ewb/services/network/tracing/networktrace/operators/open_state_operators.py +104 -0
  584. zepben/ewb/services/network/tracing/networktrace/operators/phase_state_operators.py +56 -0
  585. zepben/ewb/services/network/tracing/networktrace/tracing.py +132 -0
  586. zepben/ewb/services/network/tracing/phases/__init__.py +4 -0
  587. zepben/ewb/services/network/tracing/phases/phase_inferrer.py +205 -0
  588. zepben/ewb/services/network/tracing/phases/phase_status.py +101 -0
  589. zepben/ewb/services/network/tracing/phases/remove_phases.py +143 -0
  590. zepben/ewb/services/network/tracing/phases/set_phases.py +490 -0
  591. zepben/ewb/services/network/tracing/traversal/__init__.py +4 -0
  592. zepben/ewb/services/network/tracing/traversal/context_value_computer.py +63 -0
  593. zepben/ewb/services/network/tracing/traversal/debug_logging.py +124 -0
  594. zepben/ewb/services/network/tracing/traversal/queue.py +112 -0
  595. zepben/ewb/services/network/tracing/traversal/queue_condition.py +75 -0
  596. zepben/ewb/services/network/tracing/traversal/step_action.py +83 -0
  597. zepben/ewb/services/network/tracing/traversal/step_context.py +59 -0
  598. zepben/ewb/services/network/tracing/traversal/stop_condition.py +57 -0
  599. zepben/ewb/services/network/tracing/traversal/traversal.py +634 -0
  600. zepben/ewb/services/network/tracing/traversal/traversal_condition.py +22 -0
  601. zepben/ewb/services/network/tracing/traversal/weighted_priority_queue.py +85 -0
  602. zepben/ewb/services/network/tracing/util.py +93 -0
  603. zepben/ewb/services/network/translator/__init__.py +392 -0
  604. zepben/ewb/services/network/translator/network_cim2proto.py +1867 -0
  605. zepben/ewb/services/network/translator/network_enum_mappers.py +78 -0
  606. zepben/ewb/services/network/translator/network_proto2cim.py +2201 -0
  607. zepben/ewb/services/services.py +48 -0
  608. zepben/ewb/streaming/__init__.py +4 -0
  609. zepben/ewb/streaming/data/__init__.py +4 -0
  610. zepben/ewb/streaming/data/current_state_event.py +314 -0
  611. zepben/ewb/streaming/data/current_state_event_batch.py +25 -0
  612. zepben/ewb/streaming/data/set_current_states_status.py +286 -0
  613. zepben/ewb/streaming/exceptions.py +14 -0
  614. zepben/ewb/streaming/get/__init__.py +4 -0
  615. zepben/ewb/streaming/get/consumer.py +209 -0
  616. zepben/ewb/streaming/get/customer_consumer.py +111 -0
  617. zepben/ewb/streaming/get/diagram_consumer.py +107 -0
  618. zepben/ewb/streaming/get/hierarchy/__init__.py +4 -0
  619. zepben/ewb/streaming/get/hierarchy/data.py +27 -0
  620. zepben/ewb/streaming/get/included_energized_containers.py +36 -0
  621. zepben/ewb/streaming/get/included_energizing_containers.py +36 -0
  622. zepben/ewb/streaming/get/network_consumer.py +870 -0
  623. zepben/ewb/streaming/get/query_network_state_client.py +64 -0
  624. zepben/ewb/streaming/get/query_network_state_service.py +94 -0
  625. zepben/ewb/streaming/grpc/__init__.py +4 -0
  626. zepben/ewb/streaming/grpc/auth_token_plugin.py +24 -0
  627. zepben/ewb/streaming/grpc/connect.py +209 -0
  628. zepben/ewb/streaming/grpc/grpc.py +107 -0
  629. zepben/ewb/streaming/grpc/grpc_channel_builder.py +190 -0
  630. zepben/ewb/streaming/mutations/__init__.py +4 -0
  631. zepben/ewb/streaming/mutations/update_network_state_client.py +80 -0
  632. zepben/ewb/streaming/mutations/update_network_state_service.py +61 -0
  633. zepben/ewb/testing/__init__.py +4 -0
  634. zepben/ewb/testing/test_network_builder.py +816 -0
  635. zepben/ewb/types.py +17 -0
  636. zepben/ewb/util.py +200 -0
  637. zepben_ewb-1.0.0.dist-info/METADATA +90 -0
  638. zepben_ewb-1.0.0.dist-info/RECORD +641 -0
  639. zepben_ewb-1.0.0.dist-info/WHEEL +5 -0
  640. zepben_ewb-1.0.0.dist-info/licenses/LICENSE +374 -0
  641. zepben_ewb-1.0.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,237 @@
1
+ # Copyright 2024 Zeppelin Bend Pty Ltd
2
+ # This Source Code Form is subject to the terms of the Mozilla Public
3
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
4
+ # file, You can obtain one at https://mozilla.org/MPL/2.0/.
5
+
6
+ __all__ = ['EwbDataFilePaths']
7
+
8
+ from datetime import date, timedelta
9
+ from pathlib import Path
10
+ from typing import Callable, Iterator, Optional, List
11
+
12
+ from zepben.ewb import require
13
+ from zepben.ewb.database.paths.database_type import DatabaseType
14
+
15
+
16
+ class EwbDataFilePaths:
17
+ """Provides paths to all the various data files / folders used by EWB."""
18
+
19
+ def __init__(self, base_dir: Path,
20
+ create_path: bool = False,
21
+ create_directories_func: Callable[[Path], None] = lambda it: it.mkdir(parents=True),
22
+ is_directory: Callable[[Path], bool] = Path.is_dir,
23
+ exists: Callable[[Path], bool] = Path.exists,
24
+ list_files: Callable[[Path], Iterator[Path]] = Path.iterdir):
25
+ """
26
+ :param base_dir: The root directory of the EWB data structure.
27
+ :param create_path: Create the root directory (and any missing parent folders) if it does not exist.
28
+ """
29
+ self.create_directories_func = create_directories_func
30
+ self.is_directory = is_directory
31
+ self.exists = exists
32
+ self.list_files = list_files
33
+ self._base_dir = base_dir
34
+
35
+ if create_path:
36
+ self.create_directories_func(base_dir)
37
+
38
+ require(self.is_directory(base_dir), lambda: f"base_dir must be a directory")
39
+
40
+ @property
41
+ def base_dir(self):
42
+ """The root directory of the EWB data structure."""
43
+ return self._base_dir
44
+
45
+ def customer(self, database_date: date) -> Path:
46
+ """
47
+ Determine the path to the "customers" database for the specified date.
48
+
49
+ :param database_date: The :class:`date` to use for the "customers" database.
50
+ :return: The :class:`path` to the "customers" database for the specified date.
51
+ """
52
+ return self._to_dated_path(database_date, DatabaseType.CUSTOMER.file_descriptor)
53
+
54
+ def diagram(self, database_date: date) -> Path:
55
+ """
56
+ Determine the path to the "diagrams" database for the specified date.
57
+
58
+ :param database_date: The :class:`date` to use for the "diagrams" database.
59
+ :return: The :class:`path` to the "diagrams" database for the specified date.
60
+ """
61
+ return self._to_dated_path(database_date, DatabaseType.DIAGRAM.file_descriptor)
62
+
63
+ def measurement(self, database_date: date) -> Path:
64
+ """
65
+ Determine the path to the "measurements" database for the specified date.
66
+
67
+ :param database_date: The :class:`date` to use for the "measurements" database.
68
+ :return: The :class:`path` to the "measurements" database for the specified date.
69
+ """
70
+ return self._to_dated_path(database_date, DatabaseType.MEASUREMENT.file_descriptor)
71
+
72
+ def network_model(self, database_date: date) -> Path:
73
+ """
74
+ Determine the path to the "network model" database for the specified date.
75
+
76
+ :param database_date: The :class:`date` to use for the "network model" database.
77
+ :return: The :class:`path` to the "network model" database for the specified date.
78
+ """
79
+ return self._to_dated_path(database_date, DatabaseType.NETWORK_MODEL.file_descriptor)
80
+
81
+ def tile_cache(self, database_date: date) -> Path:
82
+ """
83
+ Determine the path to the "tile cache" database for the specified date.
84
+
85
+ :param database_date: The :class:`date` to use for the "tile cache" database.
86
+ :return: The :class:`path` to the "tile cache" database for the specified date.
87
+ """
88
+ return self._to_dated_path(database_date, DatabaseType.TILE_CACHE.file_descriptor)
89
+
90
+ def energy_reading(self, database_date: date) -> Path:
91
+ """
92
+ Determine the path to the "energy readings" database for the specified date.
93
+
94
+ :param database_date: The :class:`date` to use for the "energy readings" database.
95
+ :return: The :class:`path` to the "energy readings" database for the specified date.
96
+ """
97
+ return self._to_dated_path(database_date, DatabaseType.ENERGY_READING.file_descriptor)
98
+
99
+ def energy_readings_index(self) -> Path:
100
+ """
101
+ Determine the path to the "energy readings index" database.
102
+
103
+ :return: The :class:`path` to the "energy readings index" database.
104
+ """
105
+ return self._base_dir.joinpath(f"{DatabaseType.ENERGY_READINGS_INDEX.file_descriptor}.sqlite")
106
+
107
+ def load_aggregator_meters_by_date(self) -> Path:
108
+ """
109
+ Determine the path to the "load aggregator meters-by-date" database.
110
+
111
+ :return: The :class:`path` to the "load aggregator meters-by-date" database.
112
+ """
113
+ return self._base_dir.joinpath(f"{DatabaseType.LOAD_AGGREGATOR_METERS_BY_DATE.file_descriptor}.sqlite")
114
+
115
+ def weather_reading(self) -> Path:
116
+ """
117
+ Determine the path to the "weather readings" database.
118
+
119
+ :return: The :class:`path` to the "weather readings" database.
120
+ """
121
+ return self._base_dir.joinpath(f"{DatabaseType.WEATHER_READING.file_descriptor}.sqlite")
122
+
123
+ def results_cache(self) -> Path:
124
+ """
125
+ Determine the path to the "results cache" database.
126
+
127
+ :return: The :class:`path` to the "results cache" database.
128
+ """
129
+ return self._base_dir.joinpath(f"{DatabaseType.RESULTS_CACHE.file_descriptor}.sqlite")
130
+
131
+ def create_directories(self, database_date: date) -> Path:
132
+ """
133
+ Create the directories required to have a valid path for the specified date.
134
+
135
+ :param database_date: The :class:`date` required in the path.
136
+ :return: The :class:`path` to the directory for the `database_date`.
137
+ """
138
+ date_path = self._base_dir.joinpath(str(database_date))
139
+ if self.exists(date_path):
140
+ return date_path
141
+ else:
142
+ self.create_directories_func(date_path)
143
+ return date_path
144
+
145
+ def _to_dated_path(self, database_date: date, file: str) -> Path:
146
+ return self._base_dir.joinpath(str(database_date), f"{database_date}-{file}.sqlite")
147
+
148
+ def _check_exists(self, database_type: DatabaseType, database_date: date) -> bool:
149
+ """
150
+ Check if a database of the specified type and date exists.
151
+
152
+ :param database_type: The type of database to search for.
153
+ :param database_date: The date to check.
154
+ :return: `True` if a database of the specified `database_type` and `database_date` exists in the date path.
155
+ """
156
+ if not database_type.per_date:
157
+ raise ValueError("INTERNAL ERROR: Should only be calling `checkExists` for `perDate` files.")
158
+
159
+ if database_type == DatabaseType.CUSTOMER:
160
+ model_path = self.customer(database_date)
161
+ elif database_type == DatabaseType.DIAGRAM:
162
+ model_path = self.diagram(database_date)
163
+ elif database_type == DatabaseType.MEASUREMENT:
164
+ model_path = self.measurement(database_date)
165
+ elif database_type == DatabaseType.NETWORK_MODEL:
166
+ model_path = self.network_model(database_date)
167
+ elif database_type == DatabaseType.TILE_CACHE:
168
+ model_path = self.tile_cache(database_date)
169
+ elif database_type == DatabaseType.ENERGY_READING:
170
+ model_path = self.energy_reading(database_date)
171
+ else:
172
+ raise ValueError(
173
+ "INTERNAL ERROR: Should only be calling `check_exists` for `per_date` files, which should all be covered above, so go ahead and add it.")
174
+ return self.exists(model_path)
175
+
176
+ def find_closest(self, database_type: DatabaseType, max_days_to_search: int = 999, target_date: date = date.today(), search_forwards: bool = False) -> \
177
+ Optional[date]:
178
+ """
179
+ Find the closest date with a usable database of the specified type.
180
+
181
+ :param database_type: The type of database to search for.
182
+ :param max_days_to_search: The maximum number of days to search for a valid database.
183
+ :param target_date: The target :class:`date`. Defaults to today.
184
+ :param search_forwards: Indicates the search should also look forwards in time from `start_date` for a valid file. Defaults to reverse search only.
185
+ :return: The closest :class:`date` to `database_date` with a valid database of `database_type` within the search parameters, or `None` if no valid database was found.
186
+ """
187
+ if not database_type.per_date:
188
+ return None
189
+
190
+ if self._check_exists(database_type, target_date):
191
+ return target_date
192
+
193
+ offset = 1
194
+
195
+ while offset <= max_days_to_search:
196
+ offset_days = timedelta(offset)
197
+ try:
198
+ previous_date = target_date - offset_days
199
+ if self._check_exists(database_type, previous_date):
200
+ return previous_date
201
+ except OverflowError:
202
+ pass
203
+
204
+ if search_forwards:
205
+ try:
206
+ forward_date = target_date + offset_days
207
+ if self._check_exists(database_type, forward_date):
208
+ return forward_date
209
+ except OverflowError:
210
+ pass
211
+ offset += 1
212
+ return None
213
+
214
+ def _get_available_dates_for(self, database_type: DatabaseType) -> List[date]:
215
+ if not database_type.per_date:
216
+ raise ValueError(
217
+ "INTERNAL ERROR: Should only be calling `_get_available_dates_for` for `per_date` files.")
218
+
219
+ to_return = list()
220
+
221
+ for file in self.list_files(self._base_dir):
222
+ if self.is_directory(file):
223
+ try:
224
+ database_date = date.fromisoformat(file.name)
225
+ if self.exists(self._to_dated_path(database_date, database_type.file_descriptor)):
226
+ to_return.append(database_date)
227
+ except ValueError:
228
+ pass
229
+ return sorted(to_return)
230
+
231
+ def get_network_model_databases(self) -> List[date]:
232
+ """
233
+ Find available network-model databases in data path.
234
+
235
+ :return: A list of :class:`date`'s for which network-model databases exist in the data path.
236
+ """
237
+ return self._get_available_dates_for(DatabaseType.NETWORK_MODEL)
@@ -0,0 +1,4 @@
1
+ # Copyright 2025 Zeppelin Bend Pty Ltd
2
+ # This Source Code Form is subject to the terms of the Mozilla Public
3
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
4
+ # file, You can obtain one at https://mozilla.org/MPL/2.0/.
@@ -0,0 +1,37 @@
1
+ # Copyright 2025 Zeppelin Bend Pty Ltd
2
+ # This Source Code Form is subject to the terms of the Mozilla Public
3
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
4
+ # file, You can obtain one at https://mozilla.org/MPL/2.0/.
5
+
6
+ __all__ = ["Nullable", "Column"]
7
+
8
+ from enum import Enum
9
+
10
+ from zepben.ewb.dataclassy import dataclass
11
+ from zepben.ewb.util import require
12
+
13
+
14
+ class Nullable(Enum):
15
+ NONE = ""
16
+ NOT_NULL = "NOT NULL"
17
+ NULL = "NULL"
18
+
19
+ @property
20
+ def sql(self):
21
+ return self.value
22
+
23
+
24
+ @dataclass(slots=True)
25
+ class Column:
26
+ query_index: int
27
+ name: str
28
+ type: str
29
+ nullable: Nullable = Nullable.NONE
30
+
31
+ def __init__(self):
32
+ require(self.query_index >= 0, lambda: "You cannot use a negative query index.")
33
+ require(not self.name.isspace() and self.name, lambda: "Column Name cannot be blank.")
34
+ require(not self.type.isspace() and self.type, lambda: "Column Type cannot be blank.")
35
+
36
+ def __str__(self):
37
+ return f"{self.name} {self.type} {self.nullable.sql}".rstrip()
@@ -0,0 +1,142 @@
1
+ # Copyright 2025 Zeppelin Bend Pty Ltd
2
+ # This Source Code Form is subject to the terms of the Mozilla Public
3
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
4
+ # file, You can obtain one at https://mozilla.org/MPL/2.0/.
5
+ from __future__ import annotations
6
+
7
+ __all__ = ["SqlTable"]
8
+
9
+ from abc import abstractmethod, ABCMeta
10
+ from operator import attrgetter
11
+ from typing import List, Optional, Type, Any, Generator
12
+
13
+ from zepben.ewb.database.sql.column import Column, Nullable
14
+
15
+
16
+ class SqlTable(metaclass=ABCMeta):
17
+ """
18
+ Represents a table in an SQL Database.
19
+
20
+ By default, this class doesn't support creating schema creation statements, allowing support for database with external schema management.
21
+ """
22
+
23
+ column_index: int = 0
24
+ """Used to specify index of the column in the table during initialisation. Always increment BEFORE creating a Column. Indices start from 1."""
25
+
26
+ _column_set: Optional[List[Column]] = None
27
+ _create_table_sql: Optional[str] = None
28
+ _prepared_insert_sql: Optional[str] = None
29
+ _prepared_update_sql: Optional[str] = None
30
+ _create_indexes_sql: Optional[List[str]] = None
31
+ _select_sql: Optional[str] = None
32
+
33
+ @property
34
+ @abstractmethod
35
+ def name(self) -> str:
36
+ """
37
+ The name of the table in the actual database.
38
+ """
39
+ pass
40
+
41
+ #
42
+ # NOTE: This function is called `description` in teh JVM SDK, but in the python SDK this
43
+ # conflicts with the `description` column of `TableIdentifiedObjects`.
44
+ #
45
+ def describe(self) -> str:
46
+ """
47
+ Readable description of the contents of the table for adding to logs.
48
+ """
49
+ return self.name.replace("_", " ")
50
+
51
+ @property
52
+ @abstractmethod
53
+ def create_table_sql(self):
54
+ """
55
+ The SQL statement that should be executed to create the table in the database.
56
+ """
57
+ raise NotImplemented
58
+
59
+ @property
60
+ def prepared_insert_sql(self):
61
+ """
62
+ The SQL statement that should be used with a `PreparedStatement` to insert entries into the table.
63
+ """
64
+ if self._prepared_insert_sql is None:
65
+ self._prepared_insert_sql = (f"INSERT INTO {self.name} ({', '.join([c.name for c in self.column_set])}) "
66
+ f"VALUES ({', '.join(['?' for _ in self.column_set])})")
67
+ return self._prepared_insert_sql
68
+
69
+ @property
70
+ @abstractmethod
71
+ def create_indexes_sql(self):
72
+ """
73
+ The SQL statement that should be executed to create the indexes for the table in the database. Should be executed after all
74
+ entries are inserted into the table.
75
+ """
76
+ raise NotImplemented
77
+
78
+ @property
79
+ def select_sql(self):
80
+ """
81
+ The SQL statement that should be used to read the entries from the table in the database.
82
+ """
83
+ if self._select_sql is None:
84
+ self._select_sql = f"SELECT {', '.join([c.name for c in self.column_set])} FROM {self.name}"
85
+ return self._select_sql
86
+
87
+ @property
88
+ def prepared_update_sql(self):
89
+ """
90
+ The SQL statement that should be used with a `PreparedStatement` to update entries into the table.
91
+ """
92
+ if self._prepared_update_sql is None:
93
+ self._prepared_update_sql = f"UPDATE {self.name} SET {', '.join([f'{c.name} = ?' for c in self.column_set])}"
94
+ return self._prepared_update_sql
95
+
96
+ @property
97
+ def unique_index_columns(self) -> Generator[List[Column], None, None]:
98
+ """
99
+ A list of column groups that require a unique index in the database
100
+ """
101
+ yield from []
102
+
103
+ @property
104
+ def non_unique_index_columns(self) -> Generator[List[Column], None, None]:
105
+ """
106
+ A list of column groups that require a non-unique index in the database
107
+ """
108
+ yield from []
109
+
110
+ @property
111
+ def column_set(self) -> List[Column]:
112
+ if self._column_set is None:
113
+ self._column_set = list(self._build_column_set(self.__class__, self))
114
+ return self._column_set
115
+
116
+ @staticmethod
117
+ def _build_column_set(clazz: Type[Any], instance: SqlTable) -> Generator[Column, None, None]:
118
+ """
119
+ Builds the list of columns for use in DDL statements for this table.
120
+
121
+ :param clazz: The class of this table.
122
+ :param instance:
123
+ """
124
+ cols = list()
125
+ for field, x in instance.__dict__.items():
126
+ if isinstance(x, Column):
127
+ if x.query_index != len(cols) + 1:
128
+ raise ValueError(
129
+ f"Field {field} in SQL Table class {clazz.__name__} is using an invalid column index. "
130
+ f"Did you forget to increment column_index, or did you skip one?"
131
+ )
132
+ cols.append(x)
133
+
134
+ if len(set([c.name for c in cols])) != len(cols):
135
+ raise ValueError("You have duplicate column names, go fix that.")
136
+
137
+ yield from sorted(cols, key=attrgetter('query_index'))
138
+
139
+ def _create_column(self, name: str, type_: str, nullable: Nullable = Nullable.NONE) -> Column:
140
+ self.column_index += 1
141
+ # noinspection PyArgumentList
142
+ return Column(self.column_index, name, type_, nullable)
@@ -0,0 +1,4 @@
1
+ # Copyright 2024 Zeppelin Bend Pty Ltd
2
+ # This Source Code Form is subject to the terms of the Mozilla Public
3
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
4
+ # file, You can obtain one at https://mozilla.org/MPL/2.0/.
@@ -0,0 +1,4 @@
1
+ # Copyright 2024 Zeppelin Bend Pty Ltd
2
+ # This Source Code Form is subject to the terms of the Mozilla Public
3
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
4
+ # file, You can obtain one at https://mozilla.org/MPL/2.0/.
@@ -0,0 +1,212 @@
1
+ # Copyright 2024 Zeppelin Bend Pty Ltd
2
+ # This Source Code Form is subject to the terms of the Mozilla Public
3
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
4
+ # file, You can obtain one at https://mozilla.org/MPL/2.0/.
5
+
6
+ __all__ = ["BaseCimReader"]
7
+
8
+ import logging
9
+ from abc import ABC
10
+ from typing import Callable, Optional, Type
11
+
12
+ from zepben.ewb.database.sqlite.common.reader_exceptions import DuplicateMRIDException
13
+ from zepben.ewb.database.sqlite.extensions.result_set import ResultSet
14
+ from zepben.ewb.database.sqlite.tables.iec61968.common.table_documents import TableDocuments
15
+ from zepben.ewb.database.sqlite.tables.iec61968.common.table_organisation_roles import TableOrganisationRoles
16
+ from zepben.ewb.database.sqlite.tables.iec61968.common.table_organisations import TableOrganisations
17
+ from zepben.ewb.database.sqlite.tables.iec61970.base.core.table_identified_objects import TableIdentifiedObjects
18
+ from zepben.ewb.database.sqlite.tables.iec61970.base.core.table_name_types import TableNameTypes
19
+ from zepben.ewb.database.sqlite.tables.iec61970.base.core.table_names import TableNames
20
+ from zepben.ewb.model.cim.iec61968.common.document import Document
21
+ from zepben.ewb.model.cim.iec61968.common.organisation import Organisation
22
+ from zepben.ewb.model.cim.iec61968.common.organisation_role import OrganisationRole
23
+ from zepben.ewb.model.cim.iec61970.base.core.identified_object import IdentifiedObject, TIdentifiedObject
24
+ from zepben.ewb.model.cim.iec61970.base.core.name_type import NameType
25
+ from zepben.ewb.services.common.base_service import BaseService
26
+
27
+
28
+ class BaseCimReader(ABC):
29
+ """
30
+ A base class for reading CIM objects from a database.
31
+ """
32
+
33
+ def __init__(self, service: BaseService):
34
+ super().__init__()
35
+ self._logger: logging.Logger = logging.getLogger(self.__class__.__name__)
36
+ """The `Logger` to use for this reader."""
37
+
38
+ self._service = service
39
+ """The `BaseService` used to store any items read from the database."""
40
+
41
+ ###################
42
+ # IEC61968 Common #
43
+ ###################
44
+
45
+ def _load_document(self, document: Document, table: TableDocuments, result_set: ResultSet) -> bool:
46
+ """
47
+ Populate the `Document` fields from `TableDocuments`.
48
+
49
+ :param document: The `Document` instance to populate.
50
+ :param table: The database table to read the `Document` fields from.
51
+ :param result_set: The record in the database table containing the fields for this `Document`.
52
+
53
+ :return: True if the `Document` was successfully read from the database and added to the service.
54
+ :raises SQLException: For any errors encountered reading from the database.
55
+ """
56
+ document.title = result_set.get_string(table.title.query_index, on_none=None)
57
+ document.created_date_time = result_set.get_instant(table.created_date_time.query_index, on_none=None)
58
+ document.author_name = result_set.get_string(table.author_name.query_index, on_none=None)
59
+ document.type = result_set.get_string(table.type.query_index, on_none=None)
60
+ document.status = result_set.get_string(table.status.query_index, on_none=None)
61
+ document.comment = result_set.get_string(table.comment.query_index, on_none=None)
62
+
63
+ return self._load_identified_object(document, table, result_set)
64
+
65
+ def load_organisations(self, table: TableOrganisations, result_set: ResultSet, set_identifier: Callable[[str], str]) -> bool:
66
+ """
67
+ Create an `Organisation` and populate its fields from `TableOrganisations`.
68
+
69
+ :param table: The database table to read the `Organisation` fields from.
70
+ :param result_set: The record in the database table containing the fields for this `Organisation`.
71
+ :param set_identifier: A callback to register the mRID of this `Organisation` for logging purposes.
72
+
73
+ :return: True if the `Organisation` was successfully read from the database and added to the service.
74
+ :raises SQLException: For any errors encountered reading from the database.
75
+ """
76
+ organisation = Organisation(mrid=set_identifier(result_set.get_string(table.mrid.query_index)))
77
+
78
+ return self._load_identified_object(organisation, table, result_set) and self._add_or_throw(organisation)
79
+
80
+ def _load_organisation_role(self, organisation_role: OrganisationRole, table: TableOrganisationRoles, result_set: ResultSet) -> bool:
81
+ """
82
+ Populate the `OrganisationRole` fields from `TableOrganisationRoles`.
83
+
84
+ :param organisation_role: The `OrganisationRole` instance to populate.
85
+ :param table: The database table to read the `OrganisationRole` fields from.
86
+ :param result_set: The record in the database table containing the fields for this `OrganisationRole`.
87
+
88
+ :return: True if the `OrganisationRole` was successfully read from the database and added to the service.
89
+ :raises SQLException: For any errors encountered reading from the database.
90
+ """
91
+ organisation_role.organisation = self._ensure_get(
92
+ result_set.get_string(table.organisation_mrid.query_index, on_none=None),
93
+ Organisation
94
+ )
95
+
96
+ return self._load_identified_object(organisation_role, table, result_set)
97
+
98
+ ######################
99
+ # IEC61970 Base Core #
100
+ ######################
101
+
102
+ @staticmethod
103
+ def _load_identified_object(identified_object: IdentifiedObject, table: TableIdentifiedObjects, result_set: ResultSet) -> bool:
104
+ """
105
+ Populate the `IdentifiedObject` fields from `TableIdentifiedObjects`.
106
+
107
+ :param identified_object: The `IdentifiedObject` instance to populate.
108
+ :param table: The database table to read the `IdentifiedObject` fields from.
109
+ :param result_set: The record in the database table containing the fields for this `IdentifiedObject`.
110
+
111
+ :return: True if the `IdentifiedObject` was successfully read from the database and added to the service.
112
+ :raises SQLException: For any errors encountered reading from the database.
113
+ """
114
+ identified_object.name = result_set.get_string(table.name_.query_index, on_none=None)
115
+ identified_object.description = result_set.get_string(table.description.query_index, on_none=None)
116
+ # Currently unused
117
+ # identified_object.num_diagram_objects = result_set.get_int(table.num_diagram_objects.query_index)
118
+
119
+ return True
120
+
121
+ def load_names(self, table: TableNames, result_set: ResultSet, set_last_name: Callable[[str], str]) -> bool:
122
+ """
123
+ Create a `Name` and populate its fields from `TableNames`.
124
+
125
+ :param table: The database table to read the `Name` fields from.
126
+ :param result_set: The record in the database table containing the fields for this `Name`.
127
+ :param set_last_name: A callback to register the name of this `Name` for logging purposes.
128
+
129
+ :return: True if the `Name` was successfully read from the database and added to the service.
130
+ :raises SQLException: For any errors encountered reading from the database.
131
+ """
132
+ name_type_name = result_set.get_string(table.name_type_name.query_index)
133
+ name_name = result_set.get_string(table.name_.query_index)
134
+ set_last_name(f"{name_type_name}:{name_name}")
135
+
136
+ name_type = self._service.get_name_type(name_type_name)
137
+ self._service.get(
138
+ result_set.get_string(table.identified_object_mrid.query_index),
139
+ IdentifiedObject,
140
+ generate_error=lambda mrid, typ: f"Failed to find {typ} with mRID {mrid} for Name {name_name} [{name_type_name}]"
141
+ ).add_name(name_type, name_name)
142
+
143
+ return True
144
+
145
+ def load_name_types(self, table: TableNameTypes, result_set: ResultSet, set_last_name_type: Callable[[str], str]) -> bool:
146
+ """
147
+ Create a `NameType` and populate its fields from `TableNameTypes`.
148
+
149
+ :param table: The database table to read the `NameType` fields from.
150
+ :param result_set: The record in the database table containing the fields for this `NameType`.
151
+ :param set_last_name_type: A callback to register the name of this `NameType` for logging purposes.
152
+
153
+ :return: True if the `NameType` was successfully read from the database and added to the service.
154
+ :raises SQLException: For any errors encountered reading from the database.
155
+ """
156
+ # noinspection PyArgumentList
157
+ name_type = NameType(set_last_name_type(result_set.get_string(table.name_.query_index)))
158
+ name_type.description = result_set.get_string(table.description.query_index)
159
+
160
+ return self._add_or_throw_name_type(name_type)
161
+
162
+ def _add_or_throw(self, identified_object: IdentifiedObject) -> bool:
163
+ """
164
+ Try and add the `identified_object` to the `service`, and throw an `Exception` if unsuccessful.
165
+
166
+ :param identified_object: The `IdentifiedObject` to add to the `service`.
167
+
168
+ :return: True in all instances, otherwise it throws.
169
+ :raises DuplicateMRIDException: If the `IdentifiedObject.mRID` has already been used.
170
+ :raises UnsupportedIdentifiedObjectException: If the `IdentifiedObject` is not supported by the `service`. This is an indication of an internal coding
171
+ issue, rather than a problem with the data being read, and in a correctly configured system will never occur.
172
+ """
173
+ if self._service.add(identified_object):
174
+ return True
175
+ else:
176
+ duplicate = self._service.get(identified_object.mrid)
177
+ raise DuplicateMRIDException(
178
+ f"Failed to load {identified_object}. " +
179
+ f"Unable to add to service '{self._service.name}': duplicate MRID ({duplicate})"
180
+ )
181
+
182
+ def _add_or_throw_name_type(self, name_type: NameType) -> bool:
183
+ """
184
+ Try and add the `name_type` to the `service`, and throw an `Exception` if unsuccessful.
185
+
186
+ :param name_type: The `NameType` to add to the `service`.
187
+
188
+ :return: True in all instances, otherwise it throws.
189
+ :raises DuplicateMRIDException: If the `NameType.name` has already been used.
190
+ """
191
+ if self._service.add_name_type(name_type):
192
+ return True
193
+ else:
194
+ raise DuplicateMRIDException(
195
+ f"Failed to load NameType {name_type.name}. " +
196
+ f"Unable to add to service '{self._service.name}': duplicate NameType)"
197
+ )
198
+
199
+ def _ensure_get(self, mrid: Optional[str], type_: Type[TIdentifiedObject] = IdentifiedObject) -> Optional[TIdentifiedObject]:
200
+ """
201
+ Optionally get an object associated with this service and throw if it is not found.
202
+
203
+ :param mrid: The mRID of the object to find.
204
+ :param type_: The type of object to look for. If this is a base class it will search all subclasses.
205
+
206
+ :return: The object identified by `mrid` as `type_` if it was found, or null if no `mrid` was supplied.
207
+ :raises MRIDLookupException: if no objects of type `type_` are found with the specified `mrid`
208
+ """
209
+ if (mrid is None) or (len(mrid) == 0):
210
+ return None
211
+ else:
212
+ return self._service.get(mrid, type_)