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.
- zepben/ewb/__init__.py +601 -0
- zepben/ewb/auth/__init__.py +10 -0
- zepben/ewb/auth/client/__init__.py +5 -0
- zepben/ewb/auth/client/zepben_token_fetcher.py +273 -0
- zepben/ewb/auth/common/__init__.py +5 -0
- zepben/ewb/auth/common/auth_exception.py +16 -0
- zepben/ewb/auth/common/auth_method.py +28 -0
- zepben/ewb/auth/common/auth_provider_config.py +96 -0
- zepben/ewb/database/__init__.py +4 -0
- zepben/ewb/database/paths/__init__.py +4 -0
- zepben/ewb/database/paths/database_type.py +34 -0
- zepben/ewb/database/paths/ewb_data_file_paths.py +237 -0
- zepben/ewb/database/sql/__init__.py +4 -0
- zepben/ewb/database/sql/column.py +37 -0
- zepben/ewb/database/sql/sql_table.py +142 -0
- zepben/ewb/database/sqlite/__init__.py +4 -0
- zepben/ewb/database/sqlite/common/__init__.py +4 -0
- zepben/ewb/database/sqlite/common/base_cim_reader.py +212 -0
- zepben/ewb/database/sqlite/common/base_cim_writer.py +159 -0
- zepben/ewb/database/sqlite/common/base_collection_reader.py +96 -0
- zepben/ewb/database/sqlite/common/base_collection_writer.py +73 -0
- zepben/ewb/database/sqlite/common/base_database_reader.py +127 -0
- zepben/ewb/database/sqlite/common/base_database_tables.py +137 -0
- zepben/ewb/database/sqlite/common/base_database_writer.py +195 -0
- zepben/ewb/database/sqlite/common/base_entry_writer.py +34 -0
- zepben/ewb/database/sqlite/common/base_service_reader.py +50 -0
- zepben/ewb/database/sqlite/common/base_service_writer.py +104 -0
- zepben/ewb/database/sqlite/common/metadata_collection_reader.py +39 -0
- zepben/ewb/database/sqlite/common/metadata_collection_writer.py +38 -0
- zepben/ewb/database/sqlite/common/metadata_entry_reader.py +45 -0
- zepben/ewb/database/sqlite/common/metadata_entry_writer.py +41 -0
- zepben/ewb/database/sqlite/common/reader_exceptions.py +30 -0
- zepben/ewb/database/sqlite/customer/__init__.py +4 -0
- zepben/ewb/database/sqlite/customer/customer_cim_reader.py +169 -0
- zepben/ewb/database/sqlite/customer/customer_cim_writer.py +137 -0
- zepben/ewb/database/sqlite/customer/customer_database_reader.py +44 -0
- zepben/ewb/database/sqlite/customer/customer_database_tables.py +37 -0
- zepben/ewb/database/sqlite/customer/customer_database_writer.py +45 -0
- zepben/ewb/database/sqlite/customer/customer_service_reader.py +57 -0
- zepben/ewb/database/sqlite/customer/customer_service_writer.py +47 -0
- zepben/ewb/database/sqlite/diagram/__init__.py +4 -0
- zepben/ewb/database/sqlite/diagram/diagram_cim_reader.py +105 -0
- zepben/ewb/database/sqlite/diagram/diagram_cim_writer.py +81 -0
- zepben/ewb/database/sqlite/diagram/diagram_database_reader.py +45 -0
- zepben/ewb/database/sqlite/diagram/diagram_database_tables.py +29 -0
- zepben/ewb/database/sqlite/diagram/diagram_database_writer.py +44 -0
- zepben/ewb/database/sqlite/diagram/diagram_service_reader.py +49 -0
- zepben/ewb/database/sqlite/diagram/diagram_service_writer.py +41 -0
- zepben/ewb/database/sqlite/extensions/__init__.py +4 -0
- zepben/ewb/database/sqlite/extensions/prepared_statement.py +112 -0
- zepben/ewb/database/sqlite/extensions/result_set.py +153 -0
- zepben/ewb/database/sqlite/network/__init__.py +4 -0
- zepben/ewb/database/sqlite/network/network_cim_reader.py +3167 -0
- zepben/ewb/database/sqlite/network/network_cim_writer.py +2561 -0
- zepben/ewb/database/sqlite/network/network_database_reader.py +175 -0
- zepben/ewb/database/sqlite/network/network_database_tables.py +242 -0
- zepben/ewb/database/sqlite/network/network_database_writer.py +43 -0
- zepben/ewb/database/sqlite/network/network_service_reader.py +265 -0
- zepben/ewb/database/sqlite/network/network_service_writer.py +209 -0
- zepben/ewb/database/sqlite/tables/__init__.py +4 -0
- zepben/ewb/database/sqlite/tables/associations/__init__.py +4 -0
- zepben/ewb/database/sqlite/tables/associations/loop_substation_relationship.py +17 -0
- zepben/ewb/database/sqlite/tables/associations/table_asset_organisation_roles_assets.py +40 -0
- zepben/ewb/database/sqlite/tables/associations/table_assets_power_system_resources.py +41 -0
- zepben/ewb/database/sqlite/tables/associations/table_battery_units_battery_controls.py +40 -0
- zepben/ewb/database/sqlite/tables/associations/table_circuits_substations.py +40 -0
- zepben/ewb/database/sqlite/tables/associations/table_circuits_terminals.py +40 -0
- zepben/ewb/database/sqlite/tables/associations/table_customer_agreements_pricing_structures.py +40 -0
- zepben/ewb/database/sqlite/tables/associations/table_end_devices_end_device_functions.py +40 -0
- zepben/ewb/database/sqlite/tables/associations/table_equipment_equipment_containers.py +40 -0
- zepben/ewb/database/sqlite/tables/associations/table_equipment_operational_restrictions.py +40 -0
- zepben/ewb/database/sqlite/tables/associations/table_equipment_usage_points.py +40 -0
- zepben/ewb/database/sqlite/tables/associations/table_loops_substations.py +43 -0
- zepben/ewb/database/sqlite/tables/associations/table_pricing_structures_tariffs.py +40 -0
- zepben/ewb/database/sqlite/tables/associations/table_protection_relay_functions_protected_switches.py +40 -0
- zepben/ewb/database/sqlite/tables/associations/table_protection_relay_functions_sensors.py +40 -0
- zepben/ewb/database/sqlite/tables/associations/table_protection_relay_schemes_protection_relay_functions.py +40 -0
- zepben/ewb/database/sqlite/tables/associations/table_synchronous_machines_reactive_capability_curves.py +39 -0
- zepben/ewb/database/sqlite/tables/associations/table_usage_points_end_devices.py +40 -0
- zepben/ewb/database/sqlite/tables/exceptions.py +10 -0
- zepben/ewb/database/sqlite/tables/extensions/__init__.py +4 -0
- zepben/ewb/database/sqlite/tables/extensions/iec61968/__init__.py +4 -0
- zepben/ewb/database/sqlite/tables/extensions/iec61968/assetinfo/__init__.py +4 -0
- zepben/ewb/database/sqlite/tables/extensions/iec61968/assetinfo/table_reclose_delays.py +38 -0
- zepben/ewb/database/sqlite/tables/extensions/iec61968/assetinfo/table_relay_info.py +21 -0
- zepben/ewb/database/sqlite/tables/extensions/iec61968/metering/__init__.py +4 -0
- zepben/ewb/database/sqlite/tables/extensions/iec61968/metering/table_pan_demand_response_functions.py +21 -0
- zepben/ewb/database/sqlite/tables/extensions/iec61970/__init__.py +4 -0
- zepben/ewb/database/sqlite/tables/extensions/iec61970/base/__init__.py +4 -0
- zepben/ewb/database/sqlite/tables/extensions/iec61970/base/core/__init__.py +4 -0
- zepben/ewb/database/sqlite/tables/extensions/iec61970/base/core/table_sites.py +15 -0
- zepben/ewb/database/sqlite/tables/extensions/iec61970/base/feeder/__init__.py +4 -0
- zepben/ewb/database/sqlite/tables/extensions/iec61970/base/feeder/table_loops.py +15 -0
- zepben/ewb/database/sqlite/tables/extensions/iec61970/base/feeder/table_lv_feeders.py +20 -0
- zepben/ewb/database/sqlite/tables/extensions/iec61970/base/generation/__init__.py +4 -0
- zepben/ewb/database/sqlite/tables/extensions/iec61970/base/generation/production/__init__.py +4 -0
- zepben/ewb/database/sqlite/tables/extensions/iec61970/base/generation/production/table_ev_charging_units.py +15 -0
- zepben/ewb/database/sqlite/tables/extensions/iec61970/base/protection/__init__.py +4 -0
- zepben/ewb/database/sqlite/tables/extensions/iec61970/base/protection/table_distance_relays.py +28 -0
- zepben/ewb/database/sqlite/tables/extensions/iec61970/base/protection/table_protection_relay_function_thresholds.py +36 -0
- zepben/ewb/database/sqlite/tables/extensions/iec61970/base/protection/table_protection_relay_function_time_limits.py +34 -0
- zepben/ewb/database/sqlite/tables/extensions/iec61970/base/protection/table_protection_relay_functions.py +24 -0
- zepben/ewb/database/sqlite/tables/extensions/iec61970/base/protection/table_protection_relay_schemes.py +20 -0
- zepben/ewb/database/sqlite/tables/extensions/iec61970/base/protection/table_protection_relay_systems.py +20 -0
- zepben/ewb/database/sqlite/tables/extensions/iec61970/base/protection/table_voltage_relays.py +15 -0
- zepben/ewb/database/sqlite/tables/extensions/iec61970/base/wires/__init__.py +4 -0
- zepben/ewb/database/sqlite/tables/extensions/iec61970/base/wires/table_battery_controls.py +23 -0
- zepben/ewb/database/sqlite/tables/extensions/iec61970/base/wires/table_power_transformer_end_ratings.py +34 -0
- zepben/ewb/database/sqlite/tables/iec61968/__init__.py +4 -0
- zepben/ewb/database/sqlite/tables/iec61968/assetinfo/__init__.py +4 -0
- zepben/ewb/database/sqlite/tables/iec61968/assetinfo/table_cable_info.py +15 -0
- zepben/ewb/database/sqlite/tables/iec61968/assetinfo/table_no_load_tests.py +24 -0
- zepben/ewb/database/sqlite/tables/iec61968/assetinfo/table_open_circuit_tests.py +24 -0
- zepben/ewb/database/sqlite/tables/iec61968/assetinfo/table_overhead_wire_info.py +15 -0
- zepben/ewb/database/sqlite/tables/iec61968/assetinfo/table_power_transformer_info.py +15 -0
- zepben/ewb/database/sqlite/tables/iec61968/assetinfo/table_short_circuit_tests.py +29 -0
- zepben/ewb/database/sqlite/tables/iec61968/assetinfo/table_shunt_compensator_info.py +23 -0
- zepben/ewb/database/sqlite/tables/iec61968/assetinfo/table_switch_info.py +20 -0
- zepben/ewb/database/sqlite/tables/iec61968/assetinfo/table_transformer_end_info.py +46 -0
- zepben/ewb/database/sqlite/tables/iec61968/assetinfo/table_transformer_tank_info.py +27 -0
- zepben/ewb/database/sqlite/tables/iec61968/assetinfo/table_transformer_test.py +19 -0
- zepben/ewb/database/sqlite/tables/iec61968/assetinfo/table_wire_info.py +19 -0
- zepben/ewb/database/sqlite/tables/iec61968/assets/__init__.py +4 -0
- zepben/ewb/database/sqlite/tables/iec61968/assets/table_asset_containers.py +14 -0
- zepben/ewb/database/sqlite/tables/iec61968/assets/table_asset_functions.py +14 -0
- zepben/ewb/database/sqlite/tables/iec61968/assets/table_asset_info.py +14 -0
- zepben/ewb/database/sqlite/tables/iec61968/assets/table_asset_organisation_roles.py +14 -0
- zepben/ewb/database/sqlite/tables/iec61968/assets/table_asset_owners.py +15 -0
- zepben/ewb/database/sqlite/tables/iec61968/assets/table_assets.py +18 -0
- zepben/ewb/database/sqlite/tables/iec61968/assets/table_streetlights.py +22 -0
- zepben/ewb/database/sqlite/tables/iec61968/assets/table_structures.py +14 -0
- zepben/ewb/database/sqlite/tables/iec61968/common/__init__.py +4 -0
- zepben/ewb/database/sqlite/tables/iec61968/common/table_agreements.py +14 -0
- zepben/ewb/database/sqlite/tables/iec61968/common/table_documents.py +23 -0
- zepben/ewb/database/sqlite/tables/iec61968/common/table_location_street_address_field.py +18 -0
- zepben/ewb/database/sqlite/tables/iec61968/common/table_location_street_addresses.py +33 -0
- zepben/ewb/database/sqlite/tables/iec61968/common/table_locations.py +15 -0
- zepben/ewb/database/sqlite/tables/iec61968/common/table_organisation_roles.py +18 -0
- zepben/ewb/database/sqlite/tables/iec61968/common/table_organisations.py +15 -0
- zepben/ewb/database/sqlite/tables/iec61968/common/table_position_points.py +30 -0
- zepben/ewb/database/sqlite/tables/iec61968/common/table_street_addresses.py +26 -0
- zepben/ewb/database/sqlite/tables/iec61968/common/table_town_details.py +19 -0
- zepben/ewb/database/sqlite/tables/iec61968/customers/__init__.py +4 -0
- zepben/ewb/database/sqlite/tables/iec61968/customers/table_customer_agreements.py +27 -0
- zepben/ewb/database/sqlite/tables/iec61968/customers/table_customers.py +22 -0
- zepben/ewb/database/sqlite/tables/iec61968/customers/table_pricing_structures.py +15 -0
- zepben/ewb/database/sqlite/tables/iec61968/customers/table_tariffs.py +15 -0
- zepben/ewb/database/sqlite/tables/iec61968/infiec61968/__init__.py +4 -0
- zepben/ewb/database/sqlite/tables/iec61968/infiec61968/infassetinfo/__init__.py +4 -0
- zepben/ewb/database/sqlite/tables/iec61968/infiec61968/infassetinfo/table_current_transformer_info.py +33 -0
- zepben/ewb/database/sqlite/tables/iec61968/infiec61968/infassetinfo/table_potential_transformer_info.py +26 -0
- zepben/ewb/database/sqlite/tables/iec61968/infiec61968/infassets/__init__.py +4 -0
- zepben/ewb/database/sqlite/tables/iec61968/infiec61968/infassets/table_poles.py +20 -0
- zepben/ewb/database/sqlite/tables/iec61968/metering/__init__.py +4 -0
- zepben/ewb/database/sqlite/tables/iec61968/metering/table_end_device_functions.py +18 -0
- zepben/ewb/database/sqlite/tables/iec61968/metering/table_end_devices.py +19 -0
- zepben/ewb/database/sqlite/tables/iec61968/metering/table_meters.py +15 -0
- zepben/ewb/database/sqlite/tables/iec61968/metering/table_usage_points.py +23 -0
- zepben/ewb/database/sqlite/tables/iec61968/operations/__init__.py +4 -0
- zepben/ewb/database/sqlite/tables/iec61968/operations/table_operational_restrictions.py +15 -0
- zepben/ewb/database/sqlite/tables/iec61970/__init__.py +4 -0
- zepben/ewb/database/sqlite/tables/iec61970/base/__init__.py +4 -0
- zepben/ewb/database/sqlite/tables/iec61970/base/auxiliaryequipment/__init__.py +4 -0
- zepben/ewb/database/sqlite/tables/iec61970/base/auxiliaryequipment/table_auxiliary_equipment.py +18 -0
- zepben/ewb/database/sqlite/tables/iec61970/base/auxiliaryequipment/table_current_transformers.py +21 -0
- zepben/ewb/database/sqlite/tables/iec61970/base/auxiliaryequipment/table_fault_indicators.py +15 -0
- zepben/ewb/database/sqlite/tables/iec61970/base/auxiliaryequipment/table_potential_transformers.py +21 -0
- zepben/ewb/database/sqlite/tables/iec61970/base/auxiliaryequipment/table_sensors.py +14 -0
- zepben/ewb/database/sqlite/tables/iec61970/base/core/__init__.py +4 -0
- zepben/ewb/database/sqlite/tables/iec61970/base/core/table_ac_dc_terminals.py +14 -0
- zepben/ewb/database/sqlite/tables/iec61970/base/core/table_base_voltages.py +20 -0
- zepben/ewb/database/sqlite/tables/iec61970/base/core/table_conducting_equipment.py +18 -0
- zepben/ewb/database/sqlite/tables/iec61970/base/core/table_connectivity_node_containers.py +14 -0
- zepben/ewb/database/sqlite/tables/iec61970/base/core/table_connectivity_nodes.py +15 -0
- zepben/ewb/database/sqlite/tables/iec61970/base/core/table_curve_data.py +46 -0
- zepben/ewb/database/sqlite/tables/iec61970/base/core/table_curves.py +17 -0
- zepben/ewb/database/sqlite/tables/iec61970/base/core/table_equipment.py +20 -0
- zepben/ewb/database/sqlite/tables/iec61970/base/core/table_equipment_containers.py +14 -0
- zepben/ewb/database/sqlite/tables/iec61970/base/core/table_feeders.py +28 -0
- zepben/ewb/database/sqlite/tables/iec61970/base/core/table_geographical_regions.py +15 -0
- zepben/ewb/database/sqlite/tables/iec61970/base/core/table_identified_objects.py +29 -0
- zepben/ewb/database/sqlite/tables/iec61970/base/core/table_name_types.py +28 -0
- zepben/ewb/database/sqlite/tables/iec61970/base/core/table_names.py +36 -0
- zepben/ewb/database/sqlite/tables/iec61970/base/core/table_power_system_resources.py +19 -0
- zepben/ewb/database/sqlite/tables/iec61970/base/core/table_sub_geographical_regions.py +27 -0
- zepben/ewb/database/sqlite/tables/iec61970/base/core/table_substations.py +27 -0
- zepben/ewb/database/sqlite/tables/iec61970/base/core/table_terminals.py +35 -0
- zepben/ewb/database/sqlite/tables/iec61970/base/diagramlayout/__init__.py +4 -0
- zepben/ewb/database/sqlite/tables/iec61970/base/diagramlayout/table_diagram_object_points.py +35 -0
- zepben/ewb/database/sqlite/tables/iec61970/base/diagramlayout/table_diagram_objects.py +31 -0
- zepben/ewb/database/sqlite/tables/iec61970/base/diagramlayout/table_diagrams.py +21 -0
- zepben/ewb/database/sqlite/tables/iec61970/base/equivalents/__init__.py +4 -0
- zepben/ewb/database/sqlite/tables/iec61970/base/equivalents/table_equivalent_branches.py +35 -0
- zepben/ewb/database/sqlite/tables/iec61970/base/equivalents/table_equivalent_equipment.py +14 -0
- zepben/ewb/database/sqlite/tables/iec61970/base/generation/__init__.py +4 -0
- zepben/ewb/database/sqlite/tables/iec61970/base/generation/production/__init__.py +4 -0
- zepben/ewb/database/sqlite/tables/iec61970/base/generation/production/table_battery_units.py +22 -0
- zepben/ewb/database/sqlite/tables/iec61970/base/generation/production/table_photo_voltaic_units.py +15 -0
- zepben/ewb/database/sqlite/tables/iec61970/base/generation/production/table_power_electronics_units.py +26 -0
- zepben/ewb/database/sqlite/tables/iec61970/base/generation/production/table_power_electronics_wind_units.py +15 -0
- zepben/ewb/database/sqlite/tables/iec61970/base/meas/__init__.py +4 -0
- zepben/ewb/database/sqlite/tables/iec61970/base/meas/table_accumulators.py +15 -0
- zepben/ewb/database/sqlite/tables/iec61970/base/meas/table_analogs.py +20 -0
- zepben/ewb/database/sqlite/tables/iec61970/base/meas/table_controls.py +20 -0
- zepben/ewb/database/sqlite/tables/iec61970/base/meas/table_discretes.py +15 -0
- zepben/ewb/database/sqlite/tables/iec61970/base/meas/table_io_points.py +14 -0
- zepben/ewb/database/sqlite/tables/iec61970/base/meas/table_measurements.py +30 -0
- zepben/ewb/database/sqlite/tables/iec61970/base/protection/__init__.py +4 -0
- zepben/ewb/database/sqlite/tables/iec61970/base/protection/table_current_relays.py +22 -0
- zepben/ewb/database/sqlite/tables/iec61970/base/scada/__init__.py +4 -0
- zepben/ewb/database/sqlite/tables/iec61970/base/scada/table_remote_controls.py +20 -0
- zepben/ewb/database/sqlite/tables/iec61970/base/scada/table_remote_points.py +14 -0
- zepben/ewb/database/sqlite/tables/iec61970/base/scada/table_remote_sources.py +20 -0
- zepben/ewb/database/sqlite/tables/iec61970/base/wires/__init__.py +4 -0
- zepben/ewb/database/sqlite/tables/iec61970/base/wires/table_ac_line_segments.py +20 -0
- zepben/ewb/database/sqlite/tables/iec61970/base/wires/table_breakers.py +20 -0
- zepben/ewb/database/sqlite/tables/iec61970/base/wires/table_busbar_sections.py +15 -0
- zepben/ewb/database/sqlite/tables/iec61970/base/wires/table_clamps.py +23 -0
- zepben/ewb/database/sqlite/tables/iec61970/base/wires/table_conductors.py +21 -0
- zepben/ewb/database/sqlite/tables/iec61970/base/wires/table_connectors.py +14 -0
- zepben/ewb/database/sqlite/tables/iec61970/base/wires/table_cuts.py +23 -0
- zepben/ewb/database/sqlite/tables/iec61970/base/wires/table_disconnectors.py +15 -0
- zepben/ewb/database/sqlite/tables/iec61970/base/wires/table_earth_fault_compensators.py +22 -0
- zepben/ewb/database/sqlite/tables/iec61970/base/wires/table_energy_connections.py +14 -0
- zepben/ewb/database/sqlite/tables/iec61970/base/wires/table_energy_consumer_phases.py +37 -0
- zepben/ewb/database/sqlite/tables/iec61970/base/wires/table_energy_consumers.py +26 -0
- zepben/ewb/database/sqlite/tables/iec61970/base/wires/table_energy_source_phases.py +33 -0
- zepben/ewb/database/sqlite/tables/iec61970/base/wires/table_energy_sources.py +44 -0
- zepben/ewb/database/sqlite/tables/iec61970/base/wires/table_fuses.py +20 -0
- zepben/ewb/database/sqlite/tables/iec61970/base/wires/table_ground_disconnectors.py +15 -0
- zepben/ewb/database/sqlite/tables/iec61970/base/wires/table_grounding_impedances.py +24 -0
- zepben/ewb/database/sqlite/tables/iec61970/base/wires/table_grounds.py +15 -0
- zepben/ewb/database/sqlite/tables/iec61970/base/wires/table_jumpers.py +15 -0
- zepben/ewb/database/sqlite/tables/iec61970/base/wires/table_junctions.py +15 -0
- zepben/ewb/database/sqlite/tables/iec61970/base/wires/table_linear_shunt_compensators.py +23 -0
- zepben/ewb/database/sqlite/tables/iec61970/base/wires/table_lines.py +14 -0
- zepben/ewb/database/sqlite/tables/iec61970/base/wires/table_load_break_switches.py +15 -0
- zepben/ewb/database/sqlite/tables/iec61970/base/wires/table_per_length_impedances.py +14 -0
- zepben/ewb/database/sqlite/tables/iec61970/base/wires/table_per_length_line_parameters.py +14 -0
- zepben/ewb/database/sqlite/tables/iec61970/base/wires/table_per_length_phase_impedances.py +18 -0
- zepben/ewb/database/sqlite/tables/iec61970/base/wires/table_per_length_sequence_impedances.py +27 -0
- zepben/ewb/database/sqlite/tables/iec61970/base/wires/table_petersen_coils.py +27 -0
- zepben/ewb/database/sqlite/tables/iec61970/base/wires/table_phase_impedance_data.py +52 -0
- zepben/ewb/database/sqlite/tables/iec61970/base/wires/table_power_electronics_connection_phases.py +30 -0
- zepben/ewb/database/sqlite/tables/iec61970/base/wires/table_power_electronics_connections.py +50 -0
- zepben/ewb/database/sqlite/tables/iec61970/base/wires/table_power_transformer_ends.py +43 -0
- zepben/ewb/database/sqlite/tables/iec61970/base/wires/table_power_transformers.py +24 -0
- zepben/ewb/database/sqlite/tables/iec61970/base/wires/table_protected_switches.py +18 -0
- zepben/ewb/database/sqlite/tables/iec61970/base/wires/table_ratio_tap_changers.py +28 -0
- zepben/ewb/database/sqlite/tables/iec61970/base/wires/table_reactive_capability_curves.py +18 -0
- zepben/ewb/database/sqlite/tables/iec61970/base/wires/table_reclosers.py +15 -0
- zepben/ewb/database/sqlite/tables/iec61970/base/wires/table_regulating_cond_eq.py +19 -0
- zepben/ewb/database/sqlite/tables/iec61970/base/wires/table_regulating_controls.py +29 -0
- zepben/ewb/database/sqlite/tables/iec61970/base/wires/table_rotating_machines.py +36 -0
- zepben/ewb/database/sqlite/tables/iec61970/base/wires/table_series_compensators.py +25 -0
- zepben/ewb/database/sqlite/tables/iec61970/base/wires/table_shunt_compensators.py +22 -0
- zepben/ewb/database/sqlite/tables/iec61970/base/wires/table_static_var_compensator.py +24 -0
- zepben/ewb/database/sqlite/tables/iec61970/base/wires/table_switches.py +21 -0
- zepben/ewb/database/sqlite/tables/iec61970/base/wires/table_synchronous_machines.py +95 -0
- zepben/ewb/database/sqlite/tables/iec61970/base/wires/table_tap_changer_controls.py +28 -0
- zepben/ewb/database/sqlite/tables/iec61970/base/wires/table_tap_changers.py +25 -0
- zepben/ewb/database/sqlite/tables/iec61970/base/wires/table_transformer_ends.py +30 -0
- zepben/ewb/database/sqlite/tables/iec61970/base/wires/table_transformer_star_impedances.py +32 -0
- zepben/ewb/database/sqlite/tables/iec61970/infiec61970/__init__.py +4 -0
- zepben/ewb/database/sqlite/tables/iec61970/infiec61970/feeder/__init__.py +4 -0
- zepben/ewb/database/sqlite/tables/iec61970/infiec61970/feeder/table_circuits.py +27 -0
- zepben/ewb/database/sqlite/tables/sqlite_table.py +45 -0
- zepben/ewb/database/sqlite/tables/table_metadata_data_sources.py +21 -0
- zepben/ewb/database/sqlite/tables/table_version.py +39 -0
- zepben/ewb/dataclassy/__init__.py +15 -0
- zepben/ewb/dataclassy/dataclass.py +192 -0
- zepben/ewb/dataclassy/decorator.py +35 -0
- zepben/ewb/dataclassy/functions.py +80 -0
- zepben/ewb/examples/__init__.py +6 -0
- zepben/ewb/examples/simple_test_network.py +158 -0
- zepben/ewb/exceptions.py +52 -0
- zepben/ewb/model/__init__.py +4 -0
- zepben/ewb/model/busbranch/__init__.py +4 -0
- zepben/ewb/model/busbranch/bus_branch.py +1051 -0
- zepben/ewb/model/cim/__init__.py +4 -0
- zepben/ewb/model/cim/extensions/__init__.py +4 -0
- zepben/ewb/model/cim/extensions/iec61968/__init__.py +4 -0
- zepben/ewb/model/cim/extensions/iec61968/assetinfo/__init__.py +4 -0
- zepben/ewb/model/cim/extensions/iec61968/assetinfo/relay_info.py +128 -0
- zepben/ewb/model/cim/extensions/iec61968/metering/__init__.py +4 -0
- zepben/ewb/model/cim/extensions/iec61968/metering/pan_demand_reponse_function.py +112 -0
- zepben/ewb/model/cim/extensions/iec61970/__init__.py +4 -0
- zepben/ewb/model/cim/extensions/iec61970/base/__init__.py +4 -0
- zepben/ewb/model/cim/extensions/iec61970/base/core/__init__.py +4 -0
- zepben/ewb/model/cim/extensions/iec61970/base/core/site.py +37 -0
- zepben/ewb/model/cim/extensions/iec61970/base/feeder/__init__.py +4 -0
- zepben/ewb/model/cim/extensions/iec61970/base/feeder/loop.py +207 -0
- zepben/ewb/model/cim/extensions/iec61970/base/feeder/lv_feeder.py +258 -0
- zepben/ewb/model/cim/extensions/iec61970/base/generation/__init__.py +4 -0
- zepben/ewb/model/cim/extensions/iec61970/base/generation/production/__init__.py +4 -0
- zepben/ewb/model/cim/extensions/iec61970/base/generation/production/ev_charging_unit.py +18 -0
- zepben/ewb/model/cim/extensions/iec61970/base/protection/__init__.py +4 -0
- zepben/ewb/model/cim/extensions/iec61970/base/protection/distance_relay.py +69 -0
- zepben/ewb/model/cim/extensions/iec61970/base/protection/power_direction_kind.py +36 -0
- zepben/ewb/model/cim/extensions/iec61970/base/protection/protection_kind.py +112 -0
- zepben/ewb/model/cim/extensions/iec61970/base/protection/protection_relay_function.py +448 -0
- zepben/ewb/model/cim/extensions/iec61970/base/protection/protection_relay_scheme.py +97 -0
- zepben/ewb/model/cim/extensions/iec61970/base/protection/protection_relay_system.py +97 -0
- zepben/ewb/model/cim/extensions/iec61970/base/protection/relay_setting.py +35 -0
- zepben/ewb/model/cim/extensions/iec61970/base/protection/voltage_relay.py +20 -0
- zepben/ewb/model/cim/extensions/iec61970/base/wires/__init__.py +4 -0
- zepben/ewb/model/cim/extensions/iec61970/base/wires/battery_control.py +36 -0
- zepben/ewb/model/cim/extensions/iec61970/base/wires/battery_control_mode.py +83 -0
- zepben/ewb/model/cim/extensions/iec61970/base/wires/transformer_cooling_type.py +57 -0
- zepben/ewb/model/cim/extensions/iec61970/base/wires/transformer_end_rated_s.py +26 -0
- zepben/ewb/model/cim/extensions/iec61970/base/wires/vector_group.py +293 -0
- zepben/ewb/model/cim/extensions/zbex.py +17 -0
- zepben/ewb/model/cim/iec61968/__init__.py +4 -0
- zepben/ewb/model/cim/iec61968/assetinfo/__init__.py +4 -0
- zepben/ewb/model/cim/iec61968/assetinfo/cable_info.py +15 -0
- zepben/ewb/model/cim/iec61968/assetinfo/no_load_test.py +42 -0
- zepben/ewb/model/cim/iec61968/assetinfo/open_circuit_test.py +42 -0
- zepben/ewb/model/cim/iec61968/assetinfo/overhead_wire_info.py +15 -0
- zepben/ewb/model/cim/iec61968/assetinfo/power_transformer_info.py +103 -0
- zepben/ewb/model/cim/iec61968/assetinfo/short_circuit_test.py +67 -0
- zepben/ewb/model/cim/iec61968/assetinfo/shunt_compensator_info.py +26 -0
- zepben/ewb/model/cim/iec61968/assetinfo/switch_info.py +17 -0
- zepben/ewb/model/cim/iec61968/assetinfo/transformer_end_info.py +137 -0
- zepben/ewb/model/cim/iec61968/assetinfo/transformer_tank_info.py +108 -0
- zepben/ewb/model/cim/iec61968/assetinfo/transformer_test.py +26 -0
- zepben/ewb/model/cim/iec61968/assetinfo/wire_info.py +24 -0
- zepben/ewb/model/cim/iec61968/assetinfo/wire_material_kind.py +57 -0
- zepben/ewb/model/cim/iec61968/assets/__init__.py +4 -0
- zepben/ewb/model/cim/iec61968/assets/asset.py +154 -0
- zepben/ewb/model/cim/iec61968/assets/asset_container.py +16 -0
- zepben/ewb/model/cim/iec61968/assets/asset_function.py +15 -0
- zepben/ewb/model/cim/iec61968/assets/asset_info.py +19 -0
- zepben/ewb/model/cim/iec61968/assets/asset_organisation_role.py +13 -0
- zepben/ewb/model/cim/iec61968/assets/asset_owner.py +13 -0
- zepben/ewb/model/cim/iec61968/assets/streetlight.py +29 -0
- zepben/ewb/model/cim/iec61968/assets/structure.py +16 -0
- zepben/ewb/model/cim/iec61968/common/__init__.py +4 -0
- zepben/ewb/model/cim/iec61968/common/agreement.py +16 -0
- zepben/ewb/model/cim/iec61968/common/document.py +36 -0
- zepben/ewb/model/cim/iec61968/common/location.py +129 -0
- zepben/ewb/model/cim/iec61968/common/organisation.py +15 -0
- zepben/ewb/model/cim/iec61968/common/organisation_role.py +22 -0
- zepben/ewb/model/cim/iec61968/common/position_point.py +44 -0
- zepben/ewb/model/cim/iec61968/common/street_address.py +28 -0
- zepben/ewb/model/cim/iec61968/common/street_detail.py +46 -0
- zepben/ewb/model/cim/iec61968/common/town_detail.py +25 -0
- zepben/ewb/model/cim/iec61968/customers/__init__.py +4 -0
- zepben/ewb/model/cim/iec61968/customers/customer.py +93 -0
- zepben/ewb/model/cim/iec61968/customers/customer_agreement.py +107 -0
- zepben/ewb/model/cim/iec61968/customers/customer_kind.py +69 -0
- zepben/ewb/model/cim/iec61968/customers/pricing_structure.py +88 -0
- zepben/ewb/model/cim/iec61968/customers/tariff.py +18 -0
- zepben/ewb/model/cim/iec61968/infiec61968/__init__.py +4 -0
- zepben/ewb/model/cim/iec61968/infiec61968/infassetinfo/__init__.py +4 -0
- zepben/ewb/model/cim/iec61968/infiec61968/infassetinfo/current_transformer_info.py +51 -0
- zepben/ewb/model/cim/iec61968/infiec61968/infassetinfo/potential_transformer_info.py +33 -0
- zepben/ewb/model/cim/iec61968/infiec61968/infassetinfo/transformer_construction_kind.py +69 -0
- zepben/ewb/model/cim/iec61968/infiec61968/infassetinfo/transformer_function_kind.py +45 -0
- zepben/ewb/model/cim/iec61968/infiec61968/infassets/__init__.py +4 -0
- zepben/ewb/model/cim/iec61968/infiec61968/infassets/pole.py +87 -0
- zepben/ewb/model/cim/iec61968/infiec61968/infassets/streetlight_lamp_kind.py +27 -0
- zepben/ewb/model/cim/iec61968/infiec61968/infcommon/__init__.py +4 -0
- zepben/ewb/model/cim/iec61968/infiec61968/infcommon/ratio.py +34 -0
- zepben/ewb/model/cim/iec61968/metering/__init__.py +4 -0
- zepben/ewb/model/cim/iec61968/metering/controlled_appliance.py +152 -0
- zepben/ewb/model/cim/iec61968/metering/end_device.py +165 -0
- zepben/ewb/model/cim/iec61968/metering/end_device_function.py +17 -0
- zepben/ewb/model/cim/iec61968/metering/end_device_function_kind.py +48 -0
- zepben/ewb/model/cim/iec61968/metering/meter.py +28 -0
- zepben/ewb/model/cim/iec61968/metering/usage_point.py +186 -0
- zepben/ewb/model/cim/iec61968/operations/__init__.py +4 -0
- zepben/ewb/model/cim/iec61968/operations/operational_restriction.py +92 -0
- zepben/ewb/model/cim/iec61970/__init__.py +4 -0
- zepben/ewb/model/cim/iec61970/base/__init__.py +4 -0
- zepben/ewb/model/cim/iec61970/base/auxiliaryequipment/__init__.py +4 -0
- zepben/ewb/model/cim/iec61970/base/auxiliaryequipment/auxiliary_equipment.py +24 -0
- zepben/ewb/model/cim/iec61970/base/auxiliaryequipment/current_transformer.py +37 -0
- zepben/ewb/model/cim/iec61970/base/auxiliaryequipment/fault_indicator.py +18 -0
- zepben/ewb/model/cim/iec61970/base/auxiliaryequipment/potential_transformer.py +38 -0
- zepben/ewb/model/cim/iec61970/base/auxiliaryequipment/potential_transformer_kind.py +30 -0
- zepben/ewb/model/cim/iec61970/base/auxiliaryequipment/sensor.py +92 -0
- zepben/ewb/model/cim/iec61970/base/core/__init__.py +4 -0
- zepben/ewb/model/cim/iec61970/base/core/ac_dc_terminal.py +16 -0
- zepben/ewb/model/cim/iec61970/base/core/base_voltage.py +17 -0
- zepben/ewb/model/cim/iec61970/base/core/conducting_equipment.py +198 -0
- zepben/ewb/model/cim/iec61970/base/core/connectivity_node.py +105 -0
- zepben/ewb/model/cim/iec61970/base/core/connectivity_node_container.py +15 -0
- zepben/ewb/model/cim/iec61970/base/core/curve.py +125 -0
- zepben/ewb/model/cim/iec61970/base/core/curve_data.py +29 -0
- zepben/ewb/model/cim/iec61970/base/core/equipment.py +366 -0
- zepben/ewb/model/cim/iec61970/base/core/equipment_container.py +199 -0
- zepben/ewb/model/cim/iec61970/base/core/feeder.py +260 -0
- zepben/ewb/model/cim/iec61970/base/core/geographical_region.py +82 -0
- zepben/ewb/model/cim/iec61970/base/core/identified_object.py +239 -0
- zepben/ewb/model/cim/iec61970/base/core/name.py +36 -0
- zepben/ewb/model/cim/iec61970/base/core/name_type.py +203 -0
- zepben/ewb/model/cim/iec61970/base/core/phase_code.py +202 -0
- zepben/ewb/model/cim/iec61970/base/core/power_system_resource.py +106 -0
- zepben/ewb/model/cim/iec61970/base/core/sub_geographical_region.py +93 -0
- zepben/ewb/model/cim/iec61970/base/core/substation.py +277 -0
- zepben/ewb/model/cim/iec61970/base/core/terminal.py +171 -0
- zepben/ewb/model/cim/iec61970/base/diagramlayout/__init__.py +4 -0
- zepben/ewb/model/cim/iec61970/base/diagramlayout/diagram.py +109 -0
- zepben/ewb/model/cim/iec61970/base/diagramlayout/diagram_object.py +160 -0
- zepben/ewb/model/cim/iec61970/base/diagramlayout/diagram_object_point.py +25 -0
- zepben/ewb/model/cim/iec61970/base/diagramlayout/diagram_style.py +28 -0
- zepben/ewb/model/cim/iec61970/base/diagramlayout/orientation_kind.py +29 -0
- zepben/ewb/model/cim/iec61970/base/domain/__init__.py +4 -0
- zepben/ewb/model/cim/iec61970/base/domain/unit_symbol.py +494 -0
- zepben/ewb/model/cim/iec61970/base/equivalents/__init__.py +4 -0
- zepben/ewb/model/cim/iec61970/base/equivalents/equivalent_branch.py +113 -0
- zepben/ewb/model/cim/iec61970/base/equivalents/equivalent_equipment.py +15 -0
- zepben/ewb/model/cim/iec61970/base/generation/__init__.py +4 -0
- zepben/ewb/model/cim/iec61970/base/generation/production/__init__.py +4 -0
- zepben/ewb/model/cim/iec61970/base/generation/production/battery_state_kind.py +39 -0
- zepben/ewb/model/cim/iec61970/base/generation/production/battery_unit.py +108 -0
- zepben/ewb/model/cim/iec61970/base/generation/production/photo_voltaic_unit.py +13 -0
- zepben/ewb/model/cim/iec61970/base/generation/production/power_electronics_unit.py +28 -0
- zepben/ewb/model/cim/iec61970/base/generation/production/power_electronics_wind_unit.py +13 -0
- zepben/ewb/model/cim/iec61970/base/meas/__init__.py +4 -0
- zepben/ewb/model/cim/iec61970/base/meas/accumulator.py +13 -0
- zepben/ewb/model/cim/iec61970/base/meas/accumulator_value.py +20 -0
- zepben/ewb/model/cim/iec61970/base/meas/analog.py +18 -0
- zepben/ewb/model/cim/iec61970/base/meas/analog_value.py +20 -0
- zepben/ewb/model/cim/iec61970/base/meas/control.py +26 -0
- zepben/ewb/model/cim/iec61970/base/meas/discrete.py +13 -0
- zepben/ewb/model/cim/iec61970/base/meas/discrete_value.py +20 -0
- zepben/ewb/model/cim/iec61970/base/meas/iopoint.py +16 -0
- zepben/ewb/model/cim/iec61970/base/meas/measurement.py +60 -0
- zepben/ewb/model/cim/iec61970/base/meas/measurement_value.py +21 -0
- zepben/ewb/model/cim/iec61970/base/protection/__init__.py +4 -0
- zepben/ewb/model/cim/iec61970/base/protection/current_relay.py +23 -0
- zepben/ewb/model/cim/iec61970/base/scada/__init__.py +4 -0
- zepben/ewb/model/cim/iec61970/base/scada/remote_control.py +22 -0
- zepben/ewb/model/cim/iec61970/base/scada/remote_point.py +16 -0
- zepben/ewb/model/cim/iec61970/base/scada/remote_source.py +22 -0
- zepben/ewb/model/cim/iec61970/base/wires/__init__.py +4 -0
- zepben/ewb/model/cim/iec61970/base/wires/ac_line_segment.py +214 -0
- zepben/ewb/model/cim/iec61970/base/wires/breaker.py +32 -0
- zepben/ewb/model/cim/iec61970/base/wires/busbar_section.py +19 -0
- zepben/ewb/model/cim/iec61970/base/wires/clamp.py +32 -0
- zepben/ewb/model/cim/iec61970/base/wires/conductor.py +49 -0
- zepben/ewb/model/cim/iec61970/base/wires/connector.py +16 -0
- zepben/ewb/model/cim/iec61970/base/wires/cut.py +36 -0
- zepben/ewb/model/cim/iec61970/base/wires/disconnector.py +17 -0
- zepben/ewb/model/cim/iec61970/base/wires/earth_fault_compensator.py +21 -0
- zepben/ewb/model/cim/iec61970/base/wires/energy_connection.py +15 -0
- zepben/ewb/model/cim/iec61970/base/wires/energy_consumer.py +107 -0
- zepben/ewb/model/cim/iec61970/base/wires/energy_consumer_phase.py +56 -0
- zepben/ewb/model/cim/iec61970/base/wires/energy_source.py +172 -0
- zepben/ewb/model/cim/iec61970/base/wires/energy_source_phase.py +45 -0
- zepben/ewb/model/cim/iec61970/base/wires/fuse.py +23 -0
- zepben/ewb/model/cim/iec61970/base/wires/ground.py +15 -0
- zepben/ewb/model/cim/iec61970/base/wires/ground_disconnector.py +15 -0
- zepben/ewb/model/cim/iec61970/base/wires/grounding_impedance.py +19 -0
- zepben/ewb/model/cim/iec61970/base/wires/jumper.py +16 -0
- zepben/ewb/model/cim/iec61970/base/wires/junction.py +15 -0
- zepben/ewb/model/cim/iec61970/base/wires/line.py +13 -0
- zepben/ewb/model/cim/iec61970/base/wires/linear_shunt_compensator.py +26 -0
- zepben/ewb/model/cim/iec61970/base/wires/load_break_switch.py +14 -0
- zepben/ewb/model/cim/iec61970/base/wires/per_length_impedance.py +13 -0
- zepben/ewb/model/cim/iec61970/base/wires/per_length_line_parameter.py +13 -0
- zepben/ewb/model/cim/iec61970/base/wires/per_length_phase_impedance.py +99 -0
- zepben/ewb/model/cim/iec61970/base/wires/per_length_sequence_impedance.py +43 -0
- zepben/ewb/model/cim/iec61970/base/wires/petersen_coil.py +22 -0
- zepben/ewb/model/cim/iec61970/base/wires/phase_impedance_data.py +37 -0
- zepben/ewb/model/cim/iec61970/base/wires/phase_shunt_connection_kind.py +40 -0
- zepben/ewb/model/cim/iec61970/base/wires/power_electronics_connection.py +524 -0
- zepben/ewb/model/cim/iec61970/base/wires/power_electronics_connection_phase.py +34 -0
- zepben/ewb/model/cim/iec61970/base/wires/power_transformer.py +217 -0
- zepben/ewb/model/cim/iec61970/base/wires/power_transformer_end.py +208 -0
- zepben/ewb/model/cim/iec61970/base/wires/protected_switch.py +96 -0
- zepben/ewb/model/cim/iec61970/base/wires/ratio_tap_changer.py +30 -0
- zepben/ewb/model/cim/iec61970/base/wires/reactive_capability_curve.py +16 -0
- zepben/ewb/model/cim/iec61970/base/wires/recloser.py +15 -0
- zepben/ewb/model/cim/iec61970/base/wires/regulating_cond_eq.py +45 -0
- zepben/ewb/model/cim/iec61970/base/wires/regulating_control.py +173 -0
- zepben/ewb/model/cim/iec61970/base/wires/regulating_control_mode_kind.py +48 -0
- zepben/ewb/model/cim/iec61970/base/wires/rotating_machine.py +36 -0
- zepben/ewb/model/cim/iec61970/base/wires/series_compensator.py +42 -0
- zepben/ewb/model/cim/iec61970/base/wires/shunt_compensator.py +59 -0
- zepben/ewb/model/cim/iec61970/base/wires/single_phase_kind.py +107 -0
- zepben/ewb/model/cim/iec61970/base/wires/static_var_compensator.py +40 -0
- zepben/ewb/model/cim/iec61970/base/wires/svc_control_mode.py +30 -0
- zepben/ewb/model/cim/iec61970/base/wires/switch.py +119 -0
- zepben/ewb/model/cim/iec61970/base/wires/synchronous_machine.py +168 -0
- zepben/ewb/model/cim/iec61970/base/wires/synchronous_machine_kind.py +46 -0
- zepben/ewb/model/cim/iec61970/base/wires/tap_changer.py +150 -0
- zepben/ewb/model/cim/iec61970/base/wires/tap_changer_control.py +49 -0
- zepben/ewb/model/cim/iec61970/base/wires/transformer_end.py +73 -0
- zepben/ewb/model/cim/iec61970/base/wires/transformer_star_impedance.py +48 -0
- zepben/ewb/model/cim/iec61970/base/wires/winding_connection.py +45 -0
- zepben/ewb/model/cim/iec61970/infiec61970/__init__.py +4 -0
- zepben/ewb/model/cim/iec61970/infiec61970/feeder/__init__.py +4 -0
- zepben/ewb/model/cim/iec61970/infiec61970/feeder/circuit.py +144 -0
- zepben/ewb/model/phases.py +168 -0
- zepben/ewb/model/resistance_reactance.py +40 -0
- zepben/ewb/services/__init__.py +4 -0
- zepben/ewb/services/common/__init__.py +16 -0
- zepben/ewb/services/common/base_service.py +383 -0
- zepben/ewb/services/common/base_service_comparator.py +394 -0
- zepben/ewb/services/common/difference.py +47 -0
- zepben/ewb/services/common/enum_mapper.py +55 -0
- zepben/ewb/services/common/meta/__init__.py +4 -0
- zepben/ewb/services/common/meta/data_source.py +16 -0
- zepben/ewb/services/common/meta/metadata_collection.py +28 -0
- zepben/ewb/services/common/meta/metadata_translations.py +47 -0
- zepben/ewb/services/common/meta/service_info.py +22 -0
- zepben/ewb/services/common/reference_resolvers.py +374 -0
- zepben/ewb/services/common/resolver.py +597 -0
- zepben/ewb/services/common/translator/__init__.py +4 -0
- zepben/ewb/services/common/translator/base_cim2proto.py +115 -0
- zepben/ewb/services/common/translator/base_proto2cim.py +146 -0
- zepben/ewb/services/common/translator/service_differences.py +81 -0
- zepben/ewb/services/common/translator/util.py +75 -0
- zepben/ewb/services/customer/__init__.py +4 -0
- zepben/ewb/services/customer/customer_service_comparator.py +52 -0
- zepben/ewb/services/customer/customers.py +23 -0
- zepben/ewb/services/customer/translator/__init__.py +21 -0
- zepben/ewb/services/customer/translator/customer_cim2proto.py +71 -0
- zepben/ewb/services/customer/translator/customer_enum_mappers.py +18 -0
- zepben/ewb/services/customer/translator/customer_proto2cim.py +87 -0
- zepben/ewb/services/diagram/__init__.py +4 -0
- zepben/ewb/services/diagram/diagram_service_comparator.py +39 -0
- zepben/ewb/services/diagram/diagrams.py +107 -0
- zepben/ewb/services/diagram/translator/__init__.py +11 -0
- zepben/ewb/services/diagram/translator/diagram_cim2proto.py +51 -0
- zepben/ewb/services/diagram/translator/diagram_enum_mappers.py +21 -0
- zepben/ewb/services/diagram/translator/diagram_proto2cim.py +61 -0
- zepben/ewb/services/measurement/__init__.py +4 -0
- zepben/ewb/services/measurement/measurements.py +35 -0
- zepben/ewb/services/measurement/translator/__init__.py +6 -0
- zepben/ewb/services/measurement/translator/measurement_cim2proto.py +42 -0
- zepben/ewb/services/measurement/translator/measurement_proto2cim.py +52 -0
- zepben/ewb/services/network/__init__.py +4 -0
- zepben/ewb/services/network/network_extensions.py +119 -0
- zepben/ewb/services/network/network_service.py +302 -0
- zepben/ewb/services/network/network_service_comparator.py +1322 -0
- zepben/ewb/services/network/network_state.py +36 -0
- zepben/ewb/services/network/tracing/__init__.py +4 -0
- zepben/ewb/services/network/tracing/busbranch_trace.py +36 -0
- zepben/ewb/services/network/tracing/connectivity/__init__.py +4 -0
- zepben/ewb/services/network/tracing/connectivity/connectivity_result.py +105 -0
- zepben/ewb/services/network/tracing/connectivity/nominal_phase_path.py +23 -0
- zepben/ewb/services/network/tracing/connectivity/phase_paths.py +70 -0
- zepben/ewb/services/network/tracing/connectivity/terminal_connectivity_connected.py +226 -0
- zepben/ewb/services/network/tracing/connectivity/terminal_connectivity_internal.py +64 -0
- zepben/ewb/services/network/tracing/connectivity/transformer_phase_paths.py +202 -0
- zepben/ewb/services/network/tracing/connectivity/xy_candidate_phase_paths.py +235 -0
- zepben/ewb/services/network/tracing/connectivity/xy_phase_step.py +24 -0
- zepben/ewb/services/network/tracing/feeder/__init__.py +4 -0
- zepben/ewb/services/network/tracing/feeder/assign_to_feeders.py +202 -0
- zepben/ewb/services/network/tracing/feeder/assign_to_lv_feeders.py +202 -0
- zepben/ewb/services/network/tracing/feeder/clear_direction.py +80 -0
- zepben/ewb/services/network/tracing/feeder/direction_status.py +133 -0
- zepben/ewb/services/network/tracing/feeder/feeder_direction.py +107 -0
- zepben/ewb/services/network/tracing/feeder/set_direction.py +143 -0
- zepben/ewb/services/network/tracing/find_swer_equipment.py +175 -0
- zepben/ewb/services/network/tracing/networktrace/__init__.py +4 -0
- zepben/ewb/services/network/tracing/networktrace/actions/__init__.py +4 -0
- zepben/ewb/services/network/tracing/networktrace/actions/equipment_tree_builder.py +104 -0
- zepben/ewb/services/network/tracing/networktrace/actions/tree_node.py +35 -0
- zepben/ewb/services/network/tracing/networktrace/compute_data.py +60 -0
- zepben/ewb/services/network/tracing/networktrace/conditions/__init__.py +4 -0
- zepben/ewb/services/network/tracing/networktrace/conditions/conditions.py +73 -0
- zepben/ewb/services/network/tracing/networktrace/conditions/direction_condition.py +63 -0
- zepben/ewb/services/network/tracing/networktrace/conditions/equipment_step_limit_condition.py +26 -0
- zepben/ewb/services/network/tracing/networktrace/conditions/equipment_type_step_limit_condition.py +44 -0
- zepben/ewb/services/network/tracing/networktrace/conditions/network_trace_queue_condition.py +67 -0
- zepben/ewb/services/network/tracing/networktrace/conditions/network_trace_stop_condition.py +65 -0
- zepben/ewb/services/network/tracing/networktrace/conditions/open_condition.py +39 -0
- zepben/ewb/services/network/tracing/networktrace/network_trace.py +433 -0
- zepben/ewb/services/network/tracing/networktrace/network_trace_action_type.py +42 -0
- zepben/ewb/services/network/tracing/networktrace/network_trace_queue_next.py +84 -0
- zepben/ewb/services/network/tracing/networktrace/network_trace_step.py +128 -0
- zepben/ewb/services/network/tracing/networktrace/network_trace_step_path_provider.py +351 -0
- zepben/ewb/services/network/tracing/networktrace/network_trace_tracker.py +39 -0
- zepben/ewb/services/network/tracing/networktrace/operators/__init__.py +14 -0
- zepben/ewb/services/network/tracing/networktrace/operators/equipment_container_state_operators.py +264 -0
- zepben/ewb/services/network/tracing/networktrace/operators/feeder_direction_state_operations.py +181 -0
- zepben/ewb/services/network/tracing/networktrace/operators/in_service_state_operators.py +76 -0
- zepben/ewb/services/network/tracing/networktrace/operators/network_state_operators.py +120 -0
- zepben/ewb/services/network/tracing/networktrace/operators/open_state_operators.py +104 -0
- zepben/ewb/services/network/tracing/networktrace/operators/phase_state_operators.py +56 -0
- zepben/ewb/services/network/tracing/networktrace/tracing.py +132 -0
- zepben/ewb/services/network/tracing/phases/__init__.py +4 -0
- zepben/ewb/services/network/tracing/phases/phase_inferrer.py +205 -0
- zepben/ewb/services/network/tracing/phases/phase_status.py +101 -0
- zepben/ewb/services/network/tracing/phases/remove_phases.py +143 -0
- zepben/ewb/services/network/tracing/phases/set_phases.py +490 -0
- zepben/ewb/services/network/tracing/traversal/__init__.py +4 -0
- zepben/ewb/services/network/tracing/traversal/context_value_computer.py +63 -0
- zepben/ewb/services/network/tracing/traversal/debug_logging.py +124 -0
- zepben/ewb/services/network/tracing/traversal/queue.py +112 -0
- zepben/ewb/services/network/tracing/traversal/queue_condition.py +75 -0
- zepben/ewb/services/network/tracing/traversal/step_action.py +83 -0
- zepben/ewb/services/network/tracing/traversal/step_context.py +59 -0
- zepben/ewb/services/network/tracing/traversal/stop_condition.py +57 -0
- zepben/ewb/services/network/tracing/traversal/traversal.py +634 -0
- zepben/ewb/services/network/tracing/traversal/traversal_condition.py +22 -0
- zepben/ewb/services/network/tracing/traversal/weighted_priority_queue.py +85 -0
- zepben/ewb/services/network/tracing/util.py +93 -0
- zepben/ewb/services/network/translator/__init__.py +392 -0
- zepben/ewb/services/network/translator/network_cim2proto.py +1867 -0
- zepben/ewb/services/network/translator/network_enum_mappers.py +78 -0
- zepben/ewb/services/network/translator/network_proto2cim.py +2201 -0
- zepben/ewb/services/services.py +48 -0
- zepben/ewb/streaming/__init__.py +4 -0
- zepben/ewb/streaming/data/__init__.py +4 -0
- zepben/ewb/streaming/data/current_state_event.py +314 -0
- zepben/ewb/streaming/data/current_state_event_batch.py +25 -0
- zepben/ewb/streaming/data/set_current_states_status.py +286 -0
- zepben/ewb/streaming/exceptions.py +14 -0
- zepben/ewb/streaming/get/__init__.py +4 -0
- zepben/ewb/streaming/get/consumer.py +209 -0
- zepben/ewb/streaming/get/customer_consumer.py +111 -0
- zepben/ewb/streaming/get/diagram_consumer.py +107 -0
- zepben/ewb/streaming/get/hierarchy/__init__.py +4 -0
- zepben/ewb/streaming/get/hierarchy/data.py +27 -0
- zepben/ewb/streaming/get/included_energized_containers.py +36 -0
- zepben/ewb/streaming/get/included_energizing_containers.py +36 -0
- zepben/ewb/streaming/get/network_consumer.py +870 -0
- zepben/ewb/streaming/get/query_network_state_client.py +64 -0
- zepben/ewb/streaming/get/query_network_state_service.py +94 -0
- zepben/ewb/streaming/grpc/__init__.py +4 -0
- zepben/ewb/streaming/grpc/auth_token_plugin.py +24 -0
- zepben/ewb/streaming/grpc/connect.py +209 -0
- zepben/ewb/streaming/grpc/grpc.py +107 -0
- zepben/ewb/streaming/grpc/grpc_channel_builder.py +190 -0
- zepben/ewb/streaming/mutations/__init__.py +4 -0
- zepben/ewb/streaming/mutations/update_network_state_client.py +80 -0
- zepben/ewb/streaming/mutations/update_network_state_service.py +61 -0
- zepben/ewb/testing/__init__.py +4 -0
- zepben/ewb/testing/test_network_builder.py +816 -0
- zepben/ewb/types.py +17 -0
- zepben/ewb/util.py +200 -0
- zepben_ewb-1.0.0.dist-info/METADATA +90 -0
- zepben_ewb-1.0.0.dist-info/RECORD +641 -0
- zepben_ewb-1.0.0.dist-info/WHEEL +5 -0
- zepben_ewb-1.0.0.dist-info/licenses/LICENSE +374 -0
- 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,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,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_)
|