From e6401744ce3816e3cd433b2e18933186c966aa9b Mon Sep 17 00:00:00 2001 From: Anthony Charlton Date: Thu, 26 Mar 2026 07:35:39 +1100 Subject: [PATCH 01/26] Added missing LvSubstation constructor kwargs Signed-off-by: Anthony Charlton --- .../iec61970/base/feeder/lv_substation.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/zepben/ewb/model/cim/extensions/iec61970/base/feeder/lv_substation.py b/src/zepben/ewb/model/cim/extensions/iec61970/base/feeder/lv_substation.py index 7055eea73..aca708ff4 100644 --- a/src/zepben/ewb/model/cim/extensions/iec61970/base/feeder/lv_substation.py +++ b/src/zepben/ewb/model/cim/extensions/iec61970/base/feeder/lv_substation.py @@ -28,6 +28,24 @@ class LvSubstation(EquipmentContainer): _current_energizing_feeders_by_id: dict[str | None, 'Feeder'] | None = None _normal_energized_lv_feeders_by_id: dict[str | None, LvFeeder] | None = None + def __init__( + self, + normal_energizing_feeders: list['Feeder'] | None = None, + current_energizing_feeders: list['Feeder'] | None = None, + normal_energized_lv_feeders: list[LvFeeder] | None = None, + **kwargs + ): + super(LvSubstation, self).__init__(**kwargs) + if normal_energizing_feeders: + for lv_feeder in normal_energizing_feeders: + self.add_normal_energizing_feeder(lv_feeder) + if current_energizing_feeders: + for lv_feeder in current_energizing_feeders: + self.add_current_energizing_feeder(lv_feeder) + if normal_energized_lv_feeders: + for lv_feeder in normal_energized_lv_feeders: + self.add_normal_energized_lv_feeder(lv_feeder) + @zbex @property def normal_energizing_feeders(self) -> Generator["Feeder", None, None]: From ae108543c4c8d322020ac3d7a53db3f71ec7fa81 Mon Sep 17 00:00:00 2001 From: Anthony Charlton Date: Thu, 26 Mar 2026 08:12:34 +1100 Subject: [PATCH 02/26] Fixed typing Signed-off-by: Anthony Charlton --- .../iec61970/base/wires/regulating_control.py | 4 +- src/zepben/ewb/services/common/difference.py | 8 +-- .../networktrace/conditions/conditions.py | 24 ++++---- .../common/service_comparator_validator.py | 55 +++++++++++-------- .../test_customer_service_comparator.py | 5 +- .../test_diagram_service_comparator.py | 8 ++- .../test_network_service_comparator.py | 5 +- 7 files changed, 63 insertions(+), 46 deletions(-) diff --git a/src/zepben/ewb/model/cim/iec61970/base/wires/regulating_control.py b/src/zepben/ewb/model/cim/iec61970/base/wires/regulating_control.py index 1fedb0064..26d5a58a6 100644 --- a/src/zepben/ewb/model/cim/iec61970/base/wires/regulating_control.py +++ b/src/zepben/ewb/model/cim/iec61970/base/wires/regulating_control.py @@ -46,13 +46,13 @@ class RegulatingControl(PowerSystemResource): discrete: Optional[bool] = None """The regulation is performed in a discrete mode. This applies to equipment with discrete controls, e.g. tap changers and shunt compensators.""" - mode: [RegulatingControlModeKind] = RegulatingControlModeKind.UNKNOWN + mode: RegulatingControlModeKind = RegulatingControlModeKind.UNKNOWN """ The regulating control mode presently available. This specification allows for determining the kind of regulation without need for obtaining the units from a schedule. """ - monitored_phase: [PhaseCode] = PhaseCode.NONE + monitored_phase: PhaseCode = PhaseCode.NONE """Phase voltage controlling this regulator, measured at regulator location.""" target_deadband: Optional[float] = None diff --git a/src/zepben/ewb/services/common/difference.py b/src/zepben/ewb/services/common/difference.py index 0e0e865a4..18fac44f6 100644 --- a/src/zepben/ewb/services/common/difference.py +++ b/src/zepben/ewb/services/common/difference.py @@ -3,7 +3,7 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at https://mozilla.org/MPL/2.0/. from dataclasses import dataclass, field -from typing import Optional, Any, List, Dict, TypeVar +from typing import Optional, Any, List, Dict, TypeVar, Generic from zepben.ewb import IdentifiedObject @@ -29,9 +29,9 @@ class CollectionDifference(Difference): @dataclass() -class ObjectDifference(Difference): - source: IdentifiedObject - target: IdentifiedObject +class ObjectDifference(Difference, Generic[T]): + source: T + target: T differences: Dict[str, Difference] = field(default_factory=dict) diff --git a/src/zepben/ewb/services/network/tracing/networktrace/conditions/conditions.py b/src/zepben/ewb/services/network/tracing/networktrace/conditions/conditions.py index 8280f94d0..a99254fc7 100644 --- a/src/zepben/ewb/services/network/tracing/networktrace/conditions/conditions.py +++ b/src/zepben/ewb/services/network/tracing/networktrace/conditions/conditions.py @@ -22,47 +22,47 @@ from zepben.ewb.services.network.tracing.traversal.stop_condition import StopCondition from zepben.ewb import ConductingEquipment, NetworkStateOperators - DSLLambda = Callable[[NetworkStateOperators], QueueCondition[NetworkTraceStep[T]]] + DSLLambda = Callable[[Type[NetworkStateOperators]], QueueCondition[NetworkTraceStep[T]]] def upstream() -> DSLLambda: """ - Creates a [NetworkTrace] condition that will cause tracing a feeder upstream (towards the head terminal). - This uses [FeederDirectionStateOperations.get_direction] receiver instance method within the condition. + Creates a `NetworkTrace` condition that will cause tracing a feeder upstream (towards the head terminal). + This uses `FeederDirectionStateOperations.get_direction` receiver instance method within the condition. - :return: [NetworkTraceQueueCondition] that results in upstream tracing. + :return: `NetworkTraceQueueCondition` that results in upstream tracing. """ return lambda state_operator: state_operator.with_direction(FeederDirection.UPSTREAM) def downstream() -> DSLLambda: """ - Creates a [NetworkTrace] condition that will cause tracing a feeder downstream (away from the head terminal). - This uses [FeederDirectionStateOperations.get_direction] receiver instance method within the condition. + Creates a `NetworkTrace` condition that will cause tracing a feeder downstream (away from the head terminal). + This uses `FeederDirectionStateOperations.get_direction` receiver instance method within the condition. - :return: [NetworkTraceQueueCondition] that results in downstream tracing. + :return: `NetworkTraceQueueCondition` that results in downstream tracing. """ return lambda state_operator: state_operator.with_direction(FeederDirection.DOWNSTREAM) def with_direction(direction: FeederDirection) -> DSLLambda: """ - Creates a [NetworkTrace] condition that will cause tracing only terminals with directions that match [direction]. - This uses [FeederDirectionStateOperations.get_direction] receiver instance method within the condition. + Creates a `NetworkTrace` condition that will cause tracing only terminals with directions that match `direction`. + This uses `FeederDirectionStateOperations.get_direction` receiver instance method within the condition. - :return: [NetworkTraceQueueCondition] that results in upstream tracing. + :return: `NetworkTraceQueueCondition` that results in upstream tracing. """ return lambda state_operator: DirectionCondition(direction, state_operator) def limit_equipment_steps(limit: int, equipment_type: Type[ConductingEquipment] = None) -> StopCondition[NetworkTraceStep[T]]: """ - Creates a [NetworkTrace] condition that stops tracing a path once a specified number of equipment steps have been reached. + Creates a `NetworkTrace` condition that stops tracing a path once a specified number of equipment steps have been reached. :param limit: The maximum number of equipment steps allowed before stopping. :param equipment_type: The class of the equipment type to track against the limit - :return: A [NetworkTraceStopCondition] that stops tracing the path once the step limit is reached. + :return: A `NetworkTraceStopCondition` that stops tracing the path once the step limit is reached. """ if equipment_type is not None: return EquipmentTypeStepLimitCondition(limit, equipment_type) diff --git a/test/services/common/service_comparator_validator.py b/test/services/common/service_comparator_validator.py index 90eb294b1..94166f7b3 100644 --- a/test/services/common/service_comparator_validator.py +++ b/test/services/common/service_comparator_validator.py @@ -3,7 +3,7 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at https://mozilla.org/MPL/2.0/. from types import MemberDescriptorType -from typing import Optional, Any, Callable, TypeVar, Union, Type, Set +from typing import Optional, Any, Callable, TypeVar, Union, Type, Set, Generic, TypeAlias from zepben.ewb import (IdentifiedObject, TIdentifiedObject, ObjectDifference, BaseService, CollectionDifference, Difference, ReferenceDifference, ValueDifference, IndexedDifference) @@ -15,14 +15,18 @@ R = TypeVar("R") Property = Union[MemberDescriptorType, property] +TAddr: TypeAlias = Callable[[TIdentifiedObject, R], TIdentifiedObject] | Callable[[R], TIdentifiedObject] # -# NOTE: The callables below that use `...` do so to work around bugs in the type checking of both the IDE and mypy. -# Ideally they should have `add: Callable[[TIdentifiedObject, R], Any]`. +# NOTE: Should be using the following with TCreator[TIdentifiedObject] in the functions, but Python +# 3.10 and PyCharm don't like passing TCreator[TIdentifiedObject] to bind correctly, so until +# we move on to a new version of Python, it looks like we are stuck repeating ourselves. +# +# TCreator: TypeAlias = Type[TIdentifiedObject] | Callable[[str], TIdentifiedObject] # -class ServiceComparatorValidator(object): +class ServiceComparatorValidator(Generic[TService, C]): create_service: Callable[[], TService] create_comparator: Callable[[NetworkServiceComparatorOptions], C] @@ -64,8 +68,8 @@ def validate_name_types( def validate_compare( self, - source: Any, - target: Any, + source: R, + target: R, expect_modification: Optional[ObjectDifference] = None, options: NetworkServiceComparatorOptions = NetworkServiceComparatorOptions(), options_stop_compare: bool = False, @@ -86,8 +90,8 @@ def validate_compare( def validate_property( self, - prop: Any, # should be Property but it types are not interpreted correctly so it gives a lot of errors. - creator: Type[TIdentifiedObject], + prop: Property | R, # Isn't actually R, but that is what the type checker thinks when passing class member references. + creator: Type[TIdentifiedObject] | Callable[[str], TIdentifiedObject], # Update to TCreator[TIdentifiedObject] when available. create_value: Callable[[TIdentifiedObject], R], create_other_value: Callable[[TIdentifiedObject], R], options: NetworkServiceComparatorOptions = NetworkServiceComparatorOptions(), @@ -112,8 +116,8 @@ def validate_property( def validate_val_property( self, - prop: Any, # should be Property but it types are not interpreted correctly so it gives a lot of errors. - creator: Any, # should be Optional[Type[TIdentifiedObject] | Callable[[str], TIdentifiedObject]] but that doesn't work, + prop: Property, + creator: Type[TIdentifiedObject] | Callable[[str], TIdentifiedObject], # Update to TCreator[TIdentifiedObject] when available. change_state: Callable[[TIdentifiedObject, R], None], other_change_state: Callable[[TIdentifiedObject, R], None], options: NetworkServiceComparatorOptions = NetworkServiceComparatorOptions(), @@ -138,8 +142,8 @@ def validate_val_property( def validate_collection( self, prop: Property, - add_to_collection: Callable[..., Any], - creator: Type[TIdentifiedObject], + add_to_collection: TAddr[TIdentifiedObject, R], + creator: Type[TIdentifiedObject] | Callable[[str], TIdentifiedObject], # Update to TCreator[TIdentifiedObject] when available. create_item: Callable[[TIdentifiedObject], R], create_other_item: Callable[[TIdentifiedObject], R], options: NetworkServiceComparatorOptions = NetworkServiceComparatorOptions(), @@ -179,16 +183,16 @@ def validate_collection( def validate_name_collection( self, - creator: [[str], TIdentifiedObject], + creator: Type[TIdentifiedObject] | Callable[[str], TIdentifiedObject], # Update to TCreator[TIdentifiedObject] when available. options: NetworkServiceComparatorOptions = NetworkServiceComparatorOptions(), options_stop_compare: bool = False, expected_differences: Set[str] = None ): - source_empty: IdentifiedObject = creator("mRID") - target_empty: IdentifiedObject = creator("mRID") - in_source: IdentifiedObject = creator("mRID") - in_target: IdentifiedObject = creator("mRID") - in_target_difference: IdentifiedObject = creator("mRID") + source_empty = creator("mRID") + target_empty = creator("mRID") + in_source = creator("mRID") + in_target = creator("mRID") + in_target_difference = creator("mRID") # noinspection PyArgumentList name_type = NameType("type") @@ -221,8 +225,8 @@ def validate_name_collection( def validate_indexed_collection( self, prop: Property, - add_to_collection: Callable[..., Any], - creator: [[str], TIdentifiedObject], + add_to_collection: TAddr, + creator: Type[TIdentifiedObject] | Callable[[str], TIdentifiedObject], # Update to TCreator[TIdentifiedObject] when available. create_item: Callable[[TIdentifiedObject], R], create_other_item: Callable[[TIdentifiedObject], R], options: NetworkServiceComparatorOptions = NetworkServiceComparatorOptions(), @@ -242,7 +246,7 @@ def validate_indexed_collection( self.validate_compare(source_empty, target_empty, options=options, options_stop_compare=options_stop_compare) self.validate_compare(in_source, in_target, options=options, options_stop_compare=options_stop_compare) - def get_item(obj) -> Optional[Any]: + def get_item(obj) -> Optional[R]: return next(_get_prop(obj, prop), None) diff = ObjectDifference(in_source, target_empty, { @@ -272,15 +276,15 @@ def get_item(obj) -> Optional[Any]: def validate_unordered_collection( self, prop: Property, - add_to_collection: Callable[..., Any], - creator: [[str], TIdentifiedObject], + add_to_collection: TAddr, + creator: Type[TIdentifiedObject] | Callable[[str], TIdentifiedObject], # Update to TCreator[TIdentifiedObject] when available. create_item_1: Callable[[K], R], create_item_2: Callable[[K], R], create_diff_item_1: Callable[[K], R], options: NetworkServiceComparatorOptions = NetworkServiceComparatorOptions(), options_stop_compare: bool = False, expected_differences: Set[str] = None - ): + ) -> TIdentifiedObject: source_empty = creator("mRID") target_empty = creator("mRID") self.validate_compare(source_empty, target_empty, options=options, options_stop_compare=options_stop_compare) @@ -346,6 +350,9 @@ def get_item_2(it): }) self._validate_expected(diff, options, options_stop_compare, expected_differences=expected_differences) + # This is being returned to bind the TIdentifiedObject correctly. + return source_empty + @staticmethod def _get_value_or_reference_difference(source: Optional[R], target: Optional[R]) -> Difference: if isinstance(source, IdentifiedObject) or isinstance(target, IdentifiedObject): diff --git a/test/services/customer/test_customer_service_comparator.py b/test/services/customer/test_customer_service_comparator.py index e9c011876..26f503c8b 100644 --- a/test/services/customer/test_customer_service_comparator.py +++ b/test/services/customer/test_customer_service_comparator.py @@ -12,7 +12,10 @@ class TestCustomerServiceComparator(TestBaseServiceComparator): - validator = ServiceComparatorValidator(lambda: CustomerService(), lambda _: CustomerServiceComparator()) + validator = ServiceComparatorValidator[CustomerService, CustomerServiceComparator]( + create_service=lambda: CustomerService(), + create_comparator=lambda _: CustomerServiceComparator() + ) def test_compare_customer(self): self._compare_organisation_role(Customer) diff --git a/test/services/diagram/test_diagram_service_comparator.py b/test/services/diagram/test_diagram_service_comparator.py index 29024e156..13747e779 100644 --- a/test/services/diagram/test_diagram_service_comparator.py +++ b/test/services/diagram/test_diagram_service_comparator.py @@ -13,7 +13,10 @@ class TestDiagramServiceComparator(TestBaseServiceComparator): - validator = ServiceComparatorValidator(lambda: DiagramService(), lambda _: DiagramServiceComparator()) + validator = ServiceComparatorValidator[DiagramService, DiagramServiceComparator]( + create_service=lambda: DiagramService(), + create_comparator=lambda _: DiagramServiceComparator() + ) def test_compare_diagram_attributes(self): self._compare_identified_object(Diagram) @@ -21,7 +24,8 @@ def test_compare_diagram_attributes(self): self.validator.validate_property(Diagram.diagram_style, Diagram, lambda _: DiagramStyle.SCHEMATIC, lambda _: DiagramStyle.GEOGRAPHIC) self.validator.validate_property(Diagram.orientation_kind, Diagram, lambda _: OrientationKind.POSITIVE, lambda _: OrientationKind.NEGATIVE) self.validator.validate_collection( - Diagram.diagram_objects, Diagram.add_diagram_object, + Diagram.diagram_objects, + Diagram.add_diagram_object, Diagram, lambda it: DiagramObject(mrid="1", diagram=it), lambda it: DiagramObject(mrid="2", diagram=it)) diff --git a/test/services/network/test_network_service_comparator.py b/test/services/network/test_network_service_comparator.py index b1d9c0794..d4a9efd81 100644 --- a/test/services/network/test_network_service_comparator.py +++ b/test/services/network/test_network_service_comparator.py @@ -71,7 +71,10 @@ class TestNetworkServiceComparator(TestBaseServiceComparator): - validator = ServiceComparatorValidator(lambda: NetworkService(), lambda options: NetworkServiceComparator(options)) + validator = ServiceComparatorValidator[NetworkService, NetworkServiceComparator]( + create_service=lambda: NetworkService(), + create_comparator=lambda options: NetworkServiceComparator(options) + ) ################################## # Extensions IEC61968 Asset Info # From 15401084fa0b2f92280698db84aa29b837947f2f Mon Sep 17 00:00:00 2001 From: Anthony Charlton Date: Thu, 26 Mar 2026 08:13:30 +1100 Subject: [PATCH 03/26] Stopped test crashes timing out trying to narrow Hypothesis examples Signed-off-by: Anthony Charlton --- test/conftest.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/test/conftest.py b/test/conftest.py index 8e142dbe9..b6d994fb8 100644 --- a/test/conftest.py +++ b/test/conftest.py @@ -8,7 +8,7 @@ import pytest from zepben.ewb.dataclassy import dataclass -from hypothesis import settings, Verbosity +from hypothesis import settings, Verbosity, Phase from pytest import fixture from zepben.ewb import Terminal, ConnectivityNode, IdentifiedObject @@ -18,9 +18,11 @@ # noinspection PyUnresolvedReferences from .network_fixtures import * -settings.register_profile("ci", max_examples=1000) -settings.register_profile("dev", max_examples=10) -settings.register_profile("debug", max_examples=10, verbosity=Verbosity.verbose) +no_shrink_phases = [p for p in Phase if p != Phase.shrink] + +settings.register_profile("ci", max_examples=1000, phases=no_shrink_phases) +settings.register_profile("dev", max_examples=10, phases=no_shrink_phases) +settings.register_profile("debug", max_examples=10, phases=[p for p in Phase], verbosity=Verbosity.debug) settings.load_profile(os.getenv(u'HYPOTHESIS_PROFILE', 'dev')) From e1b2bc75b2687387ccc4ba9c612845e7f266d843 Mon Sep 17 00:00:00 2001 From: Anthony Charlton Date: Thu, 26 Mar 2026 08:14:07 +1100 Subject: [PATCH 04/26] Added missing exports Signed-off-by: Anthony Charlton --- src/zepben/ewb/services/common/reference_resolvers.py | 4 +++- src/zepben/ewb/services/common/translator/base_proto2cim.py | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/zepben/ewb/services/common/reference_resolvers.py b/src/zepben/ewb/services/common/reference_resolvers.py index 285f35dc1..2d391a928 100644 --- a/src/zepben/ewb/services/common/reference_resolvers.py +++ b/src/zepben/ewb/services/common/reference_resolvers.py @@ -26,7 +26,9 @@ "psw_to_prf_resolver", "prf_to_sen_resolver", "sen_to_prf_resolver", "prf_to_prscheme_resolver", "prscheme_to_prf_resolver", "prscheme_to_prsystem_resolver", "battery_unit_to_battery_control_resolver", "ed_to_edf_resolver", "prsystem_to_prscheme_resolver", "fuse_to_prf_resolver", "sm_to_rcc_resolver", "feeder_to_celvf_resolver", "lvfeeder_to_cef_resolver", "acls_to_cut_resolver", "cut_to_acls_resolver", "acls_to_clamp_resolver", - "clamp_to_acls_resolver", "asset_to_psr_resolver", "psr_to_asset_resolver"] + "clamp_to_acls_resolver", "asset_to_psr_resolver", "psr_to_asset_resolver", "acls_to_acls_phase_resolver", "acls_phase_to_acls_resolver", + "acls_phase_to_wire_info_resolver", "shunt_compensator_to_terminal_resolver", "lvs_to_nelvf_resolver", "lvf_to_nelvs_resolver", "lvs_to_nef_resolver", + "lvs_to_cef_resolver", "feeder_to_nelvs_resolver", "feeder_to_celvs_resolver", ] from typing import Callable, Optional diff --git a/src/zepben/ewb/services/common/translator/base_proto2cim.py b/src/zepben/ewb/services/common/translator/base_proto2cim.py index 1befde536..cba81d8dd 100644 --- a/src/zepben/ewb/services/common/translator/base_proto2cim.py +++ b/src/zepben/ewb/services/common/translator/base_proto2cim.py @@ -6,7 +6,7 @@ from __future__ import annotations __all__ = ["identified_object_to_cim", "document_to_cim", "organisation_to_cim", "organisation_role_to_cim", - "BaseProtoToCim", "add_to_network_or_none", "bind_to_cim"] + "BaseProtoToCim", "add_to_network_or_none", "bind_to_cim", "get_nullable"] import functools import inspect From b2dcde955b8c2865269a057df2ce73c3b8497980 Mon Sep 17 00:00:00 2001 From: Anthony Charlton Date: Thu, 26 Mar 2026 08:17:32 +1100 Subject: [PATCH 05/26] Added sequence unpacking support for UnresolvedReference Signed-off-by: Anthony Charlton --- src/zepben/ewb/services/common/reference_resolvers.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/zepben/ewb/services/common/reference_resolvers.py b/src/zepben/ewb/services/common/reference_resolvers.py index 2d391a928..4b534f527 100644 --- a/src/zepben/ewb/services/common/reference_resolvers.py +++ b/src/zepben/ewb/services/common/reference_resolvers.py @@ -190,6 +190,9 @@ def __ne__(self, other: UnresolvedReference): def __hash__(self): return hash((type(self), self.from_ref.mrid, self.to_mrid, self.resolver)) + def __getitem__(self, item): + return (self.from_ref, self.to_mrid, self.resolver, self.reverse_resolver)[item] + def _resolve_ce_term(ce, t): t.conducting_equipment = ce From 22ad23b690d3e30355dc945fcf78e7c608e6f729 Mon Sep 17 00:00:00 2001 From: Anthony Charlton Date: Thu, 26 Mar 2026 08:18:06 +1100 Subject: [PATCH 06/26] Fixed error in LvSubstation to LvFeeder reference resolution Signed-off-by: Anthony Charlton --- src/zepben/ewb/services/common/resolver.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/zepben/ewb/services/common/resolver.py b/src/zepben/ewb/services/common/resolver.py index 1b685c464..1dc55b436 100644 --- a/src/zepben/ewb/services/common/resolver.py +++ b/src/zepben/ewb/services/common/resolver.py @@ -317,7 +317,7 @@ def normal_energized_lv_feeders(other: Feeder | LvSubstation) -> BoundReferenceR return BoundReferenceResolver(other, feeder_to_nelvf_resolver, lvfeeder_to_nef_resolver) elif isinstance(other, LvSubstation): # noinspection PyArgumentList - return BoundReferenceResolver(other, lvs_to_nef_resolver, lvf_to_nelvs_resolver) + return BoundReferenceResolver(other, lvs_to_nelvf_resolver, lvf_to_nelvs_resolver) else: raise TypeError(f'unsupported type {type(other)}') From c695f66d8fe1cc1c62c1c9dd7d266261826b04ad Mon Sep 17 00:00:00 2001 From: Anthony Charlton Date: Thu, 26 Mar 2026 08:22:47 +1100 Subject: [PATCH 07/26] Updated `SetDirection` to correctly use the `@singledispatchmethod` registration `run` instead of the old `run_terminal` Signed-off-by: Anthony Charlton --- changelog.md | 13 ++++++++----- .../network/tracing/feeder/set_direction.py | 13 +++++++------ src/zepben/ewb/testing/test_network_builder.py | 4 ++-- .../network/tracing/feeder/test_clear_direction.py | 2 +- .../network/tracing/feeder/test_set_direction.py | 10 +++++----- .../actions/test_equipment_tree_builder.py | 8 ++++---- 6 files changed, 27 insertions(+), 23 deletions(-) diff --git a/changelog.md b/changelog.md index 779a70e1e..38dedb67d 100644 --- a/changelog.md +++ b/changelog.md @@ -1,13 +1,14 @@ # Zepben Python SDK ## [1.3.0] - UNRELEASED ### Breaking Changes -* None. +* Updated `SetDirection` to correctly use the `@singledispatchmethod` registration `run` instead of the old `run_terminal`. Simply replace your `run_terminal` + call with `run`. ### New Features * None. ### Enhancements -* None. +* `SetDirection.run` now supports `ConductingEquipment`. ### Fixes * None. @@ -23,7 +24,8 @@ * `MeasurementValue.time_stamp` * `RelayInfo.curve_setting` * `RelayInfo.reclose_fast` -* Removed `TracedPhases`. `Terminal.normalPhases` and `Terminal.currentPhases` should be used instead of `Terminal.tracedPhases` going forward. (missed in 0.48.0) +* Removed `TracedPhases`. `Terminal.normalPhases` and `Terminal.currentPhases` should be used instead of `Terminal.tracedPhases` going forward. (missed in + 0.48.0) ### New Features * Added the following new CIM classes: @@ -58,7 +60,8 @@ * Added `AcLineSegment.wire_info_for_phase(phase: SinglePhaseKind)` to retrieve the `WireInfo` associated with a given phase of a conductor. ### Enhancements -* * `BaseService.contains` has been been expanded to support objects in addition to mRIDs. +* + * `BaseService.contains` has been been expanded to support objects in addition to mRIDs. * `Agreement` now supports `validity_interval`, the date and time interval the agreement is valid (from going into effect to termination). * `StreetDetail` now supports extension `building_number`, the number of the building. * `TownDetail` now supports `country`, the name of the country. @@ -66,7 +69,7 @@ ### Fixes * Reordered the feeder equipment and direction assignment on database read to prevent parallel feeders from tracing back into the zone substation. -* `NetworkDatabaseTables`, `CustomerDatabaseTables`, `DiagramDatabaseTables` and `BaseEntryWriter` can now be imported from `zepben.ewb` and are officially +* `NetworkDatabaseTables`, `CustomerDatabaseTables`, `DiagramDatabaseTables` and `BaseEntryWriter` can now be imported from `zepben.ewb` and are officially regarded as public. ### Notes diff --git a/src/zepben/ewb/services/network/tracing/feeder/set_direction.py b/src/zepben/ewb/services/network/tracing/feeder/set_direction.py index 265b002fb..a239b88ae 100644 --- a/src/zepben/ewb/services/network/tracing/feeder/set_direction.py +++ b/src/zepben/ewb/services/network/tracing/feeder/set_direction.py @@ -134,16 +134,17 @@ async def run(self, network: NetworkService, network_state_operators: Type[Netwo for terminal in (f.normal_head_terminal for f in network.objects(Feeder) if f.normal_head_terminal): if (head_terminal := terminal.conducting_equipment) is not None: if not network_state_operators.is_open(head_terminal, None): - await self.run_terminal(terminal, network_state_operators) + await self.run(terminal, network_state_operators) - @run.register - async def run_terminal(self, terminal: Terminal, network_state_operators: Type[NetworkStateOperators] = NetworkStateOperators.NORMAL): + @run.register(Terminal) + @run.register(ConductingEquipment) + async def _(self, start: Terminal | ConductingEquipment, network_state_operators: Type[NetworkStateOperators] = NetworkStateOperators.NORMAL): """ Apply [FeederDirection.DOWNSTREAM] from the [terminal]. - :param terminal: The terminal to start applying feeder direction from. - :param network_state_operators: The `NetworkStateOperators` to be used when setting feeder direction + :param start: The ``Terminal`` or ``ConductingEquipment`` to start applying feeder direction from. + :param network_state_operators: The ``NetworkStateOperators`` to be used when setting feeder direction """ return await (self._create_traversal(network_state_operators) - .run(terminal, FeederDirection.DOWNSTREAM, can_stop_on_start_item=False)) + .run(start, FeederDirection.DOWNSTREAM, can_stop_on_start_item=False)) diff --git a/src/zepben/ewb/testing/test_network_builder.py b/src/zepben/ewb/testing/test_network_builder.py index 790dcb663..03dd7b9a2 100644 --- a/src/zepben/ewb/testing/test_network_builder.py +++ b/src/zepben/ewb/testing/test_network_builder.py @@ -677,8 +677,8 @@ async def build(self, apply_directions_from_sources: bool = True, debug_logger: if apply_directions_from_sources: for es in self.network.objects(EnergySource): for terminal in es.terminals: - await Tracing.set_direction(debug_logger=debug_logger).run_terminal(terminal, network_state_operators=NetworkStateOperators.NORMAL) - await Tracing.set_direction(debug_logger=debug_logger).run_terminal(terminal, network_state_operators=NetworkStateOperators.CURRENT) + await Tracing.set_direction(debug_logger=debug_logger).run(terminal, network_state_operators=NetworkStateOperators.NORMAL) + await Tracing.set_direction(debug_logger=debug_logger).run(terminal, network_state_operators=NetworkStateOperators.CURRENT) await Tracing.assign_equipment_to_feeders(debug_logger=debug_logger).run(self.network, network_state_operators=NetworkStateOperators.NORMAL) await Tracing.assign_equipment_to_lv_feeders(debug_logger=debug_logger).run(self.network, network_state_operators=NetworkStateOperators.NORMAL) diff --git a/test/services/network/tracing/feeder/test_clear_direction.py b/test/services/network/tracing/feeder/test_clear_direction.py index 6b735ea36..2af1a8178 100644 --- a/test/services/network/tracing/feeder/test_clear_direction.py +++ b/test/services/network/tracing/feeder/test_clear_direction.py @@ -252,7 +252,7 @@ async def test_clears_loops(self): for term in head_terminals: if not self.state_operators.is_open(term.conducting_equipment): - await Tracing.set_direction().run_terminal(term, self.state_operators) + await Tracing.set_direction().run(term, self.state_operators) _check_expected_direction(_get_t(n, 'b0', 1), NONE) _check_expected_direction(_get_t(n, 'b0', 2), DOWNSTREAM) diff --git a/test/services/network/tracing/feeder/test_set_direction.py b/test/services/network/tracing/feeder/test_set_direction.py index a028db94a..c05375063 100644 --- a/test/services/network/tracing/feeder/test_set_direction.py +++ b/test/services/network/tracing/feeder/test_set_direction.py @@ -61,7 +61,7 @@ async def test_stops_at_open_points(self): .to_acls() \ .network - await SetDirection().run_terminal(self._get_t(n, "c0", 2)) + await SetDirection().run(self._get_t(n, "c0", 2)) await log_directions(n["c0"]) self._check_expected_direction(self._get_t(n, "c0", 1), NONE) @@ -267,7 +267,7 @@ async def test_dual_path_loop_top(self): .network sd = SetDirection() - await sd.run_terminal(self._get_t(n, "j0", 1)) + await sd.run(self._get_t(n, "j0", 1)) #print(sd.nodes['j0-t1']) await log_directions(n["j0"]) @@ -340,7 +340,7 @@ async def test_dual_path_loop_bottom(self): .connect("c10", "j2", 1, 2) ).network - await SetDirection().run_terminal(self._get_t(n, "j0", 1)) + await SetDirection().run(self._get_t(n, "j0", 1)) await log_directions(n["j0"]) # To avoid reprocessing all BOTH loops in larger networks we do not process anything with a direction already set. This means this test will apply @@ -385,7 +385,7 @@ async def test_ignores_phase_pathing(self): .to_acls(nominal_phases=PhaseCode.A) \ .network - await SetDirection().run_terminal(self._get_t(n, "j0", 1)) + await SetDirection().run(self._get_t(n, "j0", 1)) await log_directions(n["j0"]) self._check_expected_direction(self._get_t(n, "j0", 1), DOWNSTREAM) @@ -406,7 +406,7 @@ async def test_works_without_phase(self): .to_acls(nominal_phases=PhaseCode.NONE) \ .network - await SetDirection().run_terminal(self._get_t(n, "j0", 1)) + await SetDirection().run(self._get_t(n, "j0", 1)) await log_directions(n["j0"]) self._check_expected_direction(self._get_t(n, "j0", 1), DOWNSTREAM) diff --git a/test/services/network/tracing/networktrace/actions/test_equipment_tree_builder.py b/test/services/network/tracing/networktrace/actions/test_equipment_tree_builder.py index f104a42c5..73df410ac 100644 --- a/test/services/network/tracing/networktrace/actions/test_equipment_tree_builder.py +++ b/test/services/network/tracing/networktrace/actions/test_equipment_tree_builder.py @@ -29,8 +29,8 @@ async def test_equipment_tree_builder_leaves(): await Tracing.set_phases().run(n) feeder_head = n.get("j0", ConductingEquipment) - await Tracing.set_direction().run_terminal(feeder_head, network_state_operators=normal) - await Tracing.set_direction().run_terminal(feeder_head, network_state_operators=current) + await Tracing.set_direction().run(feeder_head, network_state_operators=normal) + await Tracing.set_direction().run(feeder_head, network_state_operators=current) await log_directions(n.get('j0', ConductingEquipment)) start = n.get("j1", ConductingEquipment) @@ -59,8 +59,8 @@ async def test_downstream_tree(): await Tracing.set_phases().run(n) feeder_head = n.get("j0", ConductingEquipment) - await Tracing.set_direction().run_terminal(feeder_head, network_state_operators=normal) - await Tracing.set_direction().run_terminal(feeder_head, network_state_operators=current) + await Tracing.set_direction().run(feeder_head, network_state_operators=normal) + await Tracing.set_direction().run(feeder_head, network_state_operators=current) await log_directions(n.get('j0', ConductingEquipment)) visited_ce = [] From 8fcdc754b43e5dacd96903624bef47a74cdb7527 Mon Sep 17 00:00:00 2001 From: Anthony Charlton Date: Thu, 26 Mar 2026 08:34:47 +1100 Subject: [PATCH 08/26] `EquipmentTreeBuilder.roots` is now a `dict` Signed-off-by: Anthony Charlton --- changelog.md | 2 ++ .../networktrace/actions/equipment_tree_builder.py | 14 +++++--------- .../actions/test_equipment_tree_builder.py | 2 +- 3 files changed, 8 insertions(+), 10 deletions(-) diff --git a/changelog.md b/changelog.md index 38dedb67d..648c1121f 100644 --- a/changelog.md +++ b/changelog.md @@ -3,6 +3,8 @@ ### Breaking Changes * Updated `SetDirection` to correctly use the `@singledispatchmethod` registration `run` instead of the old `run_terminal`. Simply replace your `run_terminal` call with `run`. +* `EquipmentTreeBuilder.roots` is now a `dict` keyed by the `start_item` rather than a `Generator`. This allows better lookup of root items when you are looking + for an explicit items tree. ### New Features * None. diff --git a/src/zepben/ewb/services/network/tracing/networktrace/actions/equipment_tree_builder.py b/src/zepben/ewb/services/network/tracing/networktrace/actions/equipment_tree_builder.py index 217e7ff09..607feba20 100644 --- a/src/zepben/ewb/services/network/tracing/networktrace/actions/equipment_tree_builder.py +++ b/src/zepben/ewb/services/network/tracing/networktrace/actions/equipment_tree_builder.py @@ -37,15 +37,11 @@ class EquipmentTreeBuilder(StepActionWithContextValue): def __init__(self, calculate_leaves: bool = False): super().__init__(key=str(uuid.uuid4())) - self._roots: dict[ConductingEquipment, EquipmentTreeNode] = {} + self.roots: dict[ConductingEquipment, EquipmentTreeNode] = {} self._leaves: set[EquipmentTreeNode] = set() self._calculate_leaves = calculate_leaves - @property - def roots(self) -> Generator[TreeNode[ConductingEquipment], None, None]: - return (r for r in self._roots.values()) - def recurse_nodes(self) -> Generator[TreeNode[ConductingEquipment], None, None]: """ Returns a generator that will yield every node in the tree structure. @@ -55,7 +51,7 @@ def recurse(node: TreeNode[ConductingEquipment]): for child in node.children: yield from recurse(child) - for root in self._roots.values(): + for root in self.roots.values(): yield from recurse(root) @property @@ -69,10 +65,10 @@ def leaves(self) -> set[EquipmentTreeNode]: return set(self._leaves) def compute_initial_value(self, item: NetworkTraceStep[Any]) -> EquipmentTreeNode: - node = self._roots.get(item.path.to_equipment) + node = self.roots.get(item.path.to_equipment) if node is None: node = TreeNode(item.path.to_equipment, None) - self._roots[item.path.to_equipment] = node + self.roots[item.path.to_equipment] = node return node def compute_next_value( @@ -101,4 +97,4 @@ def _process_leaf(self, current_node: TreeNode[ConductingEquipment]): self._leaves.discard(current_node.parent) # this nodes parent now has a child, it's not a leaf anymore def clear(self): - self._roots.clear() + self.roots.clear() diff --git a/test/services/network/tracing/networktrace/actions/test_equipment_tree_builder.py b/test/services/network/tracing/networktrace/actions/test_equipment_tree_builder.py index 73df410ac..f23756e96 100644 --- a/test/services/network/tracing/networktrace/actions/test_equipment_tree_builder.py +++ b/test/services/network/tracing/networktrace/actions/test_equipment_tree_builder.py @@ -89,7 +89,7 @@ async def test_downstream_tree(): pprint.pprint(visit_counts) - root = tree_builder._roots[start] + root = tree_builder.roots[start] assert root is not None _verify_tree_asset(root, n["j1"], None, [n["ac1"], n["ac3"]]) From f9d908374a451e1bb4902e1327b0dfc1b266c44c Mon Sep 17 00:00:00 2001 From: Anthony Charlton Date: Thu, 26 Mar 2026 08:38:10 +1100 Subject: [PATCH 09/26] Renamed `cim_creators.py` -> `fill_fields.py` Signed-off-by: Anthony Charlton --- CONTRIBUTING.md | 2 +- test/cim/cim_creators.py | 1966 -------------- .../iec61968/common/test_contact_details.py | 2 +- .../base/wires/test_battery_control.py | 2 +- test/cim/fill_fields.py | 2412 +++++++++++++++++ .../iec61968/assetinfo/test_no_load_test.py | 2 +- .../assetinfo/test_open_circuit_test.py | 2 +- .../assetinfo/test_short_circuit_test.py | 2 +- .../assetinfo/test_shunt_compensator_info.py | 2 +- .../iec61968/assetinfo/test_switch_info.py | 2 +- .../assetinfo/test_transformer_end_info.py | 2 +- .../assetinfo/test_transformer_test.py | 2 +- test/cim/iec61968/assetinfo/test_wire_info.py | 2 +- test/cim/iec61968/assets/test_pole.py | 2 +- test/cim/iec61968/assets/test_streelight.py | 2 +- test/cim/iec61968/common/test_document.py | 2 +- .../common/test_electronic_address.py | 2 +- test/cim/iec61968/common/test_location.py | 2 +- .../iec61968/common/test_street_address.py | 2 +- .../cim/iec61968/common/test_street_detail.py | 2 +- .../iec61968/common/test_telephone_number.py | 2 +- test/cim/iec61968/common/test_town_detail.py | 2 +- test/cim/iec61968/customers/test_customer.py | 2 +- .../customers/test_pricing_structure.py | 2 +- .../test_current_transformer_info.py | 2 +- .../test_potential_transformer_info.py | 2 +- .../infassetinfo/test_relay_info.py | 2 +- test/cim/iec61968/metering/test_end_device.py | 2 +- .../cim/iec61968/metering/test_usage_point.py | 2 +- .../test_current_transformer.py | 2 +- .../iec61970/base/core/test_base_voltage.py | 2 +- .../cim/iec61970/base/core/test_curve_data.py | 2 +- test/cim/iec61970/base/core/test_equipment.py | 4 +- .../base/core/test_identified_object.py | 16 +- test/cim/iec61970/base/core/test_name.py | 2 +- test/cim/iec61970/base/core/test_name_type.py | 2 +- .../base/core/test_power_system_resource.py | 2 +- test/cim/iec61970/base/core/test_terminal.py | 2 +- .../base/diagramlayout/test_diagram_object.py | 2 +- .../test_diagram_object_point.py | 2 +- .../equivalents/test_equivalent_branch.py | 2 +- .../base/meas/test_accumulator_value.py | 2 +- .../iec61970/base/meas/test_analog_value.py | 2 +- test/cim/iec61970/base/meas/test_control.py | 2 +- .../iec61970/base/meas/test_discrete_value.py | 2 +- .../iec61970/base/meas/test_measurement.py | 2 +- .../base/protection/test_current_relay.py | 2 +- .../base/protection/test_distance_relay.py | 2 +- .../test_protection_relay_function.py | 6 +- .../production/test_battery_unit.py | 2 +- .../production/test_power_electronics_unit.py | 2 +- .../base/wires/test_ac_line_segment_phase.py | 3 +- test/cim/iec61970/base/wires/test_breaker.py | 2 +- .../cim/iec61970/base/wires/test_conductor.py | 2 +- .../wires/test_earth_fault_compensator.py | 2 +- .../base/wires/test_energy_consumer.py | 2 +- .../iec61970/base/wires/test_energy_source.py | 2 +- .../base/wires/test_grounding_impedance.py | 2 +- .../wires/test_linear_shunt_compensator.py | 27 +- .../test_per_length_sequence_impedance.py | 2 +- .../iec61970/base/wires/test_petersen_coil.py | 2 +- .../base/wires/test_phase_impedance_data.py | 2 +- .../test_power_electronics_connection.py | 2 +- .../base/wires/test_power_transformer.py | 2 +- .../base/wires/test_power_transformer_end.py | 2 +- .../base/wires/test_protected_switch.py | 2 +- .../base/wires/test_ratio_tap_changer.py | 2 +- .../base/wires/test_regulating_control.py | 2 +- .../base/wires/test_rotating_machine.py | 2 +- .../base/wires/test_series_compensator.py | 2 +- .../base/wires/test_shunt_compensator.py | 18 +- .../base/wires/test_static_var_compensator.py | 2 +- test/cim/iec61970/base/wires/test_switch.py | 2 +- .../base/wires/test_synchronous_machine.py | 2 +- .../iec61970/base/wires/test_tap_changer.py | 2 +- .../base/wires/test_tap_changer_control.py | 10 +- .../base/wires/test_transformer_end.py | 2 +- .../wires/test_transformer_star_impedance.py | 2 +- .../customer/test_customer_database_schema.py | 2 +- .../diagram/test_diagram_database_schema.py | 2 +- .../network/test_network_database_schema.py | 2 +- .../translator/test_customer_translator.py | 2 +- .../translator/test_diagram_translator.py | 2 +- .../translator/test_network_translator.py | 3 +- 84 files changed, 2524 insertions(+), 2089 deletions(-) delete mode 100644 test/cim/cim_creators.py create mode 100644 test/cim/fill_fields.py diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index be2a46a1e..62c6717d7 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -108,7 +108,7 @@ to prevent the test from timing out while you step through the code: * Add new classes to corresponding service translator test. [```test/services/.../translator```](test/services) * Add the required creators to: - [```pb_creators.py```](test/streaming/get/pb_creators.py) - - [```cim_creators.py```](test/cim/cim_creators.py) + - [```fill_fields.py```](test/cim/fill_fields.py) - If a relationship involving a branch class has been introduced. Add an entry in SAMPLE SET to ensure the correct leaf class is created for testing. * Add test for each new comparator to [test/services/...](test/services) package. * [network](test/services/network/test_network_service_comparator.py) diff --git a/test/cim/cim_creators.py b/test/cim/cim_creators.py deleted file mode 100644 index 736fdec02..000000000 --- a/test/cim/cim_creators.py +++ /dev/null @@ -1,1966 +0,0 @@ -# Copyright 2024 Zeppelin Bend Pty Ltd -# This Source Code Form is subject to the terms of the Mozilla Public -# License, v. 2.0. If a copy of the MPL was not distributed with this -# file, You can obtain one at https://mozilla.org/MPL/2.0/. - -__all__ = ['create_cable_info', 'create_no_load_test', 'create_open_circuit_test', 'create_overhead_wire_info', 'create_power_transformer_info', - 'create_short_circuit_test', 'create_series_compensator', 'create_shunt_compensator_info', 'create_switch_info', 'create_transformer_end_info', - 'create_transformer_tank_info', 'create_transformer_test', 'create_wire_info', 'sampled_wire_material_kind', 'create_asset', 'create_asset_info', - 'create_asset_container', 'create_asset_organisation_role', 'create_asset_owner', 'create_pole', 'create_streetlight', - 'sampled_streetlight_lamp_kind', 'create_structure', 'create_agreement', 'create_document', 'create_location', 'create_organisation', - 'create_organisation_role', 'create_position_point', 'create_street_address', 'create_street_detail', 'create_town_detail', 'create_customer', - 'create_customer_agreement', 'sampled_customer_kind', 'create_pricing_structure', 'create_tariffs', 'create_relay_info', - 'create_current_transformer_info', 'create_potential_transformer_info', 'create_ratio', 'create_end_device', 'create_meter', 'create_usage_point', - 'create_operational_restriction', 'create_auxiliary_equipment', 'create_current_transformer', 'create_fault_indicator', - 'create_potential_transformer', 'create_sensor', 'create_ac_dc_terminal', 'create_base_voltage', 'create_conducting_equipment', - 'create_connectivity_node', 'create_connectivity_node_container', 'create_equipment', 'create_equipment_container', 'create_feeder', - 'create_geographical_region', 'create_identified_object', 'create_name', 'create_name_type', 'sampled_phase_code', 'create_power_system_resource', - 'create_site', 'create_sub_geographical_region', 'create_substation', 'create_terminal', 'create_equivalent_branch', 'create_equivalent_equipment', - 'create_diagram', 'create_diagram_object', 'create_diagram_object_point', 'create_accumulator', 'create_accumulator_value', 'create_analog', - 'create_analog_value', 'create_control', 'create_discrete', 'create_discrete_value', 'create_io_point', 'create_measurement', 'sampled_unit_symbol', - 'create_current_relay', 'create_distance_relay', 'create_protection_relay_function', 'create_protection_relay_scheme', 'create_voltage_relay', - 'create_protection_relay_system', 'create_remote_control', 'create_remote_point', 'create_remote_source', 'sampled_battery_state_kind', - 'create_battery_unit', 'create_photo_voltaic_unit', 'create_power_electronics_unit', 'create_power_electronics_wind_unit', 'create_ac_line_segment', - 'create_breaker', 'create_busbar_section', 'create_conductor', 'create_connector', 'create_disconnector', 'create_energy_consumer', - 'create_energy_connection', 'create_energy_consumer_phase', 'create_energy_source', 'create_energy_source_phase', 'create_fuse', 'create_ground', - 'create_ground_disconnector', 'create_jumper', 'create_junction', 'create_line', 'create_linear_shunt_compensator', 'create_load_break_switch', - 'create_per_length_impedance', 'create_per_length_line_parameter', 'create_per_length_sequence_impedance', 'sampled_phase_shunt_connection_kind', - 'create_power_electronics_connection', 'create_power_electronics_connection_phase', 'create_power_transformer', 'create_power_transformer_end', - 'create_protected_switch', 'create_ratio_tap_changer', 'create_recloser', 'create_regulating_cond_eq', 'create_shunt_compensator', - 'sampled_single_phase_kind', 'create_switch', 'create_tap_changer', 'create_transformer_end', 'create_transformer_star_impedance', - 'sampled_vector_group', 'sampled_winding_connection', 'create_circuit', 'create_loop', 'create_lv_feeder', "create_ev_charging_unit", - 'traced_phases', 'sampled_wire_info', 'sampled_conducting_equipment', 'sampled_equipment', 'sampled_equipment_container', 'sampled_hvlv_feeder', - 'sampled_measurement', 'sampled_protected_switches', 'create_tap_changer_control', 'MIN_32_BIT_INTEGER', 'MAX_32_BIT_INTEGER', - 'MAX_32_BIT_UNSIGNED_INTEGER', 'MAX_64_BIT_INTEGER', 'MIN_64_BIT_INTEGER', 'TEXT_MAX_SIZE', 'FLOAT_MIN', 'FLOAT_MAX', 'MAX_END_NUMBER', - 'MAX_SEQUENCE_NUMBER', 'MIN_SEQUENCE_NUMBER', 'ALPHANUM', 'boolean_or_none', 'create_grounding_impedance', 'create_petersen_coil', - 'create_reactive_capability_curve', 'create_synchronous_machine', 'create_earth_fault_compensator', 'create_curve', 'create_curve_data', - 'create_rotating_machine', 'sampled_curves', 'create_pan_demand_response_function', 'create_battery_control', 'create_asset_function', - 'create_end_device_function', 'create_static_var_compensator', 'create_per_length_phase_impedance', 'create_phase_impedance_data', 'create_clamp', - 'create_cut', 'sampled_transformer_construction_kind', 'sampled_transformer_function_kind', 'create_controlled_appliance', - 'sampled_end_device_function_kind', 'sampled_potential_transformer_kind', 'sampled_diagram_style', 'sampled_orientation_kind', - 'create_measurement_value', 'sampled_regulating_control_mode_kind', 'sampled_svc_control_mode', 'sampled_synchronous_machine_kind', - 'sampled_power_direction_kind', 'sampled_protection_kind', 'create_relay_setting', 'sampled_battery_control_mode', 'sampled_transformer_cooling_type' - ] - -from datetime import datetime -from random import choice - -from streaming.get.pb_creators import lists, floats -from util import mrid_strategy -# @formatter:off - -# This must be above hypothesis.strategies to avoid conflicting import with zepben.ewb.util.none -from zepben.ewb import * - -from hypothesis.strategies import builds, text, integers, sampled_from, booleans, uuids, datetimes, one_of, none -from zepben.ewb.model.cim.extensions.iec61970.base.feeder.lv_substation import LvSubstation -from zepben.ewb.model.cim.iec61968.assetinfo.wire_insulation_kind import WireInsulationKind -from zepben.ewb.model.cim.iec61970.base.wires.ac_line_segment_phase import AcLineSegmentPhase -from zepben.ewb.services.common.resolver import normal_energizing_lv_substations - -# @formatter:on - -# WARNING!! # THIS IS A WORK IN PROGRESS AND MANY FUNCTIONS ARE LIKELY BROKEN - -MIN_32_BIT_INTEGER = -2147483647 # _UNKNOWN_INT = -2147483648 -MAX_32_BIT_INTEGER = 2147483647 -MAX_32_BIT_UNSIGNED_INTEGER = 4294967294 # _UNKNOWN_UINT = 4294967295 -MAX_64_BIT_INTEGER = 9223372036854775807 -MIN_64_BIT_INTEGER = -9223372036854775807 # _UNKNOWN_LONG = -9223372036854775808 -TEXT_MAX_SIZE = 6 -FLOAT_MIN = -100.0 -FLOAT_MAX = 1000.0 -MAX_END_NUMBER = 3 -MAX_SEQUENCE_NUMBER = 40 -MIN_SEQUENCE_NUMBER = 1 -ALPHANUM = "abcdefghijbklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_" - - -################################## -# Extensions IEC61968 Asset Info # -################################## - -def create_relay_info(include_runtime: bool = True): - return builds( - RelayInfo, - **create_asset_info(include_runtime), - curve_setting=text(alphabet=ALPHANUM, min_size=1, max_size=TEXT_MAX_SIZE), - reclose_delays=lists(floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX)), - reclose_fast=boolean_or_none() - ) - - -############################## -# Extensions IEC61968 Common # -############################## - -def create_contact_details(): - return builds( - ContactDetails, - id=text(alphabet=ALPHANUM, max_size=TEXT_MAX_SIZE, min_size=1), - contact_address=create_street_address(), - contact_type=one_of(none(), text(alphabet=ALPHANUM, max_size=TEXT_MAX_SIZE)), - first_name=one_of(none(), text(alphabet=ALPHANUM, max_size=TEXT_MAX_SIZE)), - last_name=one_of(none(), text(alphabet=ALPHANUM, max_size=TEXT_MAX_SIZE)), - preferred_contact_method=sampled_from(ContactMethodType), - is_primary=one_of(none(), booleans()), - business_name=one_of(none(), text(alphabet=ALPHANUM, max_size=TEXT_MAX_SIZE)), - phone_numbers=one_of(none(), lists(create_telephone_number())), - electronic_addresses=one_of(none(), lists(create_electronic_address())), - ) - -################################ -# Extensions IEC61968 Metering # -################################ - -def create_pan_demand_response_function(include_runtime: bool = True): - return builds( - PanDemandResponseFunction, - **create_end_device_function(include_runtime), - kind=sampled_from(EndDeviceFunctionKind), - appliances=integers(min_value=0, max_value=4095) - ) - - -################################# -# Extensions IEC61970 Base Core # -################################# - -def create_hv_customer(include_runtime: bool = True): - return builds(Site, **create_equipment_container(include_runtime)) - -def create_site(include_runtime: bool = True): - return builds(Site, **create_equipment_container(include_runtime)) - - -################################### -# Extensions IEC61970 Base Feeder # -################################### - -def create_loop(include_runtime: bool = True): - return builds( - Loop, - **create_identified_object(include_runtime), - circuits=lists(builds(Circuit, **create_identified_object(include_runtime)), max_size=2), - substations=lists(builds(Substation, **create_identified_object(include_runtime)), max_size=2), - energizing_substations=lists(builds(Substation, **create_identified_object(include_runtime)), max_size=2) - ) - - -def create_lv_feeder(include_runtime: bool = True): - runtime = { - "normal_energizing_feeders": lists(builds(Feeder, **create_identified_object(include_runtime)), max_size=2), - "current_equipment": lists(sampled_equipment(include_runtime), max_size=2), - "current_energizing_feeders": lists(builds(Feeder, **create_identified_object(include_runtime)), max_size=2), - "normal_energizing_lv_substation": builds(LvSubstation, **create_identified_object(include_runtime)), - } if include_runtime else {} - - return builds( - LvFeeder, - # Only include equipment if we are processing runtime as we don't write equipment to the database for LvFeeder. - **create_equipment_container(include_runtime, add_equipment=include_runtime), - normal_head_terminal=builds(Terminal, **create_identified_object(include_runtime)), - **runtime - ) - - -def create_lv_substation(include_runtime: bool = True): - runtime = { - "normal_energizing_feeders": lists(builds(Feeder, **create_identified_object(include_runtime)), max_size=2), - "current_energizing_feeders": lists(builds(Feeder, **create_identified_object(include_runtime)), max_size=2), - "current_equipment": lists(sampled_equipment(include_runtime), max_size=2), - "normal_energized_lv_feeder": builds(LvFeeder, **create_identified_object(include_runtime)), - } - - return builds( - LvSubstation, - **create_equipment_container(include_runtime, add_equipment=include_runtime), - ) - - -################################################## -# Extensions IEC61970 Base Generation Production # -################################################## - -def create_ev_charging_unit(include_runtime: bool = True): - return builds(EvChargingUnit, **create_power_electronics_unit(include_runtime)) - - -####################################### -# Extensions IEC61970 Base Protection # -####################################### - -def create_directional_current_relay(include_runtime: bool = True): - return builds( - DirectionalCurrentRelay, - **create_protection_relay_function(include_runtime), - directional_characteristic_angle=one_of(none(), floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX)), - polarizing_quantity_type=sampled_from(PolarizingQuantityType), - relay_element_phase=sampled_from(PhaseCode), - minimum_pickup_current=one_of(none(), floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX)), - current_limit_1=one_of(none(), floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX)), - inverse_time_flag=boolean_or_none(), - time_delay_1=one_of(none(), floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX)), - ) - - -def create_distance_relay(include_runtime: bool = True): - return builds( - DistanceRelay, - **create_protection_relay_function(include_runtime), - backward_blind=one_of(none(), floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX)), - backward_reach=one_of(none(), floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX)), - backward_reactance=one_of(none(), floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX)), - forward_blind=one_of(none(), floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX)), - forward_reach=one_of(none(), floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX)), - forward_reactance=one_of(none(), floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX)), - operation_phase_angle1=one_of(none(), floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX)), - operation_phase_angle2=one_of(none(), floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX)), - operation_phase_angle3=one_of(none(), floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX)) - ) - - -def sampled_power_direction_kind(): - return sampled_from(PowerDirectionKind) - - -def sampled_protection_kind(): - return sampled_from(ProtectionKind) - - -def create_protection_relay_function(include_runtime: bool = True): - return { - **create_power_system_resource(include_runtime), - "model": text(alphabet=ALPHANUM, min_size=1, max_size=TEXT_MAX_SIZE), - "reclosing": boolean_or_none(), - "relay_delay_time": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - "protection_kind": sampled_protection_kind(), - "directable": boolean_or_none(), - "power_direction": sampled_power_direction_kind(), - "sensors": lists(builds(CurrentTransformer, mrid=mrid_strategy), max_size=2), - "protected_switches": lists(builds(Breaker, mrid=mrid_strategy), max_size=2), - "schemes": lists(builds(ProtectionRelayScheme, mrid=mrid_strategy), max_size=2), - "time_limits": lists(floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), min_size=4, max_size=4), - "thresholds": lists(create_relay_setting(), min_size=4, max_size=4), - "relay_info": builds(RelayInfo, mrid=mrid_strategy) - } - - -def create_protection_relay_scheme(include_runtime: bool = True): - return builds( - ProtectionRelayScheme, - **create_identified_object(include_runtime), - system=builds(ProtectionRelaySystem, mrid=mrid_strategy), - functions=lists(builds(CurrentRelay, mrid=mrid_strategy)) - ) - - -def create_protection_relay_system(include_runtime: bool = True): - return builds( - ProtectionRelaySystem, - **create_equipment(include_runtime), - protection_kind=sampled_protection_kind(), - schemes=lists(builds(ProtectionRelayScheme, mrid=mrid_strategy)) - ) - - -def create_relay_setting(): - return builds( - RelaySetting, - unit_symbol=sampled_unit_symbol(), - value=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - name=text(alphabet=ALPHANUM, max_size=TEXT_MAX_SIZE) - ) - - -def create_voltage_relay(include_runtime: bool = True): - return builds( - VoltageRelay, - **create_protection_relay_function(include_runtime), - ) - - -################################## -# Extensions IEC61970 Base Wires # -################################## - -def create_battery_control(include_runtime: bool = True): - return builds( - BatteryControl, - **create_regulating_control(include_runtime), - charging_rate=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - discharging_rate=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - reserve_percent=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - control_mode=sampled_battery_control_mode() - ) - - -def sampled_battery_control_mode(): - return sampled_from(BatteryControlMode) - - -def sampled_transformer_cooling_type(): - return sampled_from(TransformerCoolingType) - - -def create_power_transformer_end_with_ratings(ratings: List[TransformerEndRatedS], **kwargs): - # This is needed as we purposely made it so you can't build a transformer end with multiple ratings through constructor - pte = PowerTransformerEnd(**kwargs) - if ratings: - for rating in ratings: - pte.add_transformer_end_rated_s(rating) - return pte - - -def sampled_vector_group(): - return sampled_from(VectorGroup) - - -####################### -# IEC61968 Asset Info # -####################### - - -def create_cable_info(include_runtime: bool = True): - return builds(CableInfo, **create_wire_info(include_runtime)) - - -def create_no_load_test(include_runtime: bool = True): - return builds( - NoLoadTest, - **create_transformer_test(include_runtime), - energised_end_voltage=integers(min_value=MIN_32_BIT_INTEGER, max_value=MAX_32_BIT_INTEGER), - exciting_current=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - exciting_current_zero=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - loss=integers(min_value=MIN_32_BIT_INTEGER, max_value=MAX_32_BIT_INTEGER), - loss_zero=integers(min_value=MIN_32_BIT_INTEGER, max_value=MAX_32_BIT_INTEGER) - ) - - -def create_open_circuit_test(include_runtime: bool = True): - return builds( - OpenCircuitTest, - **create_transformer_test(include_runtime), - energised_end_step=integers(min_value=MIN_32_BIT_INTEGER, max_value=MAX_32_BIT_INTEGER), - energised_end_voltage=integers(min_value=MIN_32_BIT_INTEGER, max_value=MAX_32_BIT_INTEGER), - open_end_step=integers(min_value=MIN_32_BIT_INTEGER, max_value=MAX_32_BIT_INTEGER), - open_end_voltage=integers(min_value=MIN_32_BIT_INTEGER, max_value=MAX_32_BIT_INTEGER), - phase_shift=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX) - ) - - -def create_overhead_wire_info(include_runtime: bool = True): - return builds(OverheadWireInfo, **create_wire_info(include_runtime)) - - -def create_power_transformer_info(include_runtime: bool = True): - return builds( - PowerTransformerInfo, - **create_asset_info(include_runtime), - transformer_tank_infos=lists(builds(TransformerTankInfo, **create_identified_object(include_runtime)), max_size=2) - ) - - -def create_short_circuit_test(include_runtime: bool = True): - return builds( - ShortCircuitTest, - **create_transformer_test(include_runtime), - current=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - energised_end_step=integers(min_value=MIN_32_BIT_INTEGER, max_value=MAX_32_BIT_INTEGER), - grounded_end_step=integers(min_value=MIN_32_BIT_INTEGER, max_value=MAX_32_BIT_INTEGER), - leakage_impedance=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - leakage_impedance_zero=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - loss=integers(min_value=MIN_32_BIT_INTEGER, max_value=MAX_32_BIT_INTEGER), - loss_zero=integers(min_value=MIN_32_BIT_INTEGER, max_value=MAX_32_BIT_INTEGER), - power=integers(min_value=MIN_32_BIT_INTEGER, max_value=MAX_32_BIT_INTEGER), - voltage=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - voltage_ohmic_part=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX) - ) - - -def create_shunt_compensator_info(include_runtime: bool = True): - return builds( - ShuntCompensatorInfo, - **create_asset_info(include_runtime), - max_power_loss=integers(min_value=MIN_32_BIT_INTEGER, max_value=MAX_32_BIT_INTEGER), - rated_current=integers(min_value=MIN_32_BIT_INTEGER, max_value=MAX_32_BIT_INTEGER), - rated_reactive_power=integers(min_value=MIN_32_BIT_INTEGER, max_value=MAX_32_BIT_INTEGER), - rated_voltage=integers(min_value=MIN_32_BIT_INTEGER, max_value=MAX_32_BIT_INTEGER), - ) - - -def create_switch_info(include_runtime: bool = True): - return builds( - SwitchInfo, - **create_asset_info(include_runtime), - rated_interrupting_time=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX) - ) - - -def create_transformer_end_info(include_runtime: bool = True): - return builds( - TransformerEndInfo, - **create_asset_info(include_runtime), - connection_kind=sampled_winding_connection(), - emergency_s=integers(min_value=MIN_32_BIT_INTEGER, max_value=MAX_32_BIT_INTEGER), - end_number=integers(min_value=MIN_32_BIT_INTEGER, max_value=MAX_32_BIT_INTEGER), - insulation_u=integers(min_value=MIN_32_BIT_INTEGER, max_value=MAX_32_BIT_INTEGER), - phase_angle_clock=integers(min_value=MIN_32_BIT_INTEGER, max_value=MAX_32_BIT_INTEGER), - r=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - rated_s=integers(min_value=MIN_32_BIT_INTEGER, max_value=MAX_32_BIT_INTEGER), - rated_u=integers(min_value=MIN_32_BIT_INTEGER, max_value=MAX_32_BIT_INTEGER), - short_term_s=integers(min_value=MIN_32_BIT_INTEGER, max_value=MAX_32_BIT_INTEGER), - transformer_tank_info=builds(TransformerTankInfo, **create_identified_object(include_runtime)), - transformer_star_impedance=builds(TransformerStarImpedance, **create_identified_object(include_runtime)), - energised_end_no_load_tests=builds(NoLoadTest, **create_identified_object(include_runtime)), - energised_end_short_circuit_tests=builds(ShortCircuitTest, **create_identified_object(include_runtime)), - grounded_end_short_circuit_tests=builds(ShortCircuitTest, **create_identified_object(include_runtime)), - open_end_open_circuit_tests=builds(OpenCircuitTest, **create_identified_object(include_runtime)), - energised_end_open_circuit_tests=builds(OpenCircuitTest, **create_identified_object(include_runtime)), - ) - - -def create_transformer_tank_info(include_runtime: bool = True): - return builds( - TransformerTankInfo, - **create_asset_info(include_runtime), - power_transformer_info=builds(PowerTransformerInfo, **create_identified_object(include_runtime)), - transformer_end_infos=lists(builds(TransformerEndInfo, **create_identified_object(include_runtime)), max_size=2) - ) - - -def create_transformer_test(include_runtime: bool): - return { - **create_identified_object(include_runtime), - "base_power": integers(min_value=MIN_32_BIT_INTEGER, max_value=MAX_32_BIT_INTEGER), - "temperature": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX) - } - - -def create_wire_info(include_runtime: bool): - return { - **create_asset_info(include_runtime), - "rated_current": integers(min_value=MIN_32_BIT_INTEGER, max_value=MAX_32_BIT_INTEGER), - "material": sampled_wire_material_kind(), - "size_description": one_of(none(), text(alphabet=ALPHANUM)), - "strand_count": one_of(none(), text(alphabet=ALPHANUM)), - "core_strand_count": one_of(none(), text(alphabet=ALPHANUM)), - "insulated": booleans(), - "insulation_material": sampled_wire_insulation_kind(), - "insulation_thickness": one_of(none(), floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX)), - } - - -def sampled_wire_material_kind(): - return sampled_from(WireMaterialKind) - - -def sampled_wire_insulation_kind(): - return sampled_from(WireInsulationKind) - - -################### -# IEC61968 Assets # -################### - - -def create_asset(include_runtime: bool): - return { - **create_identified_object(include_runtime), - "location": builds(Location, **create_identified_object(include_runtime)), - "organisation_roles": lists(builds(AssetOwner, **create_identified_object(include_runtime)), max_size=2), - "power_system_resources": lists(builds(Junction, **create_identified_object(include_runtime)), max_size=2) - } - - -def create_asset_container(include_runtime: bool): - return {**create_asset(include_runtime)} - - -def create_asset_function(include_runtime: bool): - return {**create_identified_object(include_runtime)} - - -def create_asset_info(include_runtime: bool): - return {**create_identified_object(include_runtime)} - - -def create_asset_organisation_role(include_runtime: bool): - return {**create_organisation_role(include_runtime)} - - -def create_asset_owner(include_runtime: bool = True): - return builds(AssetOwner, **create_asset_organisation_role(include_runtime)) - - -def create_streetlight(include_runtime: bool = True): - return builds( - Streetlight, - **create_asset(include_runtime), - pole=builds(Pole, **create_identified_object(include_runtime)), - light_rating=integers(min_value=0, max_value=MAX_32_BIT_INTEGER), # Capping unsigned int to 32-bit int range to avoid issues with Python 3.7 testing. - lamp_kind=sampled_streetlight_lamp_kind() - ) - - -def create_structure(include_runtime: bool): - return {**create_asset_container(include_runtime)} - - -################### -# IEC61968 Common # -################### - - -def create_agreement(include_runtime: bool): - return {**create_document(include_runtime)} - - -def create_document(include_runtime: bool): - return { - **create_identified_object(include_runtime), - "title": text(alphabet=ALPHANUM, max_size=TEXT_MAX_SIZE), - "created_date_time": datetimes(min_value=datetime(1970, 1, 2)), - "author_name": text(alphabet=ALPHANUM, max_size=TEXT_MAX_SIZE), - "type": text(alphabet=ALPHANUM, max_size=TEXT_MAX_SIZE), - "status": text(alphabet=ALPHANUM, max_size=TEXT_MAX_SIZE), - "comment": text(alphabet=ALPHANUM, max_size=TEXT_MAX_SIZE) - } - - -def create_electronic_address(): - return builds( - ElectronicAddress, - email1=one_of(none(), text(alphabet=ALPHANUM, max_size=TEXT_MAX_SIZE)), - is_primary=one_of(none(), booleans()), - description=one_of(none(), text(alphabet=ALPHANUM, max_size=TEXT_MAX_SIZE)), - ) - - -def create_location(include_runtime: bool = True): - return builds( - Location, - **create_identified_object(include_runtime), - main_address=create_street_address(), - position_points=lists(create_position_point(), max_size=4) - ) - - -def create_organisation(include_runtime: bool = True): - return builds(Organisation, **create_identified_object(include_runtime)) - - -def create_organisation_role(include_runtime: bool): - return { - **create_identified_object(include_runtime), - "organisation": builds(Organisation, **create_identified_object(include_runtime)) - } - - -def create_position_point(): - return builds( - PositionPoint, - x_position=floats(min_value=-180.0, max_value=180.0), - y_position=floats(min_value=-90.0, max_value=90.0) - ) - - -def create_street_address(): - return builds( - StreetAddress, - postal_code=one_of(none(), text(alphabet=ALPHANUM, max_size=TEXT_MAX_SIZE)), - town_detail=create_town_detail(), - po_box=one_of(none(), text(alphabet=ALPHANUM, max_size=TEXT_MAX_SIZE)), - street_detail=create_street_detail() - ) - - -def create_street_detail(): - return builds( - StreetDetail, - building_name=text(alphabet=ALPHANUM, max_size=TEXT_MAX_SIZE), - floor_identification=one_of(none(), text(alphabet=ALPHANUM, max_size=TEXT_MAX_SIZE)), - name=one_of(none(), text(alphabet=ALPHANUM, max_size=TEXT_MAX_SIZE)), - number=one_of(none(), text(alphabet=ALPHANUM, max_size=TEXT_MAX_SIZE)), - suite_number=one_of(none(), text(alphabet=ALPHANUM, max_size=TEXT_MAX_SIZE)), - type=one_of(none(), text(alphabet=ALPHANUM, max_size=TEXT_MAX_SIZE)), - display_address=one_of(none(), text(alphabet=ALPHANUM, max_size=TEXT_MAX_SIZE)), - building_number=one_of(none(), text(alphabet=ALPHANUM, max_size=TEXT_MAX_SIZE)) - ) - - -def create_telephone_number(): - return builds( - TelephoneNumber, - area_code=text(alphabet=ALPHANUM, max_size=3), - city_code=one_of(none(), text(alphabet=ALPHANUM, max_size=2)), - dial_out=one_of(none(), text(alphabet=ALPHANUM, max_size=3)), - extension=one_of(none(), text(alphabet=ALPHANUM, max_size=4)), - international_prefix=one_of(none(), text(alphabet=ALPHANUM, max_size=TEXT_MAX_SIZE)), - local_number=one_of(none(), text(alphabet=ALPHANUM, max_size=8)), - is_primary=one_of(none(), booleans()), - description=one_of(none(), text(alphabet=ALPHANUM, max_size=TEXT_MAX_SIZE)), - ) - - -def create_town_detail(): - return builds( - TownDetail, - name=text(alphabet=ALPHANUM, max_size=TEXT_MAX_SIZE), - state_or_province=one_of(none(), text(alphabet=ALPHANUM, max_size=TEXT_MAX_SIZE)), - country=one_of(none(), text(alphabet=ALPHANUM, max_size=TEXT_MAX_SIZE)), - ) - - -###################### -# IEC61968 Customers # -###################### - - -def create_customer(include_runtime: bool = True): - return builds( - Customer, - **create_organisation_role(include_runtime), - kind=sampled_customer_kind(), - # We can't use blank strings as it breaks some of the tests due to protobuf conversions dropping the blanks for None. - special_need=text(alphabet=ALPHANUM, min_size=1, max_size=TEXT_MAX_SIZE), - customer_agreements=lists(builds(CustomerAgreement, **create_identified_object(include_runtime)), max_size=2) - ) - - -def create_customer_agreement(include_runtime: bool = True): - return builds( - CustomerAgreement, - **create_agreement(include_runtime), - customer=builds(Customer, **create_identified_object(include_runtime)), - pricing_structures=lists(builds(PricingStructure, **create_identified_object(include_runtime)), max_size=2) - ) - - -def sampled_customer_kind(): - return sampled_from(CustomerKind) - - -def create_pricing_structure(include_runtime: bool = True): - return builds( - PricingStructure, - **create_document(include_runtime), - tariffs=lists(builds(Tariff, **create_identified_object(include_runtime)), max_size=2) - ) - - -def create_tariffs(include_runtime: bool = True): - return builds(Tariff, **create_document(include_runtime)) - - -##################################### -# IEC61968 InfIEC61968 InfAssetInfo # -##################################### - -def create_current_transformer_info(include_runtime: bool = True): - return builds( - CurrentTransformerInfo, - **create_asset_info(include_runtime), - accuracy_class=text(alphabet=ALPHANUM, min_size=1, max_size=TEXT_MAX_SIZE), - accuracy_limit=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - core_count=integers(min_value=MIN_32_BIT_INTEGER, max_value=MAX_32_BIT_INTEGER), - ct_class=text(alphabet=ALPHANUM, min_size=1, max_size=TEXT_MAX_SIZE), - knee_point_voltage=integers(min_value=MIN_32_BIT_INTEGER, max_value=MAX_32_BIT_INTEGER), - max_ratio=create_ratio(), - nominal_ratio=create_ratio(), - primary_ratio=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - rated_current=integers(min_value=MIN_32_BIT_INTEGER, max_value=MAX_32_BIT_INTEGER), - secondary_fls_rating=integers(min_value=MIN_32_BIT_INTEGER, max_value=MAX_32_BIT_INTEGER), - secondary_ratio=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - usage=text(alphabet=ALPHANUM, min_size=1, max_size=TEXT_MAX_SIZE) - ) - - -def create_potential_transformer_info(include_runtime: bool = True): - return builds( - PotentialTransformerInfo, - **create_asset_info(include_runtime), - accuracy_class=text(alphabet=ALPHANUM, min_size=1, max_size=TEXT_MAX_SIZE), - nominal_ratio=create_ratio(), - primary_ratio=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - pt_class=text(alphabet=ALPHANUM, min_size=1, max_size=TEXT_MAX_SIZE), - rated_voltage=integers(min_value=MIN_32_BIT_INTEGER, max_value=MAX_32_BIT_INTEGER), - secondary_ratio=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX) - ) - - -def sampled_transformer_construction_kind(): - return sampled_from(TransformerConstructionKind) - - -def sampled_transformer_function_kind(): - return sampled_from(TransformerFunctionKind) - - -################################## -# IEC61968 InfIEC61968 InfAssets # -################################## - - -def create_pole(include_runtime: bool = True): - return builds( - Pole, - **create_structure(include_runtime), - streetlights=lists(builds(Streetlight, **create_identified_object(include_runtime)), max_size=2), - classification=text(alphabet=ALPHANUM, max_size=TEXT_MAX_SIZE) - ) - - -def sampled_streetlight_lamp_kind(): - return sampled_from(StreetlightLampKind) - - -################################## -# IEC61968 InfIEC61968 InfCommon # -################################## - - -def create_ratio(): - return builds( - Ratio, - numerator=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - denominator=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX) - ) - - -##################### -# IEC61968 Metering # -##################### - - -def create_controlled_appliance(): - return builds( - ControlledAppliance, - appliances=sampled_from(Appliance) - ) - - -def create_end_device(include_runtime: bool): - return { - **create_asset_container(include_runtime), - "usage_points": lists(builds(UsagePoint, **create_identified_object(include_runtime)), max_size=2), - "customer_mrid": text(alphabet=ALPHANUM, min_size=1, max_size=TEXT_MAX_SIZE), - "service_location": builds(Location, **create_identified_object(include_runtime)), - "functions": lists(sampled_end_device_function(include_runtime), max_size=2) - } - - -def create_end_device_function(include_runtime: bool): - return { - **create_asset_function(include_runtime), - "enabled": booleans() - } - - -def sampled_end_device_function_kind(): - return sampled_from(EndDeviceFunctionKind) - - -def create_meter(include_runtime: bool = True): - return builds(Meter, **create_end_device(include_runtime)) - - -def create_usage_point(include_runtime: bool = True): - return builds( - UsagePoint, - **create_identified_object(include_runtime), - usage_point_location=builds(Location, **create_identified_object(include_runtime)), - is_virtual=booleans(), - connection_category=text(alphabet=ALPHANUM, min_size=2, max_size=TEXT_MAX_SIZE), - rated_power=integers(min_value=MIN_32_BIT_INTEGER, max_value=MAX_32_BIT_INTEGER), - approved_inverter_capacity=integers(min_value=MIN_32_BIT_INTEGER, max_value=MAX_32_BIT_INTEGER), - equipment=lists(builds(EnergyConsumer, **create_identified_object(include_runtime)), max_size=2), - end_devices=lists(builds(Meter, **create_identified_object(include_runtime)), max_size=2), - contacts=lists(create_contact_details(), max_size=2) - ) - - -####################### -# IEC61968 Operations # -####################### - - -def create_operational_restriction(include_runtime: bool = True): - return builds( - OperationalRestriction, - **create_document(include_runtime), - equipment=lists(builds(PowerTransformer, **create_identified_object(include_runtime)), max_size=2) - ) - - -##################################### -# IEC61970 Base Auxiliary Equipment # -##################################### - -def create_auxiliary_equipment(include_runtime: bool): - return { - **create_equipment(include_runtime), - "terminal": builds(Terminal, **create_identified_object(include_runtime)) - } - - -def create_current_transformer(include_runtime: bool = True): - return builds( - CurrentTransformer, - **create_sensor(include_runtime), - asset_info=builds(CurrentTransformerInfo, **create_identified_object(include_runtime)), - core_burden=integers(min_value=MIN_32_BIT_INTEGER, max_value=MAX_32_BIT_INTEGER) - ) - - -def create_fault_indicator(include_runtime: bool = True): - return builds(FaultIndicator, **create_auxiliary_equipment(include_runtime)) - - -def create_potential_transformer(include_runtime: bool = True): - return builds( - PotentialTransformer, - **create_sensor(include_runtime), - asset_info=builds(PotentialTransformerInfo, **create_identified_object(include_runtime)), - type=sampled_from(PotentialTransformerKind) - ) - - -def sampled_potential_transformer_kind(): - return sampled_from(PotentialTransformerKind) - - -def create_sensor(include_runtime: bool = True): - return { - **create_auxiliary_equipment(include_runtime), - "relay_functions": lists(builds(CurrentRelay, mrid=mrid_strategy), max_size=10) - } - - -###################### -# IEC61970 Base Core # -###################### - - -def create_ac_dc_terminal(include_runtime: bool): - return {**create_identified_object(include_runtime)} - - -def create_base_voltage(include_runtime: bool = True): - return builds( - BaseVoltage, - **create_identified_object(include_runtime), - nominal_voltage=integers(min_value=MIN_32_BIT_INTEGER, max_value=MAX_32_BIT_INTEGER) - ) - - -def create_conducting_equipment(include_runtime: bool): - return { - **create_equipment(include_runtime), - "base_voltage": builds(BaseVoltage, **create_identified_object(include_runtime)), - "terminals": lists(builds(Terminal, **create_identified_object(include_runtime)), max_size=3) - } - - -def create_connectivity_node(include_runtime: bool = True): - return builds( - ConnectivityNode, - **create_identified_object(include_runtime), - terminals=lists(builds(Terminal, **create_identified_object(include_runtime)), max_size=10) - ) - - -def create_connectivity_node_container(include_runtime: bool): - return {**create_power_system_resource(include_runtime)} - - -def create_curve(include_runtime: bool): - return { - **create_identified_object(include_runtime), - "data": lists(create_curve_data(), max_size=4, unique_by=lambda it: it.x_value) - } - - -def create_curve_data(): - return builds( - CurveData, - x_value=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - y1_value=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - y2_value=one_of(none(), floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX)), - y3_value=one_of(none(), floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX)) - ) - - -def create_equipment(include_runtime: bool): - runtime = { - "current_containers": lists(sampled_hvlv_feeder(include_runtime), max_size=2) - } if include_runtime else {} - - return { - **create_power_system_resource(include_runtime), - "in_service": booleans(), - "normally_in_service": booleans(), - "equipment_containers": lists(sampled_equipment_container(include_runtime), max_size=2), - "usage_points": lists(builds(UsagePoint, **create_identified_object(include_runtime)), max_size=2), - "operational_restrictions": lists(builds(OperationalRestriction, **create_identified_object(include_runtime)), max_size=2), - "commissioned_date": datetimes(min_value=datetime(1970, 1, 2)), - **runtime - } - - -def create_equipment_container(include_runtime: bool, add_equipment: bool = True): - equipment = { - "equipment": lists(sampled_equipment(include_runtime), max_size=30) - } if add_equipment else {} - - return { - **create_connectivity_node_container(include_runtime), - **equipment - } - - -def create_feeder(include_runtime: bool = True): - runtime = { - "normal_energized_lv_feeders": lists(builds(LvFeeder, **create_identified_object(include_runtime)), max_size=2), - "current_energized_lv_feeders": lists(builds(LvFeeder, **create_identified_object(include_runtime)), max_size=2), - "normal_energized_lv_substations": lists(builds(LvSubstation, **create_identified_object(include_runtime)), max_size=2), - "current_energized_lv_substations": lists(builds(LvSubstation, **create_identified_object(include_runtime)), max_size=2), - "current_equipment": lists(sampled_equipment(include_runtime), max_size=2), - } if include_runtime else {} - - return builds( - Feeder, - # Only include equipment if we are processing runtime as we don't write equipment to the database for Feeder. - **create_equipment_container(include_runtime, add_equipment=include_runtime), - normal_head_terminal=builds(Terminal, **create_identified_object(include_runtime)), - normal_energizing_substation=builds(Substation, **create_identified_object(include_runtime)), - **runtime - ) - - -def create_geographical_region(include_runtime: bool = True): - return builds( - GeographicalRegion, - **create_identified_object(include_runtime), - sub_geographical_regions=lists(builds(SubGeographicalRegion, **create_identified_object(include_runtime)), max_size=2) - ) - - -# noinspection PyUnusedLocal -def create_identified_object(include_runtime: bool): - return { - "mrid": uuids(version=4).map(lambda x: str(x)), - "name": one_of(none(), text(alphabet=ALPHANUM, max_size=TEXT_MAX_SIZE)), - "description": one_of(none(), text(alphabet=ALPHANUM, max_size=TEXT_MAX_SIZE)), - "names": one_of(none(), lists(builds(Name, text(alphabet=ALPHANUM, max_size=TEXT_MAX_SIZE), create_name_type()), max_size=2, unique_by=lambda it: it.name)) - } - - -def create_name(include_runtime: bool = True): - return builds( - Name, - name=text(alphabet=ALPHANUM, max_size=TEXT_MAX_SIZE), - type=create_name_type(), - identified_object=sampled_equipment(include_runtime) - ) - - -def create_name_type(): - return builds( - NameType, - name=text(alphabet=ALPHANUM, max_size=TEXT_MAX_SIZE), - description=text(alphabet=ALPHANUM, max_size=TEXT_MAX_SIZE) - ) - - -def sampled_phase_code(): - return sampled_from(PhaseCode) - - -def create_power_system_resource(include_runtime: bool): - # - # NOTE: We do not create the asset_info here, create it where it is actually used. - # - return { - **create_identified_object(include_runtime), - "location": create_location(), - "num_controls": integers(min_value=0, max_value=MAX_64_BIT_INTEGER), - "assets": lists(builds(Pole, **create_identified_object(include_runtime)), max_size=2) - } - - -def create_sub_geographical_region(include_runtime: bool = True): - return builds( - SubGeographicalRegion, - **create_identified_object(include_runtime), - geographical_region=builds(GeographicalRegion, **create_identified_object(include_runtime)), - substations=lists(builds(Substation, **create_identified_object(include_runtime)), max_size=2) - ) - - -def create_substation(include_runtime: bool = True): - return builds( - Substation, - **create_equipment_container(include_runtime), - sub_geographical_region=builds(SubGeographicalRegion, **create_identified_object(include_runtime)), - normal_energized_feeders=lists(builds(Feeder, **create_identified_object(include_runtime)), max_size=2), - loops=lists(builds(Loop, **create_identified_object(include_runtime)), max_size=2), - energized_loops=lists(builds(Loop, **create_identified_object(include_runtime)), max_size=2), - circuits=lists(builds(Circuit, **create_identified_object(include_runtime)), max_size=2) - ) - - -def create_terminal(include_runtime: bool = True): - runtime = { - } if include_runtime else {} - return builds( - Terminal, - **create_ac_dc_terminal(include_runtime), - conducting_equipment=sampled_conducting_equipment(include_runtime), - connectivity_node=builds(ConnectivityNode, **create_identified_object(include_runtime)), - phases=sampled_phase_code(), - sequence_number=integers(min_value=MIN_SEQUENCE_NUMBER, max_value=MAX_SEQUENCE_NUMBER), - **runtime - ) - - -################################ -# IEC61970 Base Diagram Layout # -################################ - - -def create_diagram(include_runtime: bool = True): - return builds( - Diagram, - **create_identified_object(include_runtime), - diagram_style=sampled_diagram_style(), - orientation_kind=sampled_orientation_kind(), - diagram_objects=lists(builds(DiagramObject, **create_identified_object(include_runtime)), max_size=2) - ) - - -def create_diagram_object(include_runtime: bool = True): - return builds( - DiagramObject, - **create_identified_object(include_runtime), - diagram=builds(Diagram, **create_identified_object(include_runtime)), - identified_object_mrid=text(alphabet=ALPHANUM, min_size=1, max_size=TEXT_MAX_SIZE), - style=text(alphabet=ALPHANUM, min_size=1, max_size=TEXT_MAX_SIZE), - rotation=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - diagram_object_points=lists(create_diagram_object_point(), max_size=2) - ) - - -def create_diagram_object_point(): - return builds( - DiagramObjectPoint, - x_position=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - y_position=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX) - ) - - -def sampled_diagram_style(): - return sampled_from(DiagramStyle) - - -def sampled_orientation_kind(): - return sampled_from(OrientationKind) - - -######################## -# IEC61970 Base Domain # -######################## - -def sampled_unit_symbol(): - return sampled_from(UnitSymbol) - - -############################# -# IEC61970 Base Equivalents # -############################# - - -def create_equivalent_branch(include_runtime: bool = True): - return builds( - EquivalentBranch, - **create_equivalent_equipment(include_runtime), - negative_r12=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - negative_r21=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - negative_x12=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - negative_x21=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - positive_r12=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - positive_r21=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - positive_x12=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - positive_x21=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - r=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - r21=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - x=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - x21=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - zero_r12=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - zero_r21=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - zero_x12=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - zero_x21=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX) - ) - - -def create_equivalent_equipment(include_runtime: bool): - return {**create_conducting_equipment(include_runtime)} - - -####################################### -# IEC61970 Base Generation Production # -####################################### - -def sampled_battery_state_kind(): - return sampled_from(BatteryStateKind) - - -def create_battery_unit(include_runtime: bool = True): - return builds( - BatteryUnit, - **create_power_electronics_unit(include_runtime), - battery_state=sampled_battery_state_kind(), - rated_e=integers(min_value=MIN_64_BIT_INTEGER, max_value=MAX_64_BIT_INTEGER), - stored_e=integers(min_value=MIN_64_BIT_INTEGER, max_value=MAX_64_BIT_INTEGER), - controls=lists(builds(BatteryControl, **create_identified_object(include_runtime)), max_size=2) - ) - - -def create_photo_voltaic_unit(include_runtime: bool = True): - return builds(PhotoVoltaicUnit, **create_power_electronics_unit(include_runtime)) - - -def create_power_electronics_unit(include_runtime: bool): - return { - **create_equipment(include_runtime), - "power_electronics_connection": builds(PowerElectronicsConnection, **create_identified_object(include_runtime)), - "max_p": integers(min_value=MIN_32_BIT_INTEGER, max_value=MAX_32_BIT_INTEGER), - "min_p": integers(min_value=MIN_32_BIT_INTEGER, max_value=MAX_32_BIT_INTEGER) - } - - -def create_power_electronics_wind_unit(include_runtime: bool = True): - return builds(PowerElectronicsWindUnit, **create_power_electronics_unit(include_runtime)) - - -###################### -# IEC61970 Base Meas # -###################### - - -def create_accumulator(include_runtime: bool = True): - return builds(Accumulator, **create_measurement(include_runtime)) - - -def create_accumulator_value(): - return builds( - AccumulatorValue, - **create_measurement_value(), - value=integers(min_value=MIN_64_BIT_INTEGER, max_value=MAX_64_BIT_INTEGER) - ) - - -def create_analog(include_runtime: bool = True): - return builds( - Analog, - **create_measurement(include_runtime), - positive_flow_in=booleans() - ) - - -def create_analog_value(): - return builds( - AnalogValue, - **create_measurement_value(), - value=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX) - ) - - -def create_control(include_runtime: bool = True): - return builds( - Control, - **create_io_point(include_runtime), - power_system_resource_mrid=text(alphabet=ALPHANUM, min_size=1, max_size=TEXT_MAX_SIZE), - remote_control=builds(RemoteControl, **create_identified_object(include_runtime)) - ) - - -def create_discrete(include_runtime: bool = True): - return builds(Discrete, **create_measurement(include_runtime)) - - -def create_discrete_value(): - return builds( - DiscreteValue, - **create_measurement_value(), - value=integers(min_value=MIN_64_BIT_INTEGER, max_value=MAX_64_BIT_INTEGER) - ) - - -def create_io_point(include_runtime: bool): - return {**create_identified_object(include_runtime)} - - -def create_measurement(include_runtime: bool): - return { - **create_identified_object(include_runtime), - "remote_source": builds(RemoteSource, **create_identified_object(include_runtime)), - "power_system_resource_mrid": uuids(version=4).map(lambda x: str(x)), - "terminal_mrid": uuids(version=4).map(lambda x: str(x)), - "phases": sampled_phase_code(), - "unit_symbol": sampled_unit_symbol() - } - - -# noinspection PyUnusedLocal -def create_measurement_value(): - return { - # "time_stamp": ... - } - - -############################ -# IEC61970 Base Protection # -############################ - - -def create_current_relay(include_runtime: bool = True): - return builds( - CurrentRelay, - **create_protection_relay_function(include_runtime), - current_limit_1=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - inverse_time_flag=boolean_or_none(), - time_delay_1=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX) - ) - - -####################### -# IEC61970 Base Scada # -####################### - -def create_remote_control(include_runtime: bool = True): - return builds( - RemoteControl, - **create_remote_point(include_runtime), - control=builds(Control, **create_identified_object(include_runtime)) - ) - - -def create_remote_point(include_runtime: bool): - return {**create_identified_object(include_runtime)} - - -def create_remote_source(include_runtime: bool = True): - return builds( - RemoteSource, - **create_remote_point(include_runtime), - measurement=sampled_measurement(include_runtime) - ) - - -####################### -# IEC61970 Base Wires # -####################### - - -def create_ac_line_segment(include_runtime: bool = True): - args = create_conductor(include_runtime) - args["terminals"] = lists(builds(Terminal, **create_identified_object(include_runtime)), max_size=2) - return builds( - AcLineSegment, - **args, - per_length_impedance=builds(PerLengthSequenceImpedance, **create_identified_object(include_runtime)), - ) - -def create_ac_line_segment_phase(include_runtime: bool = True): - return builds( - AcLineSegmentPhase, - **create_power_system_resource(include_runtime), - ac_line_segment=builds(AcLineSegment, **create_identified_object(include_runtime)), - phase=sampled_single_phase_kind(), - sequence_number=integers(min_value=MIN_SEQUENCE_NUMBER, max_value=MAX_SEQUENCE_NUMBER), - ) - - -def create_breaker(include_runtime: bool = True): - return builds( - Breaker, - **create_protected_switch(include_runtime), - in_transit_time=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX) - ) - - -def create_busbar_section(include_runtime: bool = True): - # Monkey patch the args to set terminals to 1, as busbars only have 1 terminal. - args = create_connector(include_runtime) - args["terminals"] = lists(builds(Terminal, **create_identified_object(include_runtime)), max_size=1) - return builds(BusbarSection, **args) - - -def create_clamp(include_runtime: bool = True): - args = create_conducting_equipment(include_runtime) - args["terminals"] = lists(builds(Terminal, **create_identified_object(include_runtime)), max_size=1) - return builds( - Clamp, - **args, - length_from_terminal_1=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - ac_line_segment=builds(AcLineSegment, **create_identified_object(include_runtime)) - ) - - -def create_conductor(include_runtime: bool): - return { - **create_conducting_equipment(include_runtime), - "asset_info": sampled_wire_info(include_runtime), - "length": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - "design_temperature": integers(min_value=MIN_32_BIT_INTEGER, max_value=MAX_32_BIT_INTEGER), - "design_rating": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX) - } - - -def create_connector(include_runtime: bool): - return {**create_conducting_equipment(include_runtime)} - - -def create_cut(include_runtime: bool = True): - args = create_switch(include_runtime) - args["terminals"] = lists(builds(Terminal, **create_identified_object(include_runtime)), max_size=2) - return builds( - Cut, - **args, - length_from_terminal_1=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - ac_line_segment=builds(AcLineSegment, **create_identified_object(include_runtime)), - ) - - -def create_disconnector(include_runtime: bool = True): - return builds(Disconnector, **create_switch(include_runtime)) - - -def create_earth_fault_compensator(include_runtime: bool): - return { - **create_conducting_equipment(include_runtime), - "r": one_of(none(), floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX)) - } - - -def create_energy_connection(include_runtime: bool): - return {**create_conducting_equipment(include_runtime)} - - -def create_energy_consumer(include_runtime: bool = True): - return builds( - EnergyConsumer, - **create_energy_connection(include_runtime), - energy_consumer_phases=lists( - builds( - EnergyConsumerPhase, - **create_identified_object(include_runtime), - phase=sampled_single_phase_kind() - ), - max_size=2 - ), - customer_count=integers(min_value=0, max_value=MAX_32_BIT_INTEGER), - grounded=booleans(), - p=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - p_fixed=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - phase_connection=sampled_phase_shunt_connection_kind(), - q=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - q_fixed=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX) - ) - - -def create_energy_consumer_phase(include_runtime: bool = True): - return builds( - EnergyConsumerPhase, - **create_power_system_resource(include_runtime), - energy_consumer=builds(EnergyConsumer, **create_identified_object(include_runtime)), - phase=sampled_single_phase_kind(), - p=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - p_fixed=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - q=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - q_fixed=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX) - ) - - -def create_energy_source(include_runtime: bool = True): - return builds( - EnergySource, - **create_energy_connection(include_runtime), - energy_source_phases=lists( - builds( - EnergySourcePhase, - **create_identified_object(include_runtime), - phase=sampled_single_phase_kind() - ), - max_size=2), - active_power=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - reactive_power=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - voltage_angle=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - voltage_magnitude=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - r=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - x=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - p_max=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - p_min=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - r0=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - rn=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - x0=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - xn=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - is_external_grid=booleans(), - r_min=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - rn_min=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - r0_min=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - x_min=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - xn_min=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - x0_min=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - r_max=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - rn_max=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - r0_max=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - x_max=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - xn_max=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - x0_max=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX) - ) - - -def create_energy_source_phase(include_runtime: bool = True): - return builds( - EnergySourcePhase, - **create_power_system_resource(include_runtime), - energy_source=builds(EnergySource, **create_identified_object(include_runtime)), - phase=sampled_single_phase_kind() - ) - - -def create_fuse(include_runtime: bool = True): - return builds( - Fuse, - **create_switch(include_runtime), - function=builds(DistanceRelay, mrid=mrid_strategy) - ) - - -def create_ground(include_runtime: bool = True): - return builds( - Ground, - **create_conducting_equipment(include_runtime) - ) - - -def create_ground_disconnector(include_runtime: bool = True): - return builds( - GroundDisconnector, - **create_switch(include_runtime) - ) - - -def create_grounding_impedance(include_runtime: bool = True): - return builds( - GroundingImpedance, - **create_earth_fault_compensator(include_runtime), - x=one_of(none(), floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX)) - ) - - -def create_jumper(include_runtime: bool = True): - return builds(Jumper, **create_switch(include_runtime)) - - -def create_junction(include_runtime: bool = True): - return builds(Junction, **create_connector(include_runtime)) - - -def create_line(include_runtime: bool): - return {**create_equipment_container(include_runtime)} - - -def create_linear_shunt_compensator(include_runtime: bool = True): - return builds( - LinearShuntCompensator, - **create_shunt_compensator(include_runtime), - b0_per_section=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - b_per_section=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - g0_per_section=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - g_per_section=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX) - ) - - -def create_load_break_switch(include_runtime: bool = True): - return builds(LoadBreakSwitch, **create_protected_switch(include_runtime)) - - -def create_per_length_impedance(include_runtime: bool): - return {**create_per_length_line_parameter(include_runtime)} - - -def create_per_length_line_parameter(include_runtime: bool): - return {**create_identified_object(include_runtime)} - - -def create_per_length_phase_impedance(include_runtime: bool = True): - return builds( - PerLengthPhaseImpedance, - data=lists(create_phase_impedance_data(), max_size=4, unique_by=(lambda it: it.from_phase, lambda it: it.to_phase)), - **create_per_length_impedance(include_runtime), - ) - - -def create_per_length_sequence_impedance(include_runtime: bool = True): - return builds( - PerLengthSequenceImpedance, - **create_per_length_impedance(include_runtime), - r=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - x=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - r0=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - x0=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - bch=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - gch=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - b0ch=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - g0ch=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX) - ) - - -def create_petersen_coil(include_runtime: bool = True): - return builds( - PetersenCoil, - **create_earth_fault_compensator(include_runtime), - x_ground_nominal=one_of(none(), floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX)) - ) - - -def create_phase_impedance_data(): - return builds( - PhaseImpedanceData, - from_phase=sampled_from(SinglePhaseKind), - to_phase=sampled_from(SinglePhaseKind), - b=one_of(none(), floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX)), - g=one_of(none(), floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX)), - r=one_of(none(), floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX)), - x=one_of(none(), floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX)) - ) - - -def sampled_phase_shunt_connection_kind(): - return sampled_from(PhaseShuntConnectionKind) - - -def create_power_electronics_connection(include_runtime: bool = True): - return builds( - PowerElectronicsConnection, - **create_regulating_cond_eq(include_runtime), - power_electronics_units=lists(builds(BatteryUnit, **create_identified_object(include_runtime)), max_size=2), - power_electronics_connection_phases=lists(builds(PowerElectronicsConnectionPhase, **create_identified_object(include_runtime)), max_size=2), - max_i_fault=integers(min_value=0, max_value=MAX_32_BIT_INTEGER), - max_q=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - min_q=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - p=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - q=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - rated_s=integers(min_value=0, max_value=MAX_32_BIT_INTEGER), - rated_u=integers(min_value=0, max_value=MAX_32_BIT_INTEGER), - inverter_standard=text(alphabet=ALPHANUM, min_size=1, max_size=TEXT_MAX_SIZE), - sustain_op_overvolt_limit=integers(min_value=0, max_value=MAX_32_BIT_INTEGER), - stop_at_over_freq=floats(min_value=51.0, max_value=52.0), - stop_at_under_freq=floats(min_value=47.0, max_value=49.0), - inv_volt_watt_resp_mode=boolean_or_none(), - inv_watt_resp_v1=integers(min_value=200, max_value=300), - inv_watt_resp_v2=integers(min_value=216, max_value=230), - inv_watt_resp_v3=integers(min_value=235, max_value=255), - inv_watt_resp_v4=integers(min_value=244, max_value=265), - inv_watt_resp_p_at_v1=floats(min_value=0.0, max_value=1.0), - inv_watt_resp_p_at_v2=floats(min_value=0.0, max_value=1.0), - inv_watt_resp_p_at_v3=floats(min_value=0.0, max_value=1.0), - inv_watt_resp_p_at_v4=floats(min_value=0.0, max_value=0.12300000339746475), - inv_volt_var_resp_mode=boolean_or_none(), - inv_var_resp_v1=integers(min_value=200, max_value=300), - inv_var_resp_v2=integers(min_value=200, max_value=300), - inv_var_resp_v3=integers(min_value=200, max_value=300), - inv_var_resp_v4=integers(min_value=200, max_value=300), - inv_var_resp_q_at_v1=floats(min_value=0.0, max_value=0.5120000243186951), - inv_var_resp_q_at_v2=floats(min_value=-1.0, max_value=1.0), - inv_var_resp_q_at_v3=floats(min_value=-1.0, max_value=1.0), - inv_var_resp_q_at_v4=floats(min_value=-0.5120000243186951, max_value=0.0), - inv_reactive_power_mode=boolean_or_none(), - inv_fix_reactive_power=floats(min_value=-1.0, max_value=1.0), - ) - - -def create_power_electronics_connection_phase(include_runtime: bool = True): - return builds( - PowerElectronicsConnectionPhase, - **create_power_system_resource(include_runtime), - power_electronics_connection=builds(PowerElectronicsConnection, **create_identified_object(include_runtime)), - phase=sampled_single_phase_kind(), - p=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - q=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX) - ) - - -def create_power_transformer(include_runtime: bool = True): - return builds( - PowerTransformer, - **create_conducting_equipment(include_runtime), - asset_info=builds(PowerTransformerInfo, **create_identified_object(include_runtime)), - power_transformer_ends=lists(builds(PowerTransformerEnd, **create_identified_object(include_runtime)), max_size=2), - vector_group=sampled_vector_group(), - transformer_utilisation=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX) - ) - - -def create_power_transformer_end(include_runtime: bool = True): - return builds( - create_power_transformer_end_with_ratings, - **create_transformer_end(include_runtime), - power_transformer=builds(PowerTransformer, **create_identified_object(include_runtime)), - # rated_s=integers(min_value=MIN_32_BIT_INTEGER, max_value=MAX_32_BIT_INTEGER), - rated_u=integers(min_value=MIN_32_BIT_INTEGER, max_value=MAX_32_BIT_INTEGER), - r=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - r0=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - x=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - x0=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - connection_kind=sampled_winding_connection(), - b=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - b0=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - g=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - g0=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - phase_angle_clock=integers(min_value=0, max_value=11), - ratings=lists(builds( - TransformerEndRatedS, - cooling_type=sampled_transformer_cooling_type(), - rated_s=integers(min_value=MIN_32_BIT_INTEGER, max_value=MAX_32_BIT_INTEGER) - ), max_size=11, unique_by=lambda it: it.cooling_type) - ) - - -def create_protected_switch(include_runtime: bool): - return { - **create_switch(include_runtime), - "breaking_capacity": integers(min_value=MIN_32_BIT_INTEGER, max_value=MAX_32_BIT_INTEGER), - "relay_functions": lists(builds(CurrentRelay, mrid=mrid_strategy), max_size=2) - } - - -def create_ratio_tap_changer(include_runtime: bool = True): - return builds( - RatioTapChanger, - **create_tap_changer(include_runtime), - transformer_end=builds(PowerTransformerEnd, **create_identified_object(include_runtime)), - step_voltage_increment=floats(min_value=0.0, max_value=1.0) - ) - - -def create_reactive_capability_curve(include_runtime: bool = True): - return builds( - ReactiveCapabilityCurve, - **create_curve(include_runtime) - ) - - -def create_recloser(include_runtime: bool = True): - return builds(Recloser, **create_protected_switch(include_runtime)) - - -def create_regulating_cond_eq(include_runtime: bool): - return { - **create_energy_connection(include_runtime), - "control_enabled": one_of(none(), booleans()), - "regulating_control": builds(TapChangerControl, **create_identified_object(include_runtime)), - } - - -def create_regulating_control(include_runtime: bool): - return { - **create_power_system_resource(include_runtime), - "discrete": boolean_or_none(), - "mode": sampled_from(RegulatingControlModeKind), - "monitored_phase": sampled_phase_code(), - "target_deadband": floats(min_value=0.0, max_value=FLOAT_MAX), - "target_value": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - "enabled": boolean_or_none(), - "max_allowed_target_value": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - "min_allowed_target_value": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - "rated_current": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - "terminal": builds(Terminal, **create_identified_object(include_runtime)), - "ct_primary": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - "min_target_deadband": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - "regulating_conducting_equipment": lists(builds(PowerElectronicsConnection, **create_identified_object(include_runtime))) - } - - -def sampled_regulating_control_mode_kind(): - return sampled_from(RegulatingControlModeKind) - - -def create_rotating_machine(include_runtime: bool): - return { - **create_regulating_cond_eq(include_runtime), - "rated_power_factor": one_of(none(), floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX)), - "rated_s": one_of(none(), floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX)), - "rated_u": one_of(none(), integers(min_value=MIN_32_BIT_INTEGER, max_value=MAX_32_BIT_INTEGER)), - "p": one_of(none(), floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX)), - "q": one_of(none(), floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX)) - } - - -def create_series_compensator(include_runtime: bool = True): - return builds( - SeriesCompensator, - **create_conducting_equipment(include_runtime), - r=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - r0=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - x=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - x0=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - varistor_rated_current=integers(min_value=MIN_32_BIT_INTEGER, max_value=MAX_32_BIT_INTEGER), - varistor_voltage_threshold=integers(min_value=MIN_32_BIT_INTEGER, max_value=MAX_32_BIT_INTEGER), - ) - - -def create_shunt_compensator(include_runtime: bool): - return { - **create_regulating_cond_eq(include_runtime), - "asset_info": builds(ShuntCompensatorInfo, **create_identified_object(include_runtime)), - "grounded": booleans(), - "nom_u": integers(min_value=MIN_32_BIT_INTEGER, max_value=MAX_32_BIT_INTEGER), - "phase_connection": sampled_phase_shunt_connection_kind(), - "sections": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - "grounding_terminal": builds(Terminal, **create_identified_object(include_runtime)), - } - - -def sampled_single_phase_kind(): - return sampled_from(SinglePhaseKind) - - -def create_static_var_compensator(include_runtime: bool = True): - return builds( - StaticVarCompensator, - **create_regulating_cond_eq(include_runtime), - capacitive_rating=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - inductive_rating=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - q=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - svc_control_mode=sampled_svc_control_mode(), - voltage_set_point=integers(min_value=MIN_32_BIT_INTEGER, max_value=MAX_32_BIT_INTEGER), - ) - - -def sampled_svc_control_mode(): - return sampled_from(SVCControlMode) - - -def create_switch(include_runtime: bool): - return { - **create_conducting_equipment(include_runtime), - "rated_current": floats(min_value=1, max_value=FLOAT_MAX), - # NOTE: These are not currently encoded properly in protobuf so we can only use all or none. - "_normally_open": sampled_from([0, 15]), - "_open": sampled_from([0, 15]) - # "_normally_open": integers(min_value=0, max_value=15), - # "_open": integers(min_value=0, max_value=15) - } - - -def create_synchronous_machine(include_runtime: bool = True): - return builds( - SynchronousMachine, - **create_rotating_machine(include_runtime), - curves=one_of(none(), lists(builds(ReactiveCapabilityCurve, **create_identified_object(include_runtime)), max_size=2)), - base_q=one_of(none(), floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX)), - condenser_p=one_of(none(), integers(min_value=MIN_32_BIT_INTEGER, max_value=MAX_32_BIT_INTEGER)), - earthing=one_of(none(), booleans()), - earthing_star_point_r=one_of(none(), floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX)), - earthing_star_point_x=one_of(none(), floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX)), - ikk=one_of(none(), floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX)), - max_q=one_of(none(), floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX)), - max_u=one_of(none(), integers(min_value=MIN_32_BIT_INTEGER, max_value=MAX_32_BIT_INTEGER)), - min_q=one_of(none(), floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX)), - min_u=one_of(none(), integers(min_value=MIN_32_BIT_INTEGER, max_value=MAX_32_BIT_INTEGER)), - mu=one_of(none(), floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX)), - r=one_of(none(), floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX)), - r0=one_of(none(), floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX)), - r2=one_of(none(), floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX)), - sat_direct_subtrans_x=one_of(none(), floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX)), - sat_direct_sync_x=one_of(none(), floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX)), - sat_direct_trans_x=one_of(none(), floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX)), - x0=one_of(none(), floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX)), - x2=one_of(none(), floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX)), - type=sampled_synchronous_machine_kind(), - operating_mode=sampled_synchronous_machine_kind() - ) - - -def sampled_synchronous_machine_kind(): - return sampled_from(SynchronousMachineKind) - - -def create_tap_changer(include_runtime: bool): - return { - **create_power_system_resource(include_runtime), - "high_step": integers(min_value=10, max_value=15), - "low_step": integers(min_value=0, max_value=2), - "step": floats(min_value=2.0, max_value=10.0), - "neutral_step": integers(min_value=2, max_value=10), - "neutral_u": integers(min_value=MIN_32_BIT_INTEGER, max_value=MAX_32_BIT_INTEGER), - "normal_step": integers(min_value=2, max_value=10), - "control_enabled": booleans(), - "tap_changer_control": builds(TapChangerControl, **create_identified_object(include_runtime)) - } - - -def create_tap_changer_control(include_runtime: bool = True): - return builds( - TapChangerControl, - **create_regulating_control(include_runtime), - limit_voltage=integers(min_value=MIN_32_BIT_INTEGER, max_value=MAX_32_BIT_INTEGER), - line_drop_compensation=boolean_or_none(), - line_drop_r=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - line_drop_x=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - reverse_line_drop_r=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - reverse_line_drop_x=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - forward_ldc_blocking=boolean_or_none(), - time_delay=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - co_generation_enabled=boolean_or_none() - ) - - -def create_transformer_end(include_runtime: bool): - return { - **create_identified_object(include_runtime), - "terminal": builds(Terminal, **create_identified_object(include_runtime)), - "base_voltage": builds(BaseVoltage, **create_identified_object(include_runtime)), - "ratio_tap_changer": builds(RatioTapChanger, **create_identified_object(include_runtime)), - "end_number": integers(min_value=MIN_SEQUENCE_NUMBER, max_value=MAX_END_NUMBER), - "grounded": booleans(), - "r_ground": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - "x_ground": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - "star_impedance": builds(TransformerStarImpedance, **create_identified_object(include_runtime)) - } - - -def create_transformer_star_impedance(include_runtime: bool = True): - return builds( - TransformerStarImpedance, - **create_identified_object(include_runtime), - r=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - r0=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - x=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - x0=floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - transformer_end_info=builds(TransformerEndInfo, **create_identified_object(include_runtime)) - ) - - -def sampled_winding_connection(): - return sampled_from(WindingConnection) - - -############################### -# IEC61970 InfIEC61970 Feeder # -############################### - - -def create_circuit(include_runtime: bool = True): - return builds( - Circuit, - **create_line(include_runtime), - loop=builds(Loop, **create_identified_object(include_runtime)), - end_terminals=lists(builds(Terminal, **create_identified_object(include_runtime)), max_size=2), - end_substations=lists(builds(Substation, **create_identified_object(include_runtime)), max_size=2) - ) - - -######### -# MODEL # -######### - - -def traced_phases(): - return builds( - TracedPhases, - normal_status=integers(min_value=MIN_32_BIT_INTEGER, max_value=MAX_32_BIT_INTEGER), - current_status=integers(min_value=MIN_32_BIT_INTEGER, max_value=MAX_32_BIT_INTEGER) - ) - - -def boolean_or_none(): - return sampled_from([False, True, None]) - - -############### -# SAMPLE SETS # -############### - - -def sampled_wire_info(include_runtime: bool): - return choice([ - builds(OverheadWireInfo, **create_identified_object(include_runtime)), - builds(CableInfo, **create_identified_object(include_runtime)), - ]) - - -def sampled_conducting_equipment(include_runtime: bool): - return choice([ - # Don't add EnergySource to this list as it's used in SetPhases to start tracing, which will cause test_schema_terminal to fail. - builds(AcLineSegment, **create_identified_object(include_runtime)), - builds(PowerTransformer, **create_identified_object(include_runtime)), - builds(Breaker, **create_identified_object(include_runtime)), - builds(Disconnector, **create_identified_object(include_runtime)), - builds(EnergyConsumer, **create_identified_object(include_runtime)), - ]) - - -def sampled_curves(include_runtime: bool): - return choice([ - builds(ReactiveCapabilityCurve, **create_identified_object(include_runtime)) - ]) - - -def sampled_end_device_function(include_runtime: bool): - return choice([ - # Don't add EnergySource to this list as it's used in SetPhases to start tracing, which will cause test_schema_terminal to fail. - builds(PanDemandResponseFunction, **create_identified_object(include_runtime)) - ]) - - -def sampled_equipment(include_runtime: bool): - return choice([ - builds(AcLineSegment, **create_identified_object(include_runtime)), - builds(PowerTransformer, **create_identified_object(include_runtime)), - builds(Breaker, **create_identified_object(include_runtime)), - builds(Disconnector, **create_identified_object(include_runtime)), - builds(EnergyConsumer, **create_identified_object(include_runtime)), - builds(EnergySource, **create_identified_object(include_runtime)), - builds(FaultIndicator, **create_identified_object(include_runtime)) - ]) - - -def sampled_equipment_container(include_runtime: bool): - available_containers = [ - builds(Site, **create_identified_object(include_runtime)), - builds(Circuit, **create_identified_object(include_runtime)), - builds(Substation, **create_identified_object(include_runtime)) - ] - - if include_runtime: - available_containers.append(builds(Feeder, **create_identified_object(include_runtime))) - - return choice(available_containers) - - -def sampled_hvlv_feeder(include_runtime: bool): - return choice([ - builds(Feeder, **create_identified_object(include_runtime)), - builds(LvFeeder, **create_identified_object(include_runtime)) - ]) - - -def sampled_measurement(include_runtime: bool): - return choice([ - builds(Accumulator, **create_identified_object(include_runtime)), - builds(Analog, **create_identified_object(include_runtime)), - builds(Discrete, **create_identified_object(include_runtime)), - ]) - - -def sampled_protected_switches(include_runtime: bool): - return choice([ - builds(Breaker, **create_identified_object(include_runtime)), - builds(LoadBreakSwitch, **create_identified_object(include_runtime)), - builds(Recloser, **create_identified_object(include_runtime)) - ]) diff --git a/test/cim/extensions/iec61968/common/test_contact_details.py b/test/cim/extensions/iec61968/common/test_contact_details.py index fdad61453..38482f830 100644 --- a/test/cim/extensions/iec61968/common/test_contact_details.py +++ b/test/cim/extensions/iec61968/common/test_contact_details.py @@ -5,7 +5,7 @@ from hypothesis import given from hypothesis.strategies import builds, text, sampled_from, booleans -from cim.cim_creators import ALPHANUM +from cim.fill_fields import ALPHANUM from cim.private_collection_validator import validate_unordered_other, DuplicateBehaviour from streaming.get.pb_creators import lists from zepben.ewb import ContactMethodType, TelephoneNumber, ElectronicAddress, ContactDetails diff --git a/test/cim/extensions/iec61970/base/wires/test_battery_control.py b/test/cim/extensions/iec61970/base/wires/test_battery_control.py index c3852101b..a354a0257 100644 --- a/test/cim/extensions/iec61970/base/wires/test_battery_control.py +++ b/test/cim/extensions/iec61970/base/wires/test_battery_control.py @@ -5,7 +5,7 @@ from hypothesis import given from hypothesis.strategies import floats, sampled_from -from cim.cim_creators import FLOAT_MIN, FLOAT_MAX +from cim.fill_fields import FLOAT_MIN, FLOAT_MAX from cim.iec61970.base.wires.test_regulating_control import regulating_control_kwargs, regulating_control_args, verify_regulating_control_constructor_default, \ verify_regulating_control_constructor_kwargs, verify_regulating_control_constructor_args from zepben.ewb import BatteryControl, BatteryControlMode, generate_id diff --git a/test/cim/fill_fields.py b/test/cim/fill_fields.py new file mode 100644 index 000000000..a5be38689 --- /dev/null +++ b/test/cim/fill_fields.py @@ -0,0 +1,2412 @@ +# Copyright 2024 Zeppelin Bend Pty Ltd +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at https://mozilla.org/MPL/2.0/. + +__all__ = [ + 'MIN_32_BIT_INTEGER', 'MAX_32_BIT_INTEGER', 'MAX_32_BIT_UNSIGNED_INTEGER', 'MAX_64_BIT_INTEGER', 'MIN_64_BIT_INTEGER', 'TEXT_MAX_SIZE', 'FLOAT_MIN', + 'FLOAT_MAX', 'MAX_END_NUMBER', 'MAX_SEQUENCE_NUMBER', 'MIN_SEQUENCE_NUMBER', 'ALPHANUM', 'create_relay_info', 'relay_info_kwargs', 'create_contact_details', + 'contact_details_kwargs', 'create_pan_demand_response_function', 'pan_demand_response_function_kwargs', 'create_hv_customer', 'hv_customer_kwargs', + 'create_site', 'site_kwargs', 'create_loop', 'loop_kwargs', 'create_lv_feeder', 'lv_feeder_kwargs', 'create_lv_substation', 'lv_substation_kwargs', + 'create_ev_charging_unit', 'ev_charging_unit_kwargs', 'create_directional_current_relay', 'directional_current_relay_kwargs', 'create_distance_relay', + 'distance_relay_kwargs', 'sampled_power_direction_kind', 'sampled_protection_kind', 'protection_relay_function_kwargs', 'create_protection_relay_scheme', + 'protection_relay_scheme_kwargs', 'create_protection_relay_system', 'protection_relay_system_kwargs', 'create_relay_setting', 'relay_setting_kwargs', + 'create_voltage_relay', 'voltage_relay_kwargs', 'create_battery_control', 'battery_control_kwargs', 'sampled_battery_control_mode', + 'sampled_transformer_cooling_type', 'create_power_transformer_end_with_ratings', 'sampled_vector_group', 'create_cable_info', 'cable_info_kwargs', + 'create_no_load_test', 'no_load_test_kwargs', 'create_open_circuit_test', 'open_circuit_test_kwargs', 'create_overhead_wire_info', + 'overhead_wire_info_kwargs', 'create_power_transformer_info', 'power_transformer_info_kwargs', 'create_short_circuit_test', 'short_circuit_test_kwargs', + 'create_shunt_compensator_info', 'shunt_compensator_info_kwargs', 'create_switch_info', 'switch_info_kwargs', 'create_transformer_end_info', + 'transformer_end_info_kwargs', 'create_transformer_tank_info', 'transformer_tank_info_kwargs', 'transformer_test_kwargs', 'wire_info_kwargs', + 'sampled_wire_material_kind', 'sampled_wire_insulation_kind', 'asset_kwargs', 'asset_container_kwargs', 'asset_function_kwargs', 'asset_info_kwargs', + 'asset_organisation_role_kwargs', 'create_asset_owner', 'asset_owner_kwargs', 'create_streetlight', 'streetlight_kwargs', 'structure_kwargs', + 'agreement_kwargs', 'document_kwargs', 'create_electronic_address', 'electronic_address_kwargs', 'create_location', 'location_kwargs', + 'create_organisation', 'organisation_kwargs', 'organisation_role_kwargs', 'create_position_point', 'position_point_kwargs', 'create_street_address', + 'street_address_kwargs', 'create_street_detail', 'street_detail_kwargs', 'create_telephone_number', 'telephone_number_kwargs', 'create_town_detail', + 'town_detail_kwargs', 'create_customer', 'customer_kwargs', 'create_customer_agreement', 'customer_agreement_kwargs', 'sampled_customer_kind', + 'create_pricing_structure', 'pricing_structure_kwargs', 'create_tariffs', 'tariffs_kwargs', 'create_current_transformer_info', + 'current_transformer_info_kwargs', 'create_potential_transformer_info', 'potential_transformer_info_kwargs', 'sampled_transformer_construction_kind', + 'sampled_transformer_function_kind', 'create_pole', 'pole_kwargs', 'sampled_streetlight_lamp_kind', 'create_ratio', 'ratio_kwargs', + 'create_controlled_appliance', 'controlled_appliance_kwargs', 'end_device_kwargs', 'end_device_function_kwargs', 'sampled_end_device_function_kind', + 'create_meter', 'meter_kwargs', 'create_usage_point', 'usage_point_kwargs', 'create_operational_restriction', 'operational_restriction_kwargs', + 'auxiliary_equipment_kwargs', 'create_current_transformer', 'current_transformer_kwargs', 'create_fault_indicator', 'fault_indicator_kwargs', + 'create_potential_transformer', 'potential_transformer_kwargs', 'sampled_potential_transformer_kind', 'sensor_kwargs', 'ac_dc_terminal_kwargs', + 'create_base_voltage', 'base_voltage_kwargs', 'conducting_equipment_kwargs', 'create_connectivity_node', 'connectivity_node_kwargs', + 'connectivity_node_container_kwargs', 'curve_kwargs', 'create_curve_data', 'curve_data_kwargs', 'equipment_kwargs', 'equipment_container_kwargs', + 'create_feeder', 'feeder_kwargs', 'create_geographical_region', 'geographical_region_kwargs', 'identified_object_kwargs', 'create_name', 'name_kwargs', + 'create_name_type', 'name_type_kwargs', 'sampled_phase_code', 'power_system_resource_kwargs', 'create_sub_geographical_region', + 'sub_geographical_region_kwargs', 'create_substation', 'substation_kwargs', 'create_terminal', 'terminal_kwargs', 'create_diagram', 'diagram_kwargs', + 'create_diagram_object', 'diagram_object_kwargs', 'create_diagram_object_point', 'diagram_object_point_kwargs', 'sampled_diagram_style', + 'sampled_orientation_kind', 'sampled_unit_symbol', 'create_equivalent_branch', 'equivalent_branch_kwargs', 'equivalent_equipment_kwargs', + 'sampled_battery_state_kind', 'create_battery_unit', 'battery_unit_kwargs', 'create_photo_voltaic_unit', 'photo_voltaic_unit_kwargs', + 'power_electronics_unit_kwargs', 'create_power_electronics_wind_unit', 'power_electronics_wind_unit_kwargs', 'create_accumulator', 'accumulator_kwargs', + 'create_accumulator_value', 'accumulator_value_kwargs', 'create_analog', 'analog_kwargs', 'create_analog_value', 'analog_value_kwargs', 'create_control', + 'control_kwargs', 'create_discrete', 'discrete_kwargs', 'create_discrete_value', 'discrete_value_kwargs', 'io_point_kwargs', 'measurement_kwargs', + 'measurement_value_kwargs', 'create_current_relay', 'current_relay_kwargs', 'create_remote_control', 'remote_control_kwargs', 'remote_point_kwargs', + 'create_remote_source', 'remote_source_kwargs', 'create_ac_line_segment', 'ac_line_segment_kwargs', 'create_ac_line_segment_phase', + 'ac_line_segment_phase_kwargs', 'create_breaker', 'breaker_kwargs', 'create_busbar_section', 'busbar_section_kwargs', 'create_clamp', 'clamp_kwargs', + 'conductor_kwargs', 'connector_kwargs', 'create_cut', 'cut_kwargs', 'create_disconnector', 'disconnector_kwargs', 'earth_fault_compensator_kwargs', + 'energy_connection_kwargs', 'create_energy_consumer', 'energy_consumer_kwargs', 'create_energy_consumer_phase', 'energy_consumer_phase_kwargs', + 'create_energy_source', 'energy_source_kwargs', 'create_energy_source_phase', 'energy_source_phase_kwargs', 'create_fuse', 'fuse_kwargs', 'create_ground', + 'ground_kwargs', 'create_ground_disconnector', 'ground_disconnector_kwargs', 'create_grounding_impedance', 'grounding_impedance_kwargs', 'create_jumper', + 'jumper_kwargs', 'create_junction', 'junction_kwargs', 'line_kwargs', 'create_linear_shunt_compensator', 'linear_shunt_compensator_kwargs', + 'create_load_break_switch', 'load_break_switch_kwargs', 'per_length_impedance_kwargs', 'per_length_line_parameter_kwargs', + 'create_per_length_phase_impedance', 'per_length_phase_impedance_kwargs', 'create_per_length_sequence_impedance', 'per_length_sequence_impedance_kwargs', + 'create_petersen_coil', 'petersen_coil_kwargs', 'create_phase_impedance_data', 'phase_impedance_data_kwargs', 'sampled_phase_shunt_connection_kind', + 'create_power_electronics_connection', 'power_electronics_connection_kwargs', 'create_power_electronics_connection_phase', + 'power_electronics_connection_phase_kwargs', 'create_power_transformer', 'power_transformer_kwargs', 'create_power_transformer_end', + 'power_transformer_end_kwargs', 'protected_switch_kwargs', 'create_ratio_tap_changer', 'ratio_tap_changer_kwargs', 'create_reactive_capability_curve', + 'reactive_capability_curve_kwargs', 'create_recloser', 'recloser_kwargs', 'regulating_cond_eq_kwargs', 'regulating_control_kwargs', + 'sampled_regulating_control_mode_kind', 'rotating_machine_kwargs', 'create_series_compensator', 'series_compensator_kwargs', 'shunt_compensator_kwargs', + 'sampled_single_phase_kind', 'create_static_var_compensator', 'static_var_compensator_kwargs', 'sampled_svc_control_mode', 'switch_kwargs', + 'create_synchronous_machine', 'synchronous_machine_kwargs', 'sampled_synchronous_machine_kind', 'tap_changer_kwargs', 'create_tap_changer_control', + 'tap_changer_control_kwargs', 'transformer_end_kwargs', 'create_transformer_star_impedance', 'transformer_star_impedance_kwargs', + 'sampled_winding_connection', 'create_circuit', 'circuit_kwargs', 'sampled_wire_info', 'sampled_conducting_equipment', 'sampled_curves', + 'sampled_end_device_function', 'sampled_equipment', 'sampled_equipment_container', 'sampled_hvlv_feeder', 'sampled_measurement', + 'sampled_protected_switches' +] + +from datetime import datetime +from random import choice + +from streaming.get.pb_creators import lists, floats +from util import mrid_strategy +# @formatter:off + +# This must be above hypothesis.strategies to avoid conflicting import with zepben.ewb.util.none +from zepben.ewb import * + +from hypothesis.strategies import builds, text, integers, sampled_from, booleans, uuids, datetimes, one_of, none +from zepben.ewb.model.cim.extensions.iec61970.base.feeder.lv_substation import LvSubstation +from zepben.ewb.model.cim.iec61968.assetinfo.wire_insulation_kind import WireInsulationKind +from zepben.ewb.model.cim.iec61970.base.wires.ac_line_segment_phase import AcLineSegmentPhase + +# @formatter:on + +MIN_32_BIT_INTEGER = -2147483647 # _UNKNOWN_INT = -2147483648 +MAX_32_BIT_INTEGER = 2147483647 +MAX_32_BIT_UNSIGNED_INTEGER = 4294967294 # _UNKNOWN_UINT = 4294967295 +MAX_64_BIT_INTEGER = 9223372036854775807 +MIN_64_BIT_INTEGER = -9223372036854775807 # _UNKNOWN_LONG = -9223372036854775808 +TEXT_MAX_SIZE = 6 +FLOAT_MIN = -100.0 +FLOAT_MAX = 1000.0 +MAX_END_NUMBER = 3 +MAX_SEQUENCE_NUMBER = 40 +MIN_SEQUENCE_NUMBER = 1 +ALPHANUM = "abcdefghijbklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_" + + +################################## +# Extensions IEC61968 Asset Info # +################################## + +def create_relay_info(include_runtime: bool = True): + return builds(RelayInfo, **relay_info_kwargs(include_runtime)) + + +def relay_info_kwargs(include_runtime: bool = True): + return { + **asset_info_kwargs(include_runtime), + "curve_setting": text(alphabet=ALPHANUM, min_size=1, max_size=TEXT_MAX_SIZE), + "reclose_delays": lists(floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX)), + "reclose_fast": one_of(none(), booleans()), + } + + +############################## +# Extensions IEC61968 Common # +############################## + +def create_contact_details(): + return builds(ContactDetails, **contact_details_kwargs()) + + +def contact_details_kwargs(): + return { + "id": text(alphabet=ALPHANUM, max_size=TEXT_MAX_SIZE, min_size=1), + "contact_address": create_street_address(), + "contact_type": one_of(none(), text(alphabet=ALPHANUM, max_size=TEXT_MAX_SIZE)), + "first_name": one_of(none(), text(alphabet=ALPHANUM, max_size=TEXT_MAX_SIZE)), + "last_name": one_of(none(), text(alphabet=ALPHANUM, max_size=TEXT_MAX_SIZE)), + "preferred_contact_method": sampled_from(ContactMethodType), + "is_primary": one_of(none(), booleans()), + "business_name": one_of(none(), text(alphabet=ALPHANUM, max_size=TEXT_MAX_SIZE)), + "phone_numbers": one_of(none(), lists(create_telephone_number())), + "electronic_addresses": one_of(none(), lists(create_electronic_address())), + } + + +################################ +# Extensions IEC61968 Metering # +################################ + +def create_pan_demand_response_function(include_runtime: bool = True): + return builds(PanDemandResponseFunction, **pan_demand_response_function_kwargs(include_runtime)) + + +def pan_demand_response_function_kwargs(include_runtime: bool = True): + return { + **end_device_function_kwargs(include_runtime), + "kind": sampled_from(EndDeviceFunctionKind), + "appliances": integers(min_value=0, max_value=4095), + } + + +################################# +# Extensions IEC61970 Base Core # +################################# + +def create_hv_customer(include_runtime: bool = True): + return builds(Site, **hv_customer_kwargs(include_runtime)) + + +def hv_customer_kwargs(include_runtime: bool = True): + return { + **equipment_container_kwargs(include_runtime) + } + + +def create_site(include_runtime: bool = True): + return builds(Site, **site_kwargs(include_runtime)) + + +def site_kwargs(include_runtime: bool = True): + return { + **equipment_container_kwargs(include_runtime) + } + + +################################### +# Extensions IEC61970 Base Feeder # +################################### + +def create_loop(include_runtime: bool = True): + return builds(Loop, **loop_kwargs(include_runtime)) + + +def loop_kwargs(include_runtime: bool = True): + return { + **identified_object_kwargs(include_runtime), + "circuits": lists(builds(Circuit, **identified_object_kwargs(include_runtime)), max_size=2), + "substations": lists(builds(Substation, **identified_object_kwargs(include_runtime)), max_size=2), + "energizing_substations": lists(builds(Substation, **identified_object_kwargs(include_runtime)), max_size=2), + } + + +def create_lv_feeder(include_runtime: bool = True): + return builds(LvFeeder, **lv_feeder_kwargs(include_runtime)) + + +def lv_feeder_kwargs(include_runtime: bool = True): + runtime = { + "normal_energizing_feeders": lists(builds(Feeder, **identified_object_kwargs(include_runtime)), max_size=2), + "current_equipment": lists(sampled_equipment(include_runtime), max_size=2), + "current_energizing_feeders": lists(builds(Feeder, **identified_object_kwargs(include_runtime)), max_size=2), + "normal_energizing_lv_substation": builds(LvSubstation, **identified_object_kwargs(include_runtime)), + } if include_runtime else {} + + return { + # Only include equipment if we are processing runtime as we don't write equipment to the database for LvFeeder. + **equipment_container_kwargs(include_runtime, add_equipment=include_runtime), + "normal_head_terminal": builds(Terminal, **identified_object_kwargs(include_runtime)), + **runtime, + } + + +def create_lv_substation(include_runtime: bool = True): + return builds(LvSubstation, **lv_substation_kwargs(include_runtime)) + + +def lv_substation_kwargs(include_runtime: bool = True): + runtime = { + "normal_energizing_feeders": one_of(none(), lists(builds(Feeder, **identified_object_kwargs(include_runtime)), max_size=2)), + "current_energizing_feeders": one_of(none(), lists(builds(Feeder, **identified_object_kwargs(include_runtime)), max_size=2)), + "normal_energized_lv_feeders": one_of(none(), lists(builds(LvFeeder, **identified_object_kwargs(include_runtime)))), + } if include_runtime else {} + + return { + **equipment_container_kwargs(include_runtime, add_equipment=include_runtime), + **runtime, + } + + +################################################## +# Extensions IEC61970 Base Generation Production # +################################################## + +def create_ev_charging_unit(include_runtime: bool = True): + return builds(EvChargingUnit, **ev_charging_unit_kwargs(include_runtime)) + + +def ev_charging_unit_kwargs(include_runtime: bool = True): + return { + **power_electronics_unit_kwargs(include_runtime) + } + + +####################################### +# Extensions IEC61970 Base Protection # +####################################### + +def create_directional_current_relay(include_runtime: bool = True): + return builds(DirectionalCurrentRelay, **directional_current_relay_kwargs(include_runtime)) + + +def directional_current_relay_kwargs(include_runtime: bool = True): + return { + **protection_relay_function_kwargs(include_runtime), + "directional_characteristic_angle": one_of(none(), floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX)), + "polarizing_quantity_type": sampled_from(PolarizingQuantityType), + "relay_element_phase": sampled_from(PhaseCode), + "minimum_pickup_current": one_of(none(), floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX)), + "current_limit_1": one_of(none(), floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX)), + "inverse_time_flag": one_of(none(), booleans()), + "time_delay_1": one_of(none(), floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX)), + } + + +def create_distance_relay(include_runtime: bool = True): + return builds(DistanceRelay, **distance_relay_kwargs(include_runtime)) + + +def distance_relay_kwargs(include_runtime: bool = True): + return { + **protection_relay_function_kwargs(include_runtime), + "backward_blind": one_of(none(), floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX)), + "backward_reach": one_of(none(), floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX)), + "backward_reactance": one_of(none(), floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX)), + "forward_blind": one_of(none(), floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX)), + "forward_reach": one_of(none(), floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX)), + "forward_reactance": one_of(none(), floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX)), + "operation_phase_angle1": one_of(none(), floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX)), + "operation_phase_angle2": one_of(none(), floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX)), + "operation_phase_angle3": one_of(none(), floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX)), + } + + +def sampled_power_direction_kind(): + return sampled_from(PowerDirectionKind) + + +def sampled_protection_kind(): + return sampled_from(ProtectionKind) + + +def protection_relay_function_kwargs(include_runtime: bool = True): + return { + **power_system_resource_kwargs(include_runtime), + "model": text(alphabet=ALPHANUM, min_size=1, max_size=TEXT_MAX_SIZE), + "reclosing": one_of(none(), booleans()), + "relay_delay_time": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + "protection_kind": sampled_protection_kind(), + "directable": one_of(none(), booleans()), + "power_direction": sampled_power_direction_kind(), + "sensors": lists(builds(CurrentTransformer, mrid=mrid_strategy), max_size=2), + "protected_switches": lists(builds(Breaker, mrid=mrid_strategy), max_size=2), + "schemes": lists(builds(ProtectionRelayScheme, mrid=mrid_strategy), max_size=2), + "time_limits": lists(floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), min_size=4, max_size=4), + "thresholds": lists(create_relay_setting(), min_size=4, max_size=4), + "relay_info": builds(RelayInfo, mrid=mrid_strategy), + } + + +def create_protection_relay_scheme(include_runtime: bool = True): + return builds(ProtectionRelayScheme, **protection_relay_scheme_kwargs(include_runtime)) + + +def protection_relay_scheme_kwargs(include_runtime: bool = True): + return { + **identified_object_kwargs(include_runtime), + "system": builds(ProtectionRelaySystem, mrid=mrid_strategy), + "functions": lists(builds(CurrentRelay, mrid=mrid_strategy)), + } + + +def create_protection_relay_system(include_runtime: bool = True): + return builds(ProtectionRelaySystem, **protection_relay_system_kwargs(include_runtime)) + + +def protection_relay_system_kwargs(include_runtime: bool = True): + return { + **equipment_kwargs(include_runtime), + "protection_kind": sampled_protection_kind(), + "schemes": lists(builds(ProtectionRelayScheme, mrid=mrid_strategy)), + } + + +def create_relay_setting(): + return builds(RelaySetting, **relay_setting_kwargs()) + + +def relay_setting_kwargs(): + return { + "unit_symbol": sampled_unit_symbol(), + "value": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + "name": text(alphabet=ALPHANUM, max_size=TEXT_MAX_SIZE), + } + + +def create_voltage_relay(include_runtime: bool = True): + return builds(VoltageRelay, **voltage_relay_kwargs(include_runtime)) + + +def voltage_relay_kwargs(include_runtime: bool = True): + return { + **protection_relay_function_kwargs(include_runtime), + } + + +################################## +# Extensions IEC61970 Base Wires # +################################## + +def create_battery_control(include_runtime: bool = True): + return builds(BatteryControl, **battery_control_kwargs(include_runtime)) + + +def battery_control_kwargs(include_runtime: bool = True): + return { + **regulating_control_kwargs(include_runtime), + "charging_rate": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + "discharging_rate": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + "reserve_percent": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + "control_mode": sampled_battery_control_mode(), + } + + +def sampled_battery_control_mode(): + return sampled_from(BatteryControlMode) + + +def sampled_transformer_cooling_type(): + return sampled_from(TransformerCoolingType) + + +def create_power_transformer_end_with_ratings(ratings: List[TransformerEndRatedS], **kwargs): + # This is needed as we purposely made it so you can't build a transformer end with multiple ratings through constructor + pte = PowerTransformerEnd(**kwargs) + if ratings: + for rating in ratings: + pte.add_transformer_end_rated_s(rating) + return pte + + +def sampled_vector_group(): + return sampled_from(VectorGroup) + + +####################### +# IEC61968 Asset Info # +####################### + + +def create_cable_info(include_runtime: bool = True): + return builds(CableInfo, **cable_info_kwargs(include_runtime)) + + +def cable_info_kwargs(include_runtime: bool = True): + return { + **wire_info_kwargs(include_runtime) + } + + +def create_no_load_test(include_runtime: bool = True): + return builds(NoLoadTest, **no_load_test_kwargs(include_runtime)) + + +def no_load_test_kwargs(include_runtime: bool = True): + return { + **transformer_test_kwargs(include_runtime), + "energised_end_voltage": integers(min_value=MIN_32_BIT_INTEGER, max_value=MAX_32_BIT_INTEGER), + "exciting_current": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + "exciting_current_zero": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + "loss": integers(min_value=MIN_32_BIT_INTEGER, max_value=MAX_32_BIT_INTEGER), + "loss_zero": integers(min_value=MIN_32_BIT_INTEGER, max_value=MAX_32_BIT_INTEGER), + } + + +def create_open_circuit_test(include_runtime: bool = True): + return builds(OpenCircuitTest, **open_circuit_test_kwargs(include_runtime)) + + +def open_circuit_test_kwargs(include_runtime: bool = True): + return { + **transformer_test_kwargs(include_runtime), + "energised_end_step": integers(min_value=MIN_32_BIT_INTEGER, max_value=MAX_32_BIT_INTEGER), + "energised_end_voltage": integers(min_value=MIN_32_BIT_INTEGER, max_value=MAX_32_BIT_INTEGER), + "open_end_step": integers(min_value=MIN_32_BIT_INTEGER, max_value=MAX_32_BIT_INTEGER), + "open_end_voltage": integers(min_value=MIN_32_BIT_INTEGER, max_value=MAX_32_BIT_INTEGER), + "phase_shift": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + } + + +def create_overhead_wire_info(include_runtime: bool = True): + return builds(OverheadWireInfo, **overhead_wire_info_kwargs(include_runtime)) + + +def overhead_wire_info_kwargs(include_runtime: bool = True): + return { + **wire_info_kwargs(include_runtime) + } + + +def create_power_transformer_info(include_runtime: bool = True): + return builds(PowerTransformerInfo, **power_transformer_info_kwargs(include_runtime)) + + +def power_transformer_info_kwargs(include_runtime: bool = True): + return { + **asset_info_kwargs(include_runtime), + "transformer_tank_infos": lists(builds(TransformerTankInfo, **identified_object_kwargs(include_runtime)), max_size=2), + } + + +def create_short_circuit_test(include_runtime: bool = True): + return builds(ShortCircuitTest, **short_circuit_test_kwargs(include_runtime)) + + +def short_circuit_test_kwargs(include_runtime: bool = True): + return { + **transformer_test_kwargs(include_runtime), + "current": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + "energised_end_step": integers(min_value=MIN_32_BIT_INTEGER, max_value=MAX_32_BIT_INTEGER), + "grounded_end_step": integers(min_value=MIN_32_BIT_INTEGER, max_value=MAX_32_BIT_INTEGER), + "leakage_impedance": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + "leakage_impedance_zero": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + "loss": integers(min_value=MIN_32_BIT_INTEGER, max_value=MAX_32_BIT_INTEGER), + "loss_zero": integers(min_value=MIN_32_BIT_INTEGER, max_value=MAX_32_BIT_INTEGER), + "power": integers(min_value=MIN_32_BIT_INTEGER, max_value=MAX_32_BIT_INTEGER), + "voltage": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + "voltage_ohmic_part": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + } + + +def create_shunt_compensator_info(include_runtime: bool = True): + return builds(ShuntCompensatorInfo, **shunt_compensator_info_kwargs(include_runtime)) + + +def shunt_compensator_info_kwargs(include_runtime: bool = True): + return { + **asset_info_kwargs(include_runtime), + "max_power_loss": integers(min_value=MIN_32_BIT_INTEGER, max_value=MAX_32_BIT_INTEGER), + "rated_current": integers(min_value=MIN_32_BIT_INTEGER, max_value=MAX_32_BIT_INTEGER), + "rated_reactive_power": integers(min_value=MIN_32_BIT_INTEGER, max_value=MAX_32_BIT_INTEGER), + "rated_voltage": integers(min_value=MIN_32_BIT_INTEGER, max_value=MAX_32_BIT_INTEGER), + } + + +def create_switch_info(include_runtime: bool = True): + return builds(SwitchInfo, **switch_info_kwargs(include_runtime)) + + +def switch_info_kwargs(include_runtime: bool = True): + return { + **asset_info_kwargs(include_runtime), + "rated_interrupting_time": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + } + + +def create_transformer_end_info(include_runtime: bool = True): + return builds(TransformerEndInfo, **transformer_end_info_kwargs(include_runtime)) + + +def transformer_end_info_kwargs(include_runtime: bool = True): + return { + **asset_info_kwargs(include_runtime), + "connection_kind": sampled_winding_connection(), + "emergency_s": integers(min_value=MIN_32_BIT_INTEGER, max_value=MAX_32_BIT_INTEGER), + "end_number": integers(min_value=MIN_32_BIT_INTEGER, max_value=MAX_32_BIT_INTEGER), + "insulation_u": integers(min_value=MIN_32_BIT_INTEGER, max_value=MAX_32_BIT_INTEGER), + "phase_angle_clock": integers(min_value=MIN_32_BIT_INTEGER, max_value=MAX_32_BIT_INTEGER), + "r": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + "rated_s": integers(min_value=MIN_32_BIT_INTEGER, max_value=MAX_32_BIT_INTEGER), + "rated_u": integers(min_value=MIN_32_BIT_INTEGER, max_value=MAX_32_BIT_INTEGER), + "short_term_s": integers(min_value=MIN_32_BIT_INTEGER, max_value=MAX_32_BIT_INTEGER), + "transformer_tank_info": builds(TransformerTankInfo, **identified_object_kwargs(include_runtime)), + "transformer_star_impedance": builds(TransformerStarImpedance, **identified_object_kwargs(include_runtime)), + "energised_end_no_load_tests": builds(NoLoadTest, **identified_object_kwargs(include_runtime)), + "energised_end_short_circuit_tests": builds(ShortCircuitTest, **identified_object_kwargs(include_runtime)), + "grounded_end_short_circuit_tests": builds(ShortCircuitTest, **identified_object_kwargs(include_runtime)), + "open_end_open_circuit_tests": builds(OpenCircuitTest, **identified_object_kwargs(include_runtime)), + "energised_end_open_circuit_tests": builds(OpenCircuitTest, **identified_object_kwargs(include_runtime)), + } + + +def create_transformer_tank_info(include_runtime: bool = True): + return builds(TransformerTankInfo, **transformer_tank_info_kwargs(include_runtime)) + + +def transformer_tank_info_kwargs(include_runtime: bool = True): + return { + **asset_info_kwargs(include_runtime), + "power_transformer_info": builds(PowerTransformerInfo, **identified_object_kwargs(include_runtime)), + "transformer_end_infos": lists(builds(TransformerEndInfo, **identified_object_kwargs(include_runtime)), max_size=2), + } + + +def transformer_test_kwargs(include_runtime: bool): + return { + **identified_object_kwargs(include_runtime), + "base_power": integers(min_value=MIN_32_BIT_INTEGER, max_value=MAX_32_BIT_INTEGER), + "temperature": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + } + + +def wire_info_kwargs(include_runtime: bool): + return { + **asset_info_kwargs(include_runtime), + "rated_current": integers(min_value=MIN_32_BIT_INTEGER, max_value=MAX_32_BIT_INTEGER), + "material": sampled_wire_material_kind(), + "size_description": one_of(none(), text(alphabet=ALPHANUM)), + "strand_count": one_of(none(), text(alphabet=ALPHANUM)), + "core_strand_count": one_of(none(), text(alphabet=ALPHANUM)), + "insulated": booleans(), + "insulation_material": sampled_wire_insulation_kind(), + "insulation_thickness": one_of(none(), floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX)), + } + + +def sampled_wire_material_kind(): + return sampled_from(WireMaterialKind) + + +def sampled_wire_insulation_kind(): + return sampled_from(WireInsulationKind) + + +################### +# IEC61968 Assets # +################### + + +def asset_kwargs(include_runtime: bool): + return { + **identified_object_kwargs(include_runtime), + "location": builds(Location, **identified_object_kwargs(include_runtime)), + "organisation_roles": lists(builds(AssetOwner, **identified_object_kwargs(include_runtime)), max_size=2), + "power_system_resources": lists(builds(Junction, **identified_object_kwargs(include_runtime)), max_size=2), + } + + +def asset_container_kwargs(include_runtime: bool): + return { + **asset_kwargs(include_runtime) + } + + +def asset_function_kwargs(include_runtime: bool): + return { + **identified_object_kwargs(include_runtime) + } + + +def asset_info_kwargs(include_runtime: bool): + return { + **identified_object_kwargs(include_runtime) + } + + +def asset_organisation_role_kwargs(include_runtime: bool): + return { + **organisation_role_kwargs(include_runtime) + } + + +def create_asset_owner(include_runtime: bool = True): + return builds(AssetOwner, **asset_owner_kwargs(include_runtime)) + + +def asset_owner_kwargs(include_runtime: bool = True): + return { + **asset_organisation_role_kwargs(include_runtime) + } + + +def create_streetlight(include_runtime: bool = True): + return builds(Streetlight, **streetlight_kwargs(include_runtime)) + + +def streetlight_kwargs(include_runtime: bool = True): + return { + **asset_kwargs(include_runtime), + "pole": builds(Pole, **identified_object_kwargs(include_runtime)), + "light_rating": integers(min_value=0, max_value=MAX_32_BIT_INTEGER), + # Capping unsigned int to 32-bit int range to avoid issues with Python 3.7 testing. + "lamp_kind": sampled_streetlight_lamp_kind(), + } + + +def structure_kwargs(include_runtime: bool): + return { + **asset_container_kwargs(include_runtime) + } + + +################### +# IEC61968 Common # +################### + + +def agreement_kwargs(include_runtime: bool): + return { + **document_kwargs(include_runtime) + } + + +def document_kwargs(include_runtime: bool): + return { + **identified_object_kwargs(include_runtime), + "title": text(alphabet=ALPHANUM, max_size=TEXT_MAX_SIZE), + "created_date_time": datetimes(min_value=datetime(1970, 1, 2)), + "author_name": text(alphabet=ALPHANUM, max_size=TEXT_MAX_SIZE), + "type": text(alphabet=ALPHANUM, max_size=TEXT_MAX_SIZE), + "status": text(alphabet=ALPHANUM, max_size=TEXT_MAX_SIZE), + "comment": text(alphabet=ALPHANUM, max_size=TEXT_MAX_SIZE), + } + + +def create_electronic_address(): + return builds(ElectronicAddress, **electronic_address_kwargs()) + + +def electronic_address_kwargs(): + return { + "email1": one_of(none(), text(alphabet=ALPHANUM, max_size=TEXT_MAX_SIZE)), + "is_primary": one_of(none(), booleans()), + "description": one_of(none(), text(alphabet=ALPHANUM, max_size=TEXT_MAX_SIZE)), + } + + +def create_location(include_runtime: bool = True): + return builds(Location, **location_kwargs(include_runtime)) + + +def location_kwargs(include_runtime: bool = True): + return { + **identified_object_kwargs(include_runtime), + "main_address": create_street_address(), + "position_points": lists(create_position_point(), max_size=4), + } + + +def create_organisation(include_runtime: bool = True): + return builds(Organisation, **organisation_kwargs(include_runtime)) + + +def organisation_kwargs(include_runtime: bool = True): + return { + **identified_object_kwargs(include_runtime) + } + + +def organisation_role_kwargs(include_runtime: bool): + return { + **identified_object_kwargs(include_runtime), + "organisation": builds(Organisation, **identified_object_kwargs(include_runtime)), + } + + +def create_position_point(): + return builds(PositionPoint, **position_point_kwargs()) + + +def position_point_kwargs(): + return { + "x_position": floats(min_value=-180.0, max_value=180.0), + "y_position": floats(min_value=-90.0, max_value=90.0), + } + + +def create_street_address(): + return builds(StreetAddress, **street_address_kwargs()) + + +def street_address_kwargs(): + return { + "postal_code": one_of(none(), text(alphabet=ALPHANUM, max_size=TEXT_MAX_SIZE)), + "town_detail": create_town_detail(), + "po_box": one_of(none(), text(alphabet=ALPHANUM, max_size=TEXT_MAX_SIZE)), + "street_detail": create_street_detail(), + } + + +def create_street_detail(): + return builds(StreetDetail, **street_detail_kwargs()) + + +def street_detail_kwargs(): + return { + "building_name": text(alphabet=ALPHANUM, max_size=TEXT_MAX_SIZE), + "floor_identification": one_of(none(), text(alphabet=ALPHANUM, max_size=TEXT_MAX_SIZE)), + "name": one_of(none(), text(alphabet=ALPHANUM, max_size=TEXT_MAX_SIZE)), + "number": one_of(none(), text(alphabet=ALPHANUM, max_size=TEXT_MAX_SIZE)), + "suite_number": one_of(none(), text(alphabet=ALPHANUM, max_size=TEXT_MAX_SIZE)), + "type": one_of(none(), text(alphabet=ALPHANUM, max_size=TEXT_MAX_SIZE)), + "display_address": one_of(none(), text(alphabet=ALPHANUM, max_size=TEXT_MAX_SIZE)), + "building_number": one_of(none(), text(alphabet=ALPHANUM, max_size=TEXT_MAX_SIZE)), + } + + +def create_telephone_number(): + return builds(TelephoneNumber, **telephone_number_kwargs()) + + +def telephone_number_kwargs(): + return { + "area_code": text(alphabet=ALPHANUM, max_size=3), + "city_code": one_of(none(), text(alphabet=ALPHANUM, max_size=2)), + "dial_out": one_of(none(), text(alphabet=ALPHANUM, max_size=3)), + "extension": one_of(none(), text(alphabet=ALPHANUM, max_size=4)), + "international_prefix": one_of(none(), text(alphabet=ALPHANUM, max_size=TEXT_MAX_SIZE)), + "local_number": one_of(none(), text(alphabet=ALPHANUM, max_size=8)), + "is_primary": one_of(none(), booleans()), + "description": one_of(none(), text(alphabet=ALPHANUM, max_size=TEXT_MAX_SIZE)), + } + + +def create_town_detail(): + return builds(TownDetail, **town_detail_kwargs()) + + +def town_detail_kwargs(): + return { + "name": text(alphabet=ALPHANUM, max_size=TEXT_MAX_SIZE), + "state_or_province": one_of(none(), text(alphabet=ALPHANUM, max_size=TEXT_MAX_SIZE)), + "country": one_of(none(), text(alphabet=ALPHANUM, max_size=TEXT_MAX_SIZE)), + } + + +###################### +# IEC61968 Customers # +###################### + + +def create_customer(include_runtime: bool = True): + return builds(Customer, **customer_kwargs(include_runtime)) + + +def customer_kwargs(include_runtime: bool = True): + return { + **organisation_role_kwargs(include_runtime), + "kind": sampled_customer_kind(), + # We can't use blank strings as it breaks some of the tests due to protobuf conversions dropping the blanks for None. + "special_need": text(alphabet=ALPHANUM, min_size=1, max_size=TEXT_MAX_SIZE), + "customer_agreements": lists(builds(CustomerAgreement, **identified_object_kwargs(include_runtime)), max_size=2), + } + + +def create_customer_agreement(include_runtime: bool = True): + return builds(CustomerAgreement, **customer_agreement_kwargs(include_runtime)) + + +def customer_agreement_kwargs(include_runtime: bool = True): + return { + **agreement_kwargs(include_runtime), + "customer": builds(Customer, **identified_object_kwargs(include_runtime)), + "pricing_structures": lists(builds(PricingStructure, **identified_object_kwargs(include_runtime)), max_size=2), + } + + +def sampled_customer_kind(): + return sampled_from(CustomerKind) + + +def create_pricing_structure(include_runtime: bool = True): + return builds(PricingStructure, **pricing_structure_kwargs(include_runtime)) + + +def pricing_structure_kwargs(include_runtime: bool = True): + return { + **document_kwargs(include_runtime), + "tariffs": lists(builds(Tariff, **identified_object_kwargs(include_runtime)), max_size=2), + } + + +def create_tariffs(include_runtime: bool = True): + return builds(Tariff, **tariffs_kwargs(include_runtime)) + + +def tariffs_kwargs(include_runtime: bool = True): + return { + **document_kwargs(include_runtime) + } + + +##################################### +# IEC61968 InfIEC61968 InfAssetInfo # +##################################### + +def create_current_transformer_info(include_runtime: bool = True): + return builds(CurrentTransformerInfo, **current_transformer_info_kwargs(include_runtime)) + + +def current_transformer_info_kwargs(include_runtime: bool = True): + return { + **asset_info_kwargs(include_runtime), + "accuracy_class": text(alphabet=ALPHANUM, min_size=1, max_size=TEXT_MAX_SIZE), + "accuracy_limit": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + "core_count": integers(min_value=MIN_32_BIT_INTEGER, max_value=MAX_32_BIT_INTEGER), + "ct_class": text(alphabet=ALPHANUM, min_size=1, max_size=TEXT_MAX_SIZE), + "knee_point_voltage": integers(min_value=MIN_32_BIT_INTEGER, max_value=MAX_32_BIT_INTEGER), + "max_ratio": create_ratio(), + "nominal_ratio": create_ratio(), + "primary_ratio": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + "rated_current": integers(min_value=MIN_32_BIT_INTEGER, max_value=MAX_32_BIT_INTEGER), + "secondary_fls_rating": integers(min_value=MIN_32_BIT_INTEGER, max_value=MAX_32_BIT_INTEGER), + "secondary_ratio": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + "usage": text(alphabet=ALPHANUM, min_size=1, max_size=TEXT_MAX_SIZE), + } + + +def create_potential_transformer_info(include_runtime: bool = True): + return builds(PotentialTransformerInfo, **potential_transformer_info_kwargs(include_runtime)) + + +def potential_transformer_info_kwargs(include_runtime: bool = True): + return { + **asset_info_kwargs(include_runtime), + "accuracy_class": text(alphabet=ALPHANUM, min_size=1, max_size=TEXT_MAX_SIZE), + "nominal_ratio": create_ratio(), + "primary_ratio": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + "pt_class": text(alphabet=ALPHANUM, min_size=1, max_size=TEXT_MAX_SIZE), + "rated_voltage": integers(min_value=MIN_32_BIT_INTEGER, max_value=MAX_32_BIT_INTEGER), + "secondary_ratio": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + } + + +def sampled_transformer_construction_kind(): + return sampled_from(TransformerConstructionKind) + + +def sampled_transformer_function_kind(): + return sampled_from(TransformerFunctionKind) + + +################################## +# IEC61968 InfIEC61968 InfAssets # +################################## + + +def create_pole(include_runtime: bool = True): + return builds(Pole, **pole_kwargs(include_runtime)) + + +def pole_kwargs(include_runtime: bool = True): + return { + **structure_kwargs(include_runtime), + "streetlights": lists(builds(Streetlight, **identified_object_kwargs(include_runtime)), max_size=2), + "classification": text(alphabet=ALPHANUM, max_size=TEXT_MAX_SIZE), + } + + +def sampled_streetlight_lamp_kind(): + return sampled_from(StreetlightLampKind) + + +################################## +# IEC61968 InfIEC61968 InfCommon # +################################## + + +def create_ratio(): + return builds(Ratio, **ratio_kwargs()) + + +def ratio_kwargs(): + return { + "numerator": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + "denominator": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + } + + +##################### +# IEC61968 Metering # +##################### + + +def create_controlled_appliance(): + return builds(ControlledAppliance, **controlled_appliance_kwargs()) + + +def controlled_appliance_kwargs(): + return { + "appliances": sampled_from(Appliance), + } + + +def end_device_kwargs(include_runtime: bool): + return { + **asset_container_kwargs(include_runtime), + "usage_points": lists(builds(UsagePoint, **identified_object_kwargs(include_runtime)), max_size=2), + "customer_mrid": text(alphabet=ALPHANUM, min_size=1, max_size=TEXT_MAX_SIZE), + "service_location": builds(Location, **identified_object_kwargs(include_runtime)), + "functions": lists(sampled_end_device_function(include_runtime), max_size=2), + } + + +def end_device_function_kwargs(include_runtime: bool): + return { + **asset_function_kwargs(include_runtime), + "enabled": booleans(), + } + + +def sampled_end_device_function_kind(): + return sampled_from(EndDeviceFunctionKind) + + +def create_meter(include_runtime: bool = True): + return builds(Meter, **meter_kwargs(include_runtime)) + + +def meter_kwargs(include_runtime: bool = True): + return { + **end_device_kwargs(include_runtime) + } + + +def create_usage_point(include_runtime: bool = True): + return builds(UsagePoint, **usage_point_kwargs(include_runtime)) + + +def usage_point_kwargs(include_runtime: bool = True): + return { + **identified_object_kwargs(include_runtime), + "usage_point_location": builds(Location, **identified_object_kwargs(include_runtime)), + "is_virtual": booleans(), + "connection_category": text(alphabet=ALPHANUM, min_size=2, max_size=TEXT_MAX_SIZE), + "rated_power": integers(min_value=MIN_32_BIT_INTEGER, max_value=MAX_32_BIT_INTEGER), + "approved_inverter_capacity": integers(min_value=MIN_32_BIT_INTEGER, max_value=MAX_32_BIT_INTEGER), + "equipment": lists(builds(EnergyConsumer, **identified_object_kwargs(include_runtime)), max_size=2), + "end_devices": lists(builds(Meter, **identified_object_kwargs(include_runtime)), max_size=2), + "contacts": lists(create_contact_details(), max_size=2), + } + + +####################### +# IEC61968 Operations # +####################### + + +def create_operational_restriction(include_runtime: bool = True): + return builds(OperationalRestriction, **operational_restriction_kwargs(include_runtime)) + + +def operational_restriction_kwargs(include_runtime: bool = True): + return { + **document_kwargs(include_runtime), + "equipment": lists(builds(PowerTransformer, **identified_object_kwargs(include_runtime)), max_size=2), + } + + +##################################### +# IEC61970 Base Auxiliary Equipment # +##################################### + +def auxiliary_equipment_kwargs(include_runtime: bool): + return { + **equipment_kwargs(include_runtime), + "terminal": builds(Terminal, **identified_object_kwargs(include_runtime)), + } + + +def create_current_transformer(include_runtime: bool = True): + return builds(CurrentTransformer, **current_transformer_kwargs(include_runtime)) + + +def current_transformer_kwargs(include_runtime: bool = True): + return { + **sensor_kwargs(include_runtime), + "asset_info": builds(CurrentTransformerInfo, **identified_object_kwargs(include_runtime)), + "core_burden": integers(min_value=MIN_32_BIT_INTEGER, max_value=MAX_32_BIT_INTEGER), + } + + +def create_fault_indicator(include_runtime: bool = True): + return builds(FaultIndicator, **fault_indicator_kwargs(include_runtime)) + + +def fault_indicator_kwargs(include_runtime: bool = True): + return { + **auxiliary_equipment_kwargs(include_runtime) + } + + +def create_potential_transformer(include_runtime: bool = True): + return builds(PotentialTransformer, **potential_transformer_kwargs(include_runtime)) + + +def potential_transformer_kwargs(include_runtime: bool = True): + return { + **sensor_kwargs(include_runtime), + "asset_info": builds(PotentialTransformerInfo, **identified_object_kwargs(include_runtime)), + "type": sampled_from(PotentialTransformerKind), + } + + +def sampled_potential_transformer_kind(): + return sampled_from(PotentialTransformerKind) + + +def sensor_kwargs(include_runtime: bool = True): + return { + **auxiliary_equipment_kwargs(include_runtime), + "relay_functions": lists(builds(CurrentRelay, mrid=mrid_strategy), max_size=10), + } + + +###################### +# IEC61970 Base Core # +###################### + + +def ac_dc_terminal_kwargs(include_runtime: bool): + return { + **identified_object_kwargs(include_runtime) + } + + +def create_base_voltage(include_runtime: bool = True): + return builds(BaseVoltage, **base_voltage_kwargs(include_runtime)) + + +def base_voltage_kwargs(include_runtime: bool = True): + return { + **identified_object_kwargs(include_runtime), + "nominal_voltage": integers(min_value=MIN_32_BIT_INTEGER, max_value=MAX_32_BIT_INTEGER), + } + + +def conducting_equipment_kwargs(include_runtime: bool): + return { + **equipment_kwargs(include_runtime), + "base_voltage": builds(BaseVoltage, **identified_object_kwargs(include_runtime)), + "terminals": lists(builds(Terminal, **identified_object_kwargs(include_runtime)), max_size=3), + } + + +def create_connectivity_node(include_runtime: bool = True): + return builds(ConnectivityNode, **connectivity_node_kwargs(include_runtime)) + + +def connectivity_node_kwargs(include_runtime: bool = True): + return { + **identified_object_kwargs(include_runtime), + "terminals": lists(builds(Terminal, **identified_object_kwargs(include_runtime)), max_size=10), + } + + +def connectivity_node_container_kwargs(include_runtime: bool): + return { + **power_system_resource_kwargs(include_runtime) + } + + +def curve_kwargs(include_runtime: bool): + return { + **identified_object_kwargs(include_runtime), + "data": lists(create_curve_data(), max_size=4, unique_by=lambda it: it.x_value), + } + + +def create_curve_data(): + return builds(CurveData, **curve_data_kwargs()) + + +def curve_data_kwargs(): + return { + "x_value": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + "y1_value": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + "y2_value": one_of(none(), floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX)), + "y3_value": one_of(none(), floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX)), + } + + +def equipment_kwargs(include_runtime: bool): + runtime = { + "current_containers": lists(sampled_hvlv_feeder(include_runtime), max_size=2), + } if include_runtime else {} + + return { + **power_system_resource_kwargs(include_runtime), + "in_service": booleans(), + "normally_in_service": booleans(), + "equipment_containers": lists(sampled_equipment_container(include_runtime), max_size=2), + "usage_points": lists(builds(UsagePoint, **identified_object_kwargs(include_runtime)), max_size=2), + "operational_restrictions": lists(builds(OperationalRestriction, **identified_object_kwargs(include_runtime)), max_size=2), + "commissioned_date": datetimes(min_value=datetime(1970, 1, 2)), + **runtime, + } + + +def equipment_container_kwargs(include_runtime: bool, add_equipment: bool = True): + equipment = { + "equipment": lists(sampled_equipment(include_runtime), max_size=30), + } if add_equipment else {} + + return { + **connectivity_node_container_kwargs(include_runtime), + **equipment + } + + +def create_feeder(include_runtime: bool = True): + return builds(Feeder, **feeder_kwargs(include_runtime)) + + +def feeder_kwargs(include_runtime: bool = True): + runtime = { + "normal_energized_lv_feeders": lists(builds(LvFeeder, **identified_object_kwargs(include_runtime)), max_size=2), + "current_energized_lv_feeders": lists(builds(LvFeeder, **identified_object_kwargs(include_runtime)), max_size=2), + "normal_energized_lv_substations": lists(builds(LvSubstation, **identified_object_kwargs(include_runtime)), max_size=2), + "current_energized_lv_substations": lists(builds(LvSubstation, **identified_object_kwargs(include_runtime)), max_size=2), + "current_equipment": lists(sampled_equipment(include_runtime), max_size=2), + } if include_runtime else {} + + return { + # Only include equipment if we are processing runtime as we don't write equipment to the database for Feeder. + **equipment_container_kwargs(include_runtime, add_equipment=include_runtime), + "normal_head_terminal": builds(Terminal, **identified_object_kwargs(include_runtime)), + "normal_energizing_substation": builds(Substation, **identified_object_kwargs(include_runtime)), + **runtime, + } + + +def create_geographical_region(include_runtime: bool = True): + return builds(GeographicalRegion, **geographical_region_kwargs(include_runtime)) + + +def geographical_region_kwargs(include_runtime: bool = True): + return { + **identified_object_kwargs(include_runtime), + "sub_geographical_regions": lists(builds(SubGeographicalRegion, **identified_object_kwargs(include_runtime)), max_size=2), + } + + +# noinspection PyUnusedLocal +def identified_object_kwargs(include_runtime: bool): + return { + "mrid": uuids(version=4).map(lambda x: str(x)), + "name": one_of(none(), text(alphabet=ALPHANUM, max_size=TEXT_MAX_SIZE)), + "description": one_of(none(), text(alphabet=ALPHANUM, max_size=TEXT_MAX_SIZE)), + "names": one_of( + none(), + lists(builds(Name, name=text(alphabet=ALPHANUM, max_size=TEXT_MAX_SIZE), type=create_name_type()), max_size=2, + unique_by=lambda it: it.name) + ), + } + + +def create_name(include_runtime: bool = True): + return builds(Name, **name_kwargs(include_runtime)) + + +def name_kwargs(include_runtime: bool = True): + return { + "name": text(alphabet=ALPHANUM, max_size=TEXT_MAX_SIZE), + "type": create_name_type(), + "identified_object": sampled_equipment(include_runtime), + } + + +def create_name_type(): + return builds(NameType, **name_type_kwargs()) + + +def name_type_kwargs(): + return { + "name": text(alphabet=ALPHANUM, max_size=TEXT_MAX_SIZE), + "description": text(alphabet=ALPHANUM, max_size=TEXT_MAX_SIZE), + } + + +def sampled_phase_code(): + return sampled_from(PhaseCode) + + +def power_system_resource_kwargs(include_runtime: bool): + # + # NOTE: We do not create the asset_info here, create it where it is actually used. + # + return { + **identified_object_kwargs(include_runtime), + "location": create_location(), + "num_controls": integers(min_value=0, max_value=MAX_64_BIT_INTEGER), + "assets": lists(builds(Pole, **identified_object_kwargs(include_runtime)), max_size=2), + } + + +def create_sub_geographical_region(include_runtime: bool = True): + return builds(SubGeographicalRegion, **sub_geographical_region_kwargs(include_runtime)) + + +def sub_geographical_region_kwargs(include_runtime: bool = True): + return { + **identified_object_kwargs(include_runtime), + "geographical_region": builds(GeographicalRegion, **identified_object_kwargs(include_runtime)), + "substations": lists(builds(Substation, **identified_object_kwargs(include_runtime)), max_size=2), + } + + +def create_substation(include_runtime: bool = True): + return builds(Substation, **substation_kwargs(include_runtime)) + + +def substation_kwargs(include_runtime: bool = True): + return { + **equipment_container_kwargs(include_runtime), + "sub_geographical_region": builds(SubGeographicalRegion, **identified_object_kwargs(include_runtime)), + "normal_energized_feeders": lists(builds(Feeder, **identified_object_kwargs(include_runtime)), max_size=2), + "loops": lists(builds(Loop, **identified_object_kwargs(include_runtime)), max_size=2), + "energized_loops": lists(builds(Loop, **identified_object_kwargs(include_runtime)), max_size=2), + "circuits": lists(builds(Circuit, **identified_object_kwargs(include_runtime)), max_size=2), + } + + +def create_terminal(include_runtime: bool = True): + return builds(Terminal, **terminal_kwargs(include_runtime)) + + +def terminal_kwargs(include_runtime: bool = True): + return { + **ac_dc_terminal_kwargs(include_runtime), + "conducting_equipment": sampled_conducting_equipment(include_runtime), + "connectivity_node": builds(ConnectivityNode, **identified_object_kwargs(include_runtime)), + "phases": sampled_phase_code(), + "sequence_number": integers(min_value=MIN_SEQUENCE_NUMBER, max_value=MAX_SEQUENCE_NUMBER), + } + + +################################ +# IEC61970 Base Diagram Layout # +################################ + + +def create_diagram(include_runtime: bool = True): + return builds(Diagram, **diagram_kwargs(include_runtime)) + + +def diagram_kwargs(include_runtime: bool = True): + return { + **identified_object_kwargs(include_runtime), + "diagram_style": sampled_diagram_style(), + "orientation_kind": sampled_orientation_kind(), + "diagram_objects": lists(builds(DiagramObject, **identified_object_kwargs(include_runtime)), max_size=2), + } + + +def create_diagram_object(include_runtime: bool = True): + return builds(DiagramObject, **diagram_object_kwargs(include_runtime)) + + +def diagram_object_kwargs(include_runtime: bool = True): + return { + **identified_object_kwargs(include_runtime), + "diagram": builds(Diagram, **identified_object_kwargs(include_runtime)), + "identified_object_mrid": text(alphabet=ALPHANUM, min_size=1, max_size=TEXT_MAX_SIZE), + "style": text(alphabet=ALPHANUM, min_size=1, max_size=TEXT_MAX_SIZE), + "rotation": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + "diagram_object_points": lists(create_diagram_object_point(), max_size=2), + } + + +def create_diagram_object_point(): + return builds(DiagramObjectPoint, **diagram_object_point_kwargs()) + + +def diagram_object_point_kwargs(): + return { + "x_position": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + "y_position": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + } + + +def sampled_diagram_style(): + return sampled_from(DiagramStyle) + + +def sampled_orientation_kind(): + return sampled_from(OrientationKind) + + +######################## +# IEC61970 Base Domain # +######################## + +def sampled_unit_symbol(): + return sampled_from(UnitSymbol) + + +############################# +# IEC61970 Base Equivalents # +############################# + + +def create_equivalent_branch(include_runtime: bool = True): + return builds(EquivalentBranch, **equivalent_branch_kwargs(include_runtime)) + + +def equivalent_branch_kwargs(include_runtime: bool = True): + return { + **equivalent_equipment_kwargs(include_runtime), + "negative_r12": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + "negative_r21": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + "negative_x12": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + "negative_x21": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + "positive_r12": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + "positive_r21": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + "positive_x12": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + "positive_x21": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + "r": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + "r21": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + "x": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + "x21": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + "zero_r12": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + "zero_r21": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + "zero_x12": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + "zero_x21": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + } + + +def equivalent_equipment_kwargs(include_runtime: bool): + return { + **conducting_equipment_kwargs(include_runtime) + } + + +####################################### +# IEC61970 Base Generation Production # +####################################### + +def sampled_battery_state_kind(): + return sampled_from(BatteryStateKind) + + +def create_battery_unit(include_runtime: bool = True): + return builds(BatteryUnit, **battery_unit_kwargs(include_runtime)) + + +def battery_unit_kwargs(include_runtime: bool = True): + return { + **power_electronics_unit_kwargs(include_runtime), + "battery_state": sampled_battery_state_kind(), + "rated_e": integers(min_value=MIN_64_BIT_INTEGER, max_value=MAX_64_BIT_INTEGER), + "stored_e": integers(min_value=MIN_64_BIT_INTEGER, max_value=MAX_64_BIT_INTEGER), + "controls": lists(builds(BatteryControl, **identified_object_kwargs(include_runtime)), max_size=2), + } + + +def create_photo_voltaic_unit(include_runtime: bool = True): + return builds(PhotoVoltaicUnit, **photo_voltaic_unit_kwargs(include_runtime)) + + +def photo_voltaic_unit_kwargs(include_runtime: bool = True): + return { + **power_electronics_unit_kwargs(include_runtime) + } + + +def power_electronics_unit_kwargs(include_runtime: bool): + return { + **equipment_kwargs(include_runtime), + "power_electronics_connection": builds(PowerElectronicsConnection, **identified_object_kwargs(include_runtime)), + "max_p": integers(min_value=MIN_32_BIT_INTEGER, max_value=MAX_32_BIT_INTEGER), + "min_p": integers(min_value=MIN_32_BIT_INTEGER, max_value=MAX_32_BIT_INTEGER), + } + + +def create_power_electronics_wind_unit(include_runtime: bool = True): + return builds(PowerElectronicsWindUnit, **power_electronics_wind_unit_kwargs(include_runtime)) + + +def power_electronics_wind_unit_kwargs(include_runtime: bool = True): + return { + **power_electronics_unit_kwargs(include_runtime) + } + + +###################### +# IEC61970 Base Meas # +###################### + + +def create_accumulator(include_runtime: bool = True): + return builds(Accumulator, **accumulator_kwargs(include_runtime)) + + +def accumulator_kwargs(include_runtime: bool = True): + return { + **measurement_kwargs(include_runtime) + } + + +def create_accumulator_value(): + return builds(AccumulatorValue, **accumulator_value_kwargs()) + + +def accumulator_value_kwargs(): + return { + **measurement_value_kwargs(), + "value": integers(min_value=MIN_64_BIT_INTEGER, max_value=MAX_64_BIT_INTEGER), + } + + +def create_analog(include_runtime: bool = True): + return builds(Analog, **analog_kwargs(include_runtime)) + + +def analog_kwargs(include_runtime: bool = True): + return { + **measurement_kwargs(include_runtime), + "positive_flow_in": booleans(), + } + + +def create_analog_value(): + return builds(AnalogValue, **analog_value_kwargs()) + + +def analog_value_kwargs(): + return { + **measurement_value_kwargs(), + "value": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + } + + +def create_control(include_runtime: bool = True): + return builds(Control, **control_kwargs(include_runtime)) + + +def control_kwargs(include_runtime: bool = True): + return { + **io_point_kwargs(include_runtime), + "power_system_resource_mrid": text(alphabet=ALPHANUM, min_size=1, max_size=TEXT_MAX_SIZE), + "remote_control": builds(RemoteControl, **identified_object_kwargs(include_runtime)), + } + + +def create_discrete(include_runtime: bool = True): + return builds(Discrete, **discrete_kwargs(include_runtime)) + + +def discrete_kwargs(include_runtime: bool = True): + return { + **measurement_kwargs(include_runtime) + } + + +def create_discrete_value(): + return builds(DiscreteValue, **discrete_value_kwargs()) + + +def discrete_value_kwargs(): + return { + **measurement_value_kwargs(), + "value": integers(min_value=MIN_64_BIT_INTEGER, max_value=MAX_64_BIT_INTEGER), + } + + +def io_point_kwargs(include_runtime: bool): + return { + **identified_object_kwargs(include_runtime) + } + + +def measurement_kwargs(include_runtime: bool): + return { + **identified_object_kwargs(include_runtime), + "remote_source": builds(RemoteSource, **identified_object_kwargs(include_runtime)), + "power_system_resource_mrid": uuids(version=4).map(lambda x: str(x)), + "terminal_mrid": uuids(version=4).map(lambda x: str(x)), + "phases": sampled_phase_code(), + "unit_symbol": sampled_unit_symbol(), + } + + +# noinspection PyUnusedLocal +def measurement_value_kwargs(): + return { + # "time_stamp": ... + } + + +############################ +# IEC61970 Base Protection # +############################ + + +def create_current_relay(include_runtime: bool = True): + return builds(CurrentRelay, **current_relay_kwargs(include_runtime)) + + +def current_relay_kwargs(include_runtime: bool = True): + return { + **protection_relay_function_kwargs(include_runtime), + "current_limit_1": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + "inverse_time_flag": one_of(none(), booleans()), + "time_delay_1": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + } + + +####################### +# IEC61970 Base Scada # +####################### + +def create_remote_control(include_runtime: bool = True): + return builds(RemoteControl, **remote_control_kwargs(include_runtime)) + + +def remote_control_kwargs(include_runtime: bool = True): + return { + **remote_point_kwargs(include_runtime), + "control": builds(Control, **identified_object_kwargs(include_runtime)), + } + + +def remote_point_kwargs(include_runtime: bool): + return { + **identified_object_kwargs(include_runtime) + } + + +def create_remote_source(include_runtime: bool = True): + return builds(RemoteSource, **remote_source_kwargs(include_runtime)) + + +def remote_source_kwargs(include_runtime: bool = True): + return { + **remote_point_kwargs(include_runtime), + "measurement": sampled_measurement(include_runtime), + } + + +####################### +# IEC61970 Base Wires # +####################### + + +def create_ac_line_segment(include_runtime: bool = True): + return builds(AcLineSegment, **ac_line_segment_kwargs(include_runtime)) + + +def ac_line_segment_kwargs(include_runtime: bool = True): + args = conductor_kwargs(include_runtime) + args["terminals"] = lists(builds(Terminal, **identified_object_kwargs(include_runtime)), max_size=2) + + return { + **args, + "per_length_impedance": builds(PerLengthSequenceImpedance, **identified_object_kwargs(include_runtime)), + } + + +def create_ac_line_segment_phase(include_runtime: bool = True): + return builds(AcLineSegmentPhase, **ac_line_segment_phase_kwargs(include_runtime)) + + +def ac_line_segment_phase_kwargs(include_runtime: bool = True): + return { + **power_system_resource_kwargs(include_runtime), + "ac_line_segment": builds(AcLineSegment, **identified_object_kwargs(include_runtime)), + "phase": sampled_single_phase_kind(), + "sequence_number": integers(min_value=MIN_SEQUENCE_NUMBER, max_value=MAX_SEQUENCE_NUMBER), + } + + +def create_breaker(include_runtime: bool = True): + return builds(Breaker, **breaker_kwargs(include_runtime)) + + +def breaker_kwargs(include_runtime: bool = True): + return { + **protected_switch_kwargs(include_runtime), + "in_transit_time": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + } + + +def create_busbar_section(include_runtime: bool = True): + return builds(BusbarSection, **busbar_section_kwargs(include_runtime)) + + +def busbar_section_kwargs(include_runtime: bool = True): + # Monkey patch the args to set terminals to 1, as busbars only have 1 terminal. + args = connector_kwargs(include_runtime) + args["terminals"] = lists(builds(Terminal, **identified_object_kwargs(include_runtime)), max_size=1) + + return { + **args + } + + +def create_clamp(include_runtime: bool = True): + return builds(Clamp, **clamp_kwargs(include_runtime)) + + +def clamp_kwargs(include_runtime: bool = True): + args = conducting_equipment_kwargs(include_runtime) + args["terminals"] = lists(builds(Terminal, **identified_object_kwargs(include_runtime)), max_size=1) + + return { + **args, + "length_from_terminal_1": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + "ac_line_segment": builds(AcLineSegment, **identified_object_kwargs(include_runtime)), + } + + +def conductor_kwargs(include_runtime: bool): + return { + **conducting_equipment_kwargs(include_runtime), + "asset_info": sampled_wire_info(include_runtime), + "length": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + "design_temperature": integers(min_value=MIN_32_BIT_INTEGER, max_value=MAX_32_BIT_INTEGER), + "design_rating": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + } + + +def connector_kwargs(include_runtime: bool): + return { + **conducting_equipment_kwargs(include_runtime) + } + + +def create_cut(include_runtime: bool = True): + return builds(Cut, **cut_kwargs(include_runtime)) + + +def cut_kwargs(include_runtime: bool = True): + args = switch_kwargs(include_runtime) + args["terminals"] = lists(builds(Terminal, **identified_object_kwargs(include_runtime)), max_size=2) + + return { + **args, + "length_from_terminal_1": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + "ac_line_segment": builds(AcLineSegment, **identified_object_kwargs(include_runtime)), + } + + +def create_disconnector(include_runtime: bool = True): + return builds(Disconnector, **disconnector_kwargs(include_runtime)) + + +def disconnector_kwargs(include_runtime: bool = True): + return { + **switch_kwargs(include_runtime) + } + + +def earth_fault_compensator_kwargs(include_runtime: bool): + return { + **conducting_equipment_kwargs(include_runtime), + "r": one_of(none(), floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX)), + } + + +def energy_connection_kwargs(include_runtime: bool): + return { + **conducting_equipment_kwargs(include_runtime) + } + + +def create_energy_consumer(include_runtime: bool = True): + return builds(EnergyConsumer, **energy_consumer_kwargs(include_runtime)) + + +def energy_consumer_kwargs(include_runtime: bool = True): + return { + **energy_connection_kwargs(include_runtime), + "energy_consumer_phases": lists( + builds( + EnergyConsumerPhase, + **identified_object_kwargs(include_runtime), + phase=sampled_single_phase_kind() + ), + max_size=2 + ), + "customer_count": integers(min_value=0, max_value=MAX_32_BIT_INTEGER), + "grounded": booleans(), + "p": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + "p_fixed": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + "phase_connection": sampled_phase_shunt_connection_kind(), + "q": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + "q_fixed": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + } + + +def create_energy_consumer_phase(include_runtime: bool = True): + return builds(EnergyConsumerPhase, **energy_consumer_phase_kwargs(include_runtime)) + + +def energy_consumer_phase_kwargs(include_runtime: bool = True): + return { + **power_system_resource_kwargs(include_runtime), + "energy_consumer": builds(EnergyConsumer, **identified_object_kwargs(include_runtime)), + "phase": sampled_single_phase_kind(), + "p": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + "p_fixed": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + "q": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + "q_fixed": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + } + + +def create_energy_source(include_runtime: bool = True): + return builds(EnergySource, **energy_source_kwargs(include_runtime)) + + +def energy_source_kwargs(include_runtime: bool = True): + return { + **energy_connection_kwargs(include_runtime), + "energy_source_phases": lists( + builds( + EnergySourcePhase, + **identified_object_kwargs(include_runtime), + phase=sampled_single_phase_kind() + ), + max_size=2), + "active_power": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + "reactive_power": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + "voltage_angle": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + "voltage_magnitude": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + "r": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + "x": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + "p_max": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + "p_min": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + "r0": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + "rn": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + "x0": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + "xn": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + "is_external_grid": booleans(), + "r_min": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + "rn_min": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + "r0_min": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + "x_min": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + "xn_min": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + "x0_min": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + "r_max": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + "rn_max": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + "r0_max": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + "x_max": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + "xn_max": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + "x0_max": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + } + + +def create_energy_source_phase(include_runtime: bool = True): + return builds(EnergySourcePhase, **energy_source_phase_kwargs(include_runtime)) + + +def energy_source_phase_kwargs(include_runtime: bool = True): + return { + **power_system_resource_kwargs(include_runtime), + "energy_source": builds(EnergySource, **identified_object_kwargs(include_runtime)), + "phase": sampled_single_phase_kind(), + } + + +def create_fuse(include_runtime: bool = True): + return builds(Fuse, **fuse_kwargs(include_runtime)) + + +def fuse_kwargs(include_runtime: bool = True): + return { + **switch_kwargs(include_runtime), + "function": builds(DistanceRelay, mrid=mrid_strategy), + } + + +def create_ground(include_runtime: bool = True): + return builds(Ground, **ground_kwargs(include_runtime)) + + +def ground_kwargs(include_runtime: bool = True): + return { + **conducting_equipment_kwargs(include_runtime), + } + + +def create_ground_disconnector(include_runtime: bool = True): + return builds(GroundDisconnector, **ground_disconnector_kwargs(include_runtime)) + + +def ground_disconnector_kwargs(include_runtime: bool = True): + return { + **switch_kwargs(include_runtime), + } + + +def create_grounding_impedance(include_runtime: bool = True): + return builds(GroundingImpedance, **grounding_impedance_kwargs(include_runtime)) + + +def grounding_impedance_kwargs(include_runtime: bool = True): + return { + **earth_fault_compensator_kwargs(include_runtime), + "x": one_of(none(), floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX)), + } + + +def create_jumper(include_runtime: bool = True): + return builds(Jumper, **jumper_kwargs(include_runtime)) + + +def jumper_kwargs(include_runtime: bool = True): + return { + **switch_kwargs(include_runtime) + } + + +def create_junction(include_runtime: bool = True): + return builds(Junction, **junction_kwargs(include_runtime)) + + +def junction_kwargs(include_runtime: bool = True): + return { + **connector_kwargs(include_runtime) + } + + +def line_kwargs(include_runtime: bool): + return { + **equipment_container_kwargs(include_runtime) + } + + +def create_linear_shunt_compensator(include_runtime: bool = True): + return builds(LinearShuntCompensator, **linear_shunt_compensator_kwargs(include_runtime)) + + +def linear_shunt_compensator_kwargs(include_runtime: bool = True): + return { + **shunt_compensator_kwargs(include_runtime), + "b0_per_section": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + "b_per_section": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + "g0_per_section": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + "g_per_section": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + } + + +def create_load_break_switch(include_runtime: bool = True): + return builds(LoadBreakSwitch, **load_break_switch_kwargs(include_runtime)) + + +def load_break_switch_kwargs(include_runtime: bool = True): + return { + **protected_switch_kwargs(include_runtime) + } + + +def per_length_impedance_kwargs(include_runtime: bool): + return { + **per_length_line_parameter_kwargs(include_runtime) + } + + +def per_length_line_parameter_kwargs(include_runtime: bool): + return { + **identified_object_kwargs(include_runtime) + } + + +def create_per_length_phase_impedance(include_runtime: bool = True): + return builds(PerLengthPhaseImpedance, **per_length_phase_impedance_kwargs(include_runtime)) + + +def per_length_phase_impedance_kwargs(include_runtime: bool = True): + return { + **per_length_impedance_kwargs(include_runtime), + "data": lists(create_phase_impedance_data(), max_size=4, unique_by=(lambda it: it.from_phase, lambda it: it.to_phase)), + } + + +def create_per_length_sequence_impedance(include_runtime: bool = True): + return builds(PerLengthSequenceImpedance, **per_length_sequence_impedance_kwargs(include_runtime)) + + +def per_length_sequence_impedance_kwargs(include_runtime: bool = True): + return { + **per_length_impedance_kwargs(include_runtime), + "r": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + "x": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + "r0": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + "x0": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + "bch": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + "gch": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + "b0ch": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + "g0ch": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + } + + +def create_petersen_coil(include_runtime: bool = True): + return builds(PetersenCoil, **petersen_coil_kwargs(include_runtime)) + + +def petersen_coil_kwargs(include_runtime: bool = True): + return { + **earth_fault_compensator_kwargs(include_runtime), + "x_ground_nominal": one_of(none(), floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX)), + } + + +def create_phase_impedance_data(): + return builds(PhaseImpedanceData, **phase_impedance_data_kwargs()) + + +def phase_impedance_data_kwargs(): + return { + "from_phase": sampled_from(SinglePhaseKind), + "to_phase": sampled_from(SinglePhaseKind), + "b": one_of(none(), floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX)), + "g": one_of(none(), floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX)), + "r": one_of(none(), floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX)), + "x": one_of(none(), floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX)), + } + + +def sampled_phase_shunt_connection_kind(): + return sampled_from(PhaseShuntConnectionKind) + + +def create_power_electronics_connection(include_runtime: bool = True): + return builds(PowerElectronicsConnection, **power_electronics_connection_kwargs(include_runtime)) + + +def power_electronics_connection_kwargs(include_runtime: bool = True): + return { + **regulating_cond_eq_kwargs(include_runtime), + "power_electronics_units": lists(builds(BatteryUnit, **identified_object_kwargs(include_runtime)), max_size=2), + "power_electronics_connection_phases": lists(builds(PowerElectronicsConnectionPhase, **identified_object_kwargs(include_runtime)), max_size=2), + "max_i_fault": integers(min_value=0, max_value=MAX_32_BIT_INTEGER), + "max_q": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + "min_q": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + "p": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + "q": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + "rated_s": integers(min_value=0, max_value=MAX_32_BIT_INTEGER), + "rated_u": integers(min_value=0, max_value=MAX_32_BIT_INTEGER), + "inverter_standard": text(alphabet=ALPHANUM, min_size=1, max_size=TEXT_MAX_SIZE), + "sustain_op_overvolt_limit": integers(min_value=0, max_value=MAX_32_BIT_INTEGER), + "stop_at_over_freq": floats(min_value=51.0, max_value=52.0), + "stop_at_under_freq": floats(min_value=47.0, max_value=49.0), + "inv_volt_watt_resp_mode": one_of(none(), booleans()), + "inv_watt_resp_v1": integers(min_value=200, max_value=300), + "inv_watt_resp_v2": integers(min_value=216, max_value=230), + "inv_watt_resp_v3": integers(min_value=235, max_value=255), + "inv_watt_resp_v4": integers(min_value=244, max_value=265), + "inv_watt_resp_p_at_v1": floats(min_value=0.0, max_value=1.0), + "inv_watt_resp_p_at_v2": floats(min_value=0.0, max_value=1.0), + "inv_watt_resp_p_at_v3": floats(min_value=0.0, max_value=1.0), + "inv_watt_resp_p_at_v4": floats(min_value=0.0, max_value=0.12300000339746475), + "inv_volt_var_resp_mode": one_of(none(), booleans()), + "inv_var_resp_v1": integers(min_value=200, max_value=300), + "inv_var_resp_v2": integers(min_value=200, max_value=300), + "inv_var_resp_v3": integers(min_value=200, max_value=300), + "inv_var_resp_v4": integers(min_value=200, max_value=300), + "inv_var_resp_q_at_v1": floats(min_value=0.0, max_value=0.5120000243186951), + "inv_var_resp_q_at_v2": floats(min_value=-1.0, max_value=1.0), + "inv_var_resp_q_at_v3": floats(min_value=-1.0, max_value=1.0), + "inv_var_resp_q_at_v4": floats(min_value=-0.5120000243186951, max_value=0.0), + "inv_reactive_power_mode": one_of(none(), booleans()), + "inv_fix_reactive_power": floats(min_value=-1.0, max_value=1.0), + } + + +def create_power_electronics_connection_phase(include_runtime: bool = True): + return builds(PowerElectronicsConnectionPhase, **power_electronics_connection_phase_kwargs(include_runtime)) + + +def power_electronics_connection_phase_kwargs(include_runtime: bool = True): + return { + **power_system_resource_kwargs(include_runtime), + "power_electronics_connection": builds(PowerElectronicsConnection, **identified_object_kwargs(include_runtime)), + "phase": sampled_single_phase_kind(), + "p": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + "q": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + } + + +def create_power_transformer(include_runtime: bool = True): + return builds(PowerTransformer, **power_transformer_kwargs(include_runtime)) + + +def power_transformer_kwargs(include_runtime: bool = True): + return { + **conducting_equipment_kwargs(include_runtime), + "asset_info": builds(PowerTransformerInfo, **identified_object_kwargs(include_runtime)), + "power_transformer_ends": lists(builds(PowerTransformerEnd, **identified_object_kwargs(include_runtime)), max_size=2), + "vector_group": sampled_vector_group(), + "transformer_utilisation": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + } + + +def create_power_transformer_end(include_runtime: bool = True): + return builds(create_power_transformer_end_with_ratings, **power_transformer_end_kwargs(include_runtime)) + + +def power_transformer_end_kwargs(include_runtime: bool = True): + return { + **transformer_end_kwargs(include_runtime), + "power_transformer": builds(PowerTransformer, **identified_object_kwargs(include_runtime)), + # rated_s=integers(min_value=MIN_32_BIT_INTEGER, max_value=MAX_32_BIT_INTEGER), + "rated_u": integers(min_value=MIN_32_BIT_INTEGER, max_value=MAX_32_BIT_INTEGER), + "r": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + "r0": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + "x": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + "x0": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + "connection_kind": sampled_winding_connection(), + "b": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + "b0": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + "g": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + "g0": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + "phase_angle_clock": integers(min_value=0, max_value=11), + "ratings": lists(builds( + TransformerEndRatedS, + cooling_type=sampled_transformer_cooling_type(), + rated_s=integers(min_value=MIN_32_BIT_INTEGER, max_value=MAX_32_BIT_INTEGER) + ), max_size=11, unique_by=lambda it: it.cooling_type), + } + + +def protected_switch_kwargs(include_runtime: bool): + return { + **switch_kwargs(include_runtime), + "breaking_capacity": integers(min_value=MIN_32_BIT_INTEGER, max_value=MAX_32_BIT_INTEGER), + "relay_functions": lists(builds(CurrentRelay, mrid=mrid_strategy), max_size=2), + } + + +def create_ratio_tap_changer(include_runtime: bool = True): + return builds(RatioTapChanger, **ratio_tap_changer_kwargs(include_runtime)) + + +def ratio_tap_changer_kwargs(include_runtime: bool = True): + return { + **tap_changer_kwargs(include_runtime), + "transformer_end": builds(PowerTransformerEnd, **identified_object_kwargs(include_runtime)), + "step_voltage_increment": floats(min_value=0.0, max_value=1.0), + } + + +def create_reactive_capability_curve(include_runtime: bool = True): + return builds(ReactiveCapabilityCurve, **reactive_capability_curve_kwargs(include_runtime)) + + +def reactive_capability_curve_kwargs(include_runtime: bool = True): + return { + **curve_kwargs(include_runtime), + } + + +def create_recloser(include_runtime: bool = True): + return builds(Recloser, **recloser_kwargs(include_runtime)) + + +def recloser_kwargs(include_runtime: bool = True): + return { + **protected_switch_kwargs(include_runtime) + } + + +def regulating_cond_eq_kwargs(include_runtime: bool): + return { + **energy_connection_kwargs(include_runtime), + "control_enabled": one_of(none(), booleans()), + "regulating_control": builds(TapChangerControl, **identified_object_kwargs(include_runtime)), + } + + +def regulating_control_kwargs(include_runtime: bool): + return { + **power_system_resource_kwargs(include_runtime), + "discrete": one_of(none(), booleans()), + "mode": sampled_from(RegulatingControlModeKind), + "monitored_phase": sampled_phase_code(), + "target_deadband": floats(min_value=0.0, max_value=FLOAT_MAX), + "target_value": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + "enabled": one_of(none(), booleans()), + "max_allowed_target_value": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + "min_allowed_target_value": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + "rated_current": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + "terminal": builds(Terminal, **identified_object_kwargs(include_runtime)), + "ct_primary": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + "min_target_deadband": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + "regulating_conducting_equipment": lists(builds(PowerElectronicsConnection, **identified_object_kwargs(include_runtime))), + } + + +def sampled_regulating_control_mode_kind(): + return sampled_from(RegulatingControlModeKind) + + +def rotating_machine_kwargs(include_runtime: bool): + return { + **regulating_cond_eq_kwargs(include_runtime), + "rated_power_factor": one_of(none(), floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX)), + "rated_s": one_of(none(), floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX)), + "rated_u": one_of(none(), integers(min_value=MIN_32_BIT_INTEGER, max_value=MAX_32_BIT_INTEGER)), + "p": one_of(none(), floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX)), + "q": one_of(none(), floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX)), + } + + +def create_series_compensator(include_runtime: bool = True): + return builds(SeriesCompensator, **series_compensator_kwargs(include_runtime)) + + +def series_compensator_kwargs(include_runtime: bool = True): + return { + **conducting_equipment_kwargs(include_runtime), + "r": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + "r0": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + "x": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + "x0": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + "varistor_rated_current": integers(min_value=MIN_32_BIT_INTEGER, max_value=MAX_32_BIT_INTEGER), + "varistor_voltage_threshold": integers(min_value=MIN_32_BIT_INTEGER, max_value=MAX_32_BIT_INTEGER), + } + + +def shunt_compensator_kwargs(include_runtime: bool): + return { + **regulating_cond_eq_kwargs(include_runtime), + "asset_info": builds(ShuntCompensatorInfo, **identified_object_kwargs(include_runtime)), + "grounded": booleans(), + "nom_u": integers(min_value=MIN_32_BIT_INTEGER, max_value=MAX_32_BIT_INTEGER), + "phase_connection": sampled_phase_shunt_connection_kind(), + "sections": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + "grounding_terminal": builds(Terminal, **identified_object_kwargs(include_runtime)), + } + + +def sampled_single_phase_kind(): + return sampled_from(SinglePhaseKind) + + +def create_static_var_compensator(include_runtime: bool = True): + return builds(StaticVarCompensator, **static_var_compensator_kwargs(include_runtime)) + + +def static_var_compensator_kwargs(include_runtime: bool = True): + return { + **regulating_cond_eq_kwargs(include_runtime), + "capacitive_rating": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + "inductive_rating": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + "q": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + "svc_control_mode": sampled_svc_control_mode(), + "voltage_set_point": integers(min_value=MIN_32_BIT_INTEGER, max_value=MAX_32_BIT_INTEGER), + } + + +def sampled_svc_control_mode(): + return sampled_from(SVCControlMode) + + +def switch_kwargs(include_runtime: bool): + return { + **conducting_equipment_kwargs(include_runtime), + "rated_current": floats(min_value=1, max_value=FLOAT_MAX), + # NOTE: These are not currently encoded properly in protobuf so we can only use all or none. + "_normally_open": sampled_from([0, 15]), + "_open": sampled_from([0, 15]) + # "_normally_open": integers(min_value=0, max_value=15), + # "_open": integers(min_value=0, max_value=15), + } + + +def create_synchronous_machine(include_runtime: bool = True): + return builds(SynchronousMachine, **synchronous_machine_kwargs(include_runtime)) + + +def synchronous_machine_kwargs(include_runtime: bool = True): + return { + **rotating_machine_kwargs(include_runtime), + "curves": one_of(none(), lists(builds(ReactiveCapabilityCurve, **identified_object_kwargs(include_runtime)), max_size=2)), + "base_q": one_of(none(), floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX)), + "condenser_p": one_of(none(), integers(min_value=MIN_32_BIT_INTEGER, max_value=MAX_32_BIT_INTEGER)), + "earthing": one_of(none(), booleans()), + "earthing_star_point_r": one_of(none(), floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX)), + "earthing_star_point_x": one_of(none(), floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX)), + "ikk": one_of(none(), floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX)), + "max_q": one_of(none(), floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX)), + "max_u": one_of(none(), integers(min_value=MIN_32_BIT_INTEGER, max_value=MAX_32_BIT_INTEGER)), + "min_q": one_of(none(), floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX)), + "min_u": one_of(none(), integers(min_value=MIN_32_BIT_INTEGER, max_value=MAX_32_BIT_INTEGER)), + "mu": one_of(none(), floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX)), + "r": one_of(none(), floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX)), + "r0": one_of(none(), floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX)), + "r2": one_of(none(), floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX)), + "sat_direct_subtrans_x": one_of(none(), floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX)), + "sat_direct_sync_x": one_of(none(), floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX)), + "sat_direct_trans_x": one_of(none(), floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX)), + "x0": one_of(none(), floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX)), + "x2": one_of(none(), floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX)), + "type": sampled_synchronous_machine_kind(), + "operating_mode": sampled_synchronous_machine_kind(), + } + + +def sampled_synchronous_machine_kind(): + return sampled_from(SynchronousMachineKind) + + +def tap_changer_kwargs(include_runtime: bool): + return { + **power_system_resource_kwargs(include_runtime), + "high_step": integers(min_value=10, max_value=15), + "low_step": integers(min_value=0, max_value=2), + "step": floats(min_value=2.0, max_value=10.0), + "neutral_step": integers(min_value=2, max_value=10), + "neutral_u": integers(min_value=MIN_32_BIT_INTEGER, max_value=MAX_32_BIT_INTEGER), + "normal_step": integers(min_value=2, max_value=10), + "control_enabled": booleans(), + "tap_changer_control": builds(TapChangerControl, **identified_object_kwargs(include_runtime)), + } + + +def create_tap_changer_control(include_runtime: bool = True): + return builds(TapChangerControl, **tap_changer_control_kwargs(include_runtime)) + + +def tap_changer_control_kwargs(include_runtime: bool = True): + return { + **regulating_control_kwargs(include_runtime), + "limit_voltage": integers(min_value=MIN_32_BIT_INTEGER, max_value=MAX_32_BIT_INTEGER), + "line_drop_compensation": one_of(none(), booleans()), + "line_drop_r": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + "line_drop_x": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + "reverse_line_drop_r": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + "reverse_line_drop_x": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + "forward_ldc_blocking": one_of(none(), booleans()), + "time_delay": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + "co_generation_enabled": one_of(none(), booleans()), + } + + +def transformer_end_kwargs(include_runtime: bool): + return { + **identified_object_kwargs(include_runtime), + "terminal": builds(Terminal, **identified_object_kwargs(include_runtime)), + "base_voltage": builds(BaseVoltage, **identified_object_kwargs(include_runtime)), + "ratio_tap_changer": builds(RatioTapChanger, **identified_object_kwargs(include_runtime)), + "end_number": integers(min_value=MIN_SEQUENCE_NUMBER, max_value=MAX_END_NUMBER), + "grounded": booleans(), + "r_ground": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + "x_ground": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + "star_impedance": builds(TransformerStarImpedance, **identified_object_kwargs(include_runtime)), + } + + +def create_transformer_star_impedance(include_runtime: bool = True): + return builds(TransformerStarImpedance, **transformer_star_impedance_kwargs(include_runtime)) + + +def transformer_star_impedance_kwargs(include_runtime: bool = True): + return { + **identified_object_kwargs(include_runtime), + "r": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + "r0": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + "x": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + "x0": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), + "transformer_end_info": builds(TransformerEndInfo, **identified_object_kwargs(include_runtime)), + } + + +def sampled_winding_connection(): + return sampled_from(WindingConnection) + + +############################### +# IEC61970 InfIEC61970 Feeder # +############################### + + +def create_circuit(include_runtime: bool = True): + return builds(Circuit, **circuit_kwargs(include_runtime)) + + +def circuit_kwargs(include_runtime: bool = True): + return { + **line_kwargs(include_runtime), + "loop": builds(Loop, **identified_object_kwargs(include_runtime)), + "end_terminals": lists(builds(Terminal, **identified_object_kwargs(include_runtime)), max_size=2), + "end_substations": lists(builds(Substation, **identified_object_kwargs(include_runtime)), max_size=2), + } + + +############### +# SAMPLE SETS # +############### + + +def sampled_wire_info(include_runtime: bool): + return choice([ + builds(OverheadWireInfo, **identified_object_kwargs(include_runtime)), + builds(CableInfo, **identified_object_kwargs(include_runtime)), + ]) + + +def sampled_conducting_equipment(include_runtime: bool): + return choice([ + # Don't add EnergySource to this list as it's used in SetPhases to start tracing, which will cause test_schema_terminal to fail. + builds(AcLineSegment, **identified_object_kwargs(include_runtime)), + builds(PowerTransformer, **identified_object_kwargs(include_runtime)), + builds(Breaker, **identified_object_kwargs(include_runtime)), + builds(Disconnector, **identified_object_kwargs(include_runtime)), + builds(EnergyConsumer, **identified_object_kwargs(include_runtime)), + ]) + + +def sampled_curves(include_runtime: bool): + return choice([ + builds(ReactiveCapabilityCurve, **identified_object_kwargs(include_runtime)) + ]) + + +def sampled_end_device_function(include_runtime: bool): + return choice([ + # Don't add EnergySource to this list as it's used in SetPhases to start tracing, which will cause test_schema_terminal to fail. + builds(PanDemandResponseFunction, **identified_object_kwargs(include_runtime)) + ]) + + +def sampled_equipment(include_runtime: bool): + return choice([ + builds(AcLineSegment, **identified_object_kwargs(include_runtime)), + builds(PowerTransformer, **identified_object_kwargs(include_runtime)), + builds(Breaker, **identified_object_kwargs(include_runtime)), + builds(Disconnector, **identified_object_kwargs(include_runtime)), + builds(EnergyConsumer, **identified_object_kwargs(include_runtime)), + builds(EnergySource, **identified_object_kwargs(include_runtime)), + builds(FaultIndicator, **identified_object_kwargs(include_runtime)) + ]) + + +def sampled_equipment_container(include_runtime: bool): + available_containers = [ + builds(Site, **identified_object_kwargs(include_runtime)), + builds(Circuit, **identified_object_kwargs(include_runtime)), + builds(Substation, **identified_object_kwargs(include_runtime)) + ] + + if include_runtime: + available_containers.append(builds(Feeder, **identified_object_kwargs(include_runtime))) + + return choice(available_containers) + + +def sampled_hvlv_feeder(include_runtime: bool): + return choice([ + builds(Feeder, **identified_object_kwargs(include_runtime)), + builds(LvFeeder, **identified_object_kwargs(include_runtime)) + ]) + + +def sampled_measurement(include_runtime: bool): + return choice([ + builds(Accumulator, **identified_object_kwargs(include_runtime)), + builds(Analog, **identified_object_kwargs(include_runtime)), + builds(Discrete, **identified_object_kwargs(include_runtime)), + ]) + + +def sampled_protected_switches(include_runtime: bool): + return choice([ + builds(Breaker, **identified_object_kwargs(include_runtime)), + builds(LoadBreakSwitch, **identified_object_kwargs(include_runtime)), + builds(Recloser, **identified_object_kwargs(include_runtime)) + ]) diff --git a/test/cim/iec61968/assetinfo/test_no_load_test.py b/test/cim/iec61968/assetinfo/test_no_load_test.py index e346ffb88..301abc0c2 100644 --- a/test/cim/iec61968/assetinfo/test_no_load_test.py +++ b/test/cim/iec61968/assetinfo/test_no_load_test.py @@ -6,7 +6,7 @@ from hypothesis.strategies import integers, floats from zepben.ewb import NoLoadTest, generate_id -from cim.cim_creators import MIN_32_BIT_INTEGER, MAX_32_BIT_INTEGER, FLOAT_MIN, FLOAT_MAX +from cim.fill_fields import MIN_32_BIT_INTEGER, MAX_32_BIT_INTEGER, FLOAT_MIN, FLOAT_MAX from cim.iec61968.assetinfo.test_transformer_test import transformer_test_kwargs, verify_transformer_test_constructor_default, \ verify_transformer_test_constructor_kwargs, verify_transformer_test_constructor_args, transformer_test_args diff --git a/test/cim/iec61968/assetinfo/test_open_circuit_test.py b/test/cim/iec61968/assetinfo/test_open_circuit_test.py index 705af6abc..4c37c6c56 100644 --- a/test/cim/iec61968/assetinfo/test_open_circuit_test.py +++ b/test/cim/iec61968/assetinfo/test_open_circuit_test.py @@ -6,7 +6,7 @@ from hypothesis.strategies import integers, floats from zepben.ewb import OpenCircuitTest, generate_id -from cim.cim_creators import MIN_32_BIT_INTEGER, MAX_32_BIT_INTEGER, FLOAT_MIN, FLOAT_MAX +from cim.fill_fields import MIN_32_BIT_INTEGER, MAX_32_BIT_INTEGER, FLOAT_MIN, FLOAT_MAX from cim.iec61968.assetinfo.test_transformer_test import transformer_test_kwargs, verify_transformer_test_constructor_default, \ verify_transformer_test_constructor_kwargs, verify_transformer_test_constructor_args, transformer_test_args diff --git a/test/cim/iec61968/assetinfo/test_short_circuit_test.py b/test/cim/iec61968/assetinfo/test_short_circuit_test.py index 9193f2b42..956632d17 100644 --- a/test/cim/iec61968/assetinfo/test_short_circuit_test.py +++ b/test/cim/iec61968/assetinfo/test_short_circuit_test.py @@ -6,7 +6,7 @@ from hypothesis.strategies import integers, floats from zepben.ewb import ShortCircuitTest, generate_id -from cim.cim_creators import MIN_32_BIT_INTEGER, MAX_32_BIT_INTEGER, FLOAT_MIN, FLOAT_MAX +from cim.fill_fields import MIN_32_BIT_INTEGER, MAX_32_BIT_INTEGER, FLOAT_MIN, FLOAT_MAX from cim.iec61968.assetinfo.test_transformer_test import transformer_test_kwargs, verify_transformer_test_constructor_default, \ verify_transformer_test_constructor_kwargs, verify_transformer_test_constructor_args, transformer_test_args diff --git a/test/cim/iec61968/assetinfo/test_shunt_compensator_info.py b/test/cim/iec61968/assetinfo/test_shunt_compensator_info.py index e58310146..955f2b4f9 100644 --- a/test/cim/iec61968/assetinfo/test_shunt_compensator_info.py +++ b/test/cim/iec61968/assetinfo/test_shunt_compensator_info.py @@ -6,7 +6,7 @@ from hypothesis.strategies import integers from zepben.ewb import ShuntCompensatorInfo, generate_id -from cim.cim_creators import MIN_32_BIT_INTEGER, MAX_32_BIT_INTEGER +from cim.fill_fields import MIN_32_BIT_INTEGER, MAX_32_BIT_INTEGER from cim.iec61968.assets.test_asset_info import asset_info_kwargs, asset_info_args, verify_asset_info_constructor_default, \ verify_asset_info_constructor_kwargs, verify_asset_info_constructor_args diff --git a/test/cim/iec61968/assetinfo/test_switch_info.py b/test/cim/iec61968/assetinfo/test_switch_info.py index 62a7c055a..1f343d4ff 100644 --- a/test/cim/iec61968/assetinfo/test_switch_info.py +++ b/test/cim/iec61968/assetinfo/test_switch_info.py @@ -6,7 +6,7 @@ from hypothesis.strategies import floats from zepben.ewb import SwitchInfo, generate_id -from cim.cim_creators import FLOAT_MIN, FLOAT_MAX +from cim.fill_fields import FLOAT_MIN, FLOAT_MAX from cim.iec61968.assets.test_asset_info import asset_info_kwargs, asset_info_args, verify_asset_info_constructor_default, verify_asset_info_constructor_kwargs, \ verify_asset_info_constructor_args diff --git a/test/cim/iec61968/assetinfo/test_transformer_end_info.py b/test/cim/iec61968/assetinfo/test_transformer_end_info.py index 2fa974ad5..71398cdf5 100644 --- a/test/cim/iec61968/assetinfo/test_transformer_end_info.py +++ b/test/cim/iec61968/assetinfo/test_transformer_end_info.py @@ -7,7 +7,7 @@ from hypothesis import given from hypothesis.strategies import integers, floats -from cim.cim_creators import MIN_32_BIT_INTEGER, MAX_32_BIT_INTEGER, FLOAT_MIN, FLOAT_MAX, sampled_winding_connection, create_transformer_tank_info, \ +from cim.fill_fields import MIN_32_BIT_INTEGER, MAX_32_BIT_INTEGER, FLOAT_MIN, FLOAT_MAX, sampled_winding_connection, create_transformer_tank_info, \ create_transformer_star_impedance, create_no_load_test, create_short_circuit_test, create_open_circuit_test from cim.iec61968.assets.test_asset_info import asset_info_kwargs, verify_asset_info_constructor_default, verify_asset_info_constructor_kwargs, \ verify_asset_info_constructor_args, asset_info_args diff --git a/test/cim/iec61968/assetinfo/test_transformer_test.py b/test/cim/iec61968/assetinfo/test_transformer_test.py index bf5d1eebd..6b7fa5782 100644 --- a/test/cim/iec61968/assetinfo/test_transformer_test.py +++ b/test/cim/iec61968/assetinfo/test_transformer_test.py @@ -5,7 +5,7 @@ from hypothesis.strategies import integers, floats from zepben.ewb import TransformerTest -from cim.cim_creators import MIN_32_BIT_INTEGER, MAX_32_BIT_INTEGER, FLOAT_MIN, FLOAT_MAX +from cim.fill_fields import MIN_32_BIT_INTEGER, MAX_32_BIT_INTEGER, FLOAT_MIN, FLOAT_MAX from cim.iec61970.base.core.test_identified_object import identified_object_kwargs, verify_identified_object_constructor_default, \ verify_identified_object_constructor_kwargs, verify_identified_object_constructor_args, identified_object_args diff --git a/test/cim/iec61968/assetinfo/test_wire_info.py b/test/cim/iec61968/assetinfo/test_wire_info.py index 1ad8bd213..c6a19091d 100644 --- a/test/cim/iec61968/assetinfo/test_wire_info.py +++ b/test/cim/iec61968/assetinfo/test_wire_info.py @@ -7,7 +7,7 @@ from streaming.get.pb_creators import floats from zepben.ewb import WireInfo, WireMaterialKind -from cim.cim_creators import MIN_32_BIT_INTEGER, MAX_32_BIT_INTEGER, ALPHANUM, FLOAT_MIN, FLOAT_MAX, sampled_wire_insulation_kind +from cim.fill_fields import MIN_32_BIT_INTEGER, MAX_32_BIT_INTEGER, ALPHANUM, FLOAT_MIN, FLOAT_MAX, sampled_wire_insulation_kind from cim.iec61970.base.core.test_identified_object import identified_object_kwargs, verify_identified_object_constructor_default, \ verify_identified_object_constructor_kwargs, verify_identified_object_constructor_args, identified_object_args from zepben.ewb.model.cim.iec61968.assetinfo.wire_insulation_kind import WireInsulationKind diff --git a/test/cim/iec61968/assets/test_pole.py b/test/cim/iec61968/assets/test_pole.py index eea178705..a2ee313a4 100644 --- a/test/cim/iec61968/assets/test_pole.py +++ b/test/cim/iec61968/assets/test_pole.py @@ -8,7 +8,7 @@ from util import mrid_strategy from zepben.ewb import Pole, Streetlight, generate_id -from cim.cim_creators import ALPHANUM, TEXT_MAX_SIZE +from cim.fill_fields import ALPHANUM, TEXT_MAX_SIZE from cim.iec61968.assets.test_structure import structure_kwargs, verify_structure_constructor_default, \ verify_structure_constructor_kwargs, verify_structure_constructor_args, structure_args from cim.private_collection_validator import validate_unordered diff --git a/test/cim/iec61968/assets/test_streelight.py b/test/cim/iec61968/assets/test_streelight.py index bbdb60605..42d4fcfa4 100644 --- a/test/cim/iec61968/assets/test_streelight.py +++ b/test/cim/iec61968/assets/test_streelight.py @@ -9,7 +9,7 @@ from zepben.ewb import Streetlight, Pole, generate_id from zepben.ewb.model.cim.iec61968.infiec61968.infassets.streetlight_lamp_kind import StreetlightLampKind -from cim.cim_creators import MIN_32_BIT_INTEGER, MAX_32_BIT_INTEGER +from cim.fill_fields import MIN_32_BIT_INTEGER, MAX_32_BIT_INTEGER from cim.iec61968.assets.test_asset import asset_kwargs, verify_asset_constructor_default, \ verify_asset_constructor_kwargs, verify_asset_constructor_args, asset_args diff --git a/test/cim/iec61968/common/test_document.py b/test/cim/iec61968/common/test_document.py index 3f5f57a3d..ee4e7337f 100644 --- a/test/cim/iec61968/common/test_document.py +++ b/test/cim/iec61968/common/test_document.py @@ -7,7 +7,7 @@ from hypothesis.strategies import text, datetimes from zepben.ewb import Document -from cim.cim_creators import ALPHANUM, TEXT_MAX_SIZE +from cim.fill_fields import ALPHANUM, TEXT_MAX_SIZE from cim.iec61970.base.core.test_identified_object import identified_object_kwargs, verify_identified_object_constructor_default, \ verify_identified_object_constructor_kwargs, verify_identified_object_constructor_args, identified_object_args diff --git a/test/cim/iec61968/common/test_electronic_address.py b/test/cim/iec61968/common/test_electronic_address.py index fd824560e..8501e0b6a 100644 --- a/test/cim/iec61968/common/test_electronic_address.py +++ b/test/cim/iec61968/common/test_electronic_address.py @@ -5,7 +5,7 @@ from hypothesis import given from hypothesis.strategies import booleans, text -from cim.cim_creators import ALPHANUM +from cim.fill_fields import ALPHANUM from zepben.ewb import ElectronicAddress diff --git a/test/cim/iec61968/common/test_location.py b/test/cim/iec61968/common/test_location.py index 5d8ced813..f66ecd29d 100644 --- a/test/cim/iec61968/common/test_location.py +++ b/test/cim/iec61968/common/test_location.py @@ -8,7 +8,7 @@ from zepben.ewb.model.cim.iec61968.common.street_address import StreetAddress from zepben.ewb.model.cim.iec61968.common.position_point import PositionPoint -from cim.cim_creators import create_position_point +from cim.fill_fields import create_position_point from cim.iec61970.base.core.test_identified_object import identified_object_kwargs, verify_identified_object_constructor_default, \ verify_identified_object_constructor_kwargs, verify_identified_object_constructor_args, identified_object_args from cim.private_collection_validator import validate_ordered_other diff --git a/test/cim/iec61968/common/test_street_address.py b/test/cim/iec61968/common/test_street_address.py index f009e405f..7e65f2078 100644 --- a/test/cim/iec61968/common/test_street_address.py +++ b/test/cim/iec61968/common/test_street_address.py @@ -12,7 +12,7 @@ from zepben.ewb.model.cim.iec61968.common.street_detail import StreetDetail from zepben.ewb.model.cim.iec61968.common.town_detail import TownDetail -from cim.cim_creators import ALPHANUM, TEXT_MAX_SIZE +from cim.fill_fields import ALPHANUM, TEXT_MAX_SIZE street_address_kwargs = { "postal_code": text(alphabet=ALPHANUM, max_size=TEXT_MAX_SIZE), diff --git a/test/cim/iec61968/common/test_street_detail.py b/test/cim/iec61968/common/test_street_detail.py index 0e2fd8059..4c753e5e6 100644 --- a/test/cim/iec61968/common/test_street_detail.py +++ b/test/cim/iec61968/common/test_street_detail.py @@ -7,7 +7,7 @@ from hypothesis.strategies import text from zepben.ewb.model.cim.iec61968.common.street_detail import StreetDetail -from cim.cim_creators import ALPHANUM, TEXT_MAX_SIZE +from cim.fill_fields import ALPHANUM, TEXT_MAX_SIZE street_detail_kwargs = { "building_name": text(alphabet=ALPHANUM, max_size=TEXT_MAX_SIZE), diff --git a/test/cim/iec61968/common/test_telephone_number.py b/test/cim/iec61968/common/test_telephone_number.py index df031fc12..c1eee2883 100644 --- a/test/cim/iec61968/common/test_telephone_number.py +++ b/test/cim/iec61968/common/test_telephone_number.py @@ -5,7 +5,7 @@ from hypothesis import given from hypothesis.strategies import text -from cim.cim_creators import ALPHANUM +from cim.fill_fields import ALPHANUM from zepben.ewb import TelephoneNumber diff --git a/test/cim/iec61968/common/test_town_detail.py b/test/cim/iec61968/common/test_town_detail.py index 820a8d55a..b7f28f3be 100644 --- a/test/cim/iec61968/common/test_town_detail.py +++ b/test/cim/iec61968/common/test_town_detail.py @@ -7,7 +7,7 @@ from hypothesis.strategies import text from zepben.ewb.model.cim.iec61968.common.town_detail import TownDetail -from cim.cim_creators import ALPHANUM, TEXT_MAX_SIZE +from cim.fill_fields import ALPHANUM, TEXT_MAX_SIZE town_detail_kwargs = { "name": text(alphabet=ALPHANUM, max_size=TEXT_MAX_SIZE), diff --git a/test/cim/iec61968/customers/test_customer.py b/test/cim/iec61968/customers/test_customer.py index 9b4be5ee4..78d11b3a3 100644 --- a/test/cim/iec61968/customers/test_customer.py +++ b/test/cim/iec61968/customers/test_customer.py @@ -6,7 +6,7 @@ from hypothesis import given from hypothesis.strategies import lists, builds, sampled_from, text -from cim.cim_creators import ALPHANUM, TEXT_MAX_SIZE +from cim.fill_fields import ALPHANUM, TEXT_MAX_SIZE from util import mrid_strategy from zepben.ewb import Customer, CustomerKind, CustomerAgreement, generate_id diff --git a/test/cim/iec61968/customers/test_pricing_structure.py b/test/cim/iec61968/customers/test_pricing_structure.py index 32a1a40b4..f52c61161 100644 --- a/test/cim/iec61968/customers/test_pricing_structure.py +++ b/test/cim/iec61968/customers/test_pricing_structure.py @@ -6,7 +6,7 @@ from hypothesis import given from hypothesis.strategies import lists, builds, text -from cim.cim_creators import ALPHANUM +from cim.fill_fields import ALPHANUM from util import mrid_strategy from zepben.ewb import PricingStructure, Tariff, generate_id diff --git a/test/cim/iec61968/infiec61968/infassetinfo/test_current_transformer_info.py b/test/cim/iec61968/infiec61968/infassetinfo/test_current_transformer_info.py index 0c468c1e7..e1dc87914 100644 --- a/test/cim/iec61968/infiec61968/infassetinfo/test_current_transformer_info.py +++ b/test/cim/iec61968/infiec61968/infassetinfo/test_current_transformer_info.py @@ -7,7 +7,7 @@ from hypothesis.strategies import builds, floats, integers, text from zepben.ewb import CurrentTransformerInfo, Ratio, generate_id -from cim.cim_creators import FLOAT_MIN, FLOAT_MAX, MIN_32_BIT_INTEGER, MAX_32_BIT_INTEGER, ALPHANUM, TEXT_MAX_SIZE +from cim.fill_fields import FLOAT_MIN, FLOAT_MAX, MIN_32_BIT_INTEGER, MAX_32_BIT_INTEGER, ALPHANUM, TEXT_MAX_SIZE from cim.iec61968.assets.test_asset_info import asset_info_kwargs, verify_asset_info_constructor_default, \ verify_asset_info_constructor_kwargs, verify_asset_info_constructor_args, asset_info_args diff --git a/test/cim/iec61968/infiec61968/infassetinfo/test_potential_transformer_info.py b/test/cim/iec61968/infiec61968/infassetinfo/test_potential_transformer_info.py index 2108a1adc..ee8121762 100644 --- a/test/cim/iec61968/infiec61968/infassetinfo/test_potential_transformer_info.py +++ b/test/cim/iec61968/infiec61968/infassetinfo/test_potential_transformer_info.py @@ -8,7 +8,7 @@ from zepben.ewb import PotentialTransformerInfo, Ratio, generate_id -from cim.cim_creators import FLOAT_MIN, FLOAT_MAX, MIN_32_BIT_INTEGER, MAX_32_BIT_INTEGER, ALPHANUM, TEXT_MAX_SIZE +from cim.fill_fields import FLOAT_MIN, FLOAT_MAX, MIN_32_BIT_INTEGER, MAX_32_BIT_INTEGER, ALPHANUM, TEXT_MAX_SIZE from cim.iec61968.assets.test_asset_info import asset_info_kwargs, verify_asset_info_constructor_default, \ verify_asset_info_constructor_kwargs, verify_asset_info_constructor_args, asset_info_args diff --git a/test/cim/iec61968/infiec61968/infassetinfo/test_relay_info.py b/test/cim/iec61968/infiec61968/infassetinfo/test_relay_info.py index 8845dae60..390f1da44 100644 --- a/test/cim/iec61968/infiec61968/infassetinfo/test_relay_info.py +++ b/test/cim/iec61968/infiec61968/infassetinfo/test_relay_info.py @@ -5,7 +5,7 @@ from hypothesis import given from hypothesis.strategies import text, lists, floats, booleans -from cim.cim_creators import ALPHANUM, TEXT_MAX_SIZE, FLOAT_MIN, FLOAT_MAX +from cim.fill_fields import ALPHANUM, TEXT_MAX_SIZE, FLOAT_MIN, FLOAT_MAX from cim.iec61968.assets.test_asset_info import asset_info_kwargs, asset_info_args, verify_asset_info_constructor_default, verify_asset_info_constructor_kwargs, \ verify_asset_info_constructor_args from cim.private_collection_validator import validate_ordered_other diff --git a/test/cim/iec61968/metering/test_end_device.py b/test/cim/iec61968/metering/test_end_device.py index 17e3f9611..450354131 100644 --- a/test/cim/iec61968/metering/test_end_device.py +++ b/test/cim/iec61968/metering/test_end_device.py @@ -5,7 +5,7 @@ from hypothesis.strategies import text, builds, lists -from cim.cim_creators import ALPHANUM, TEXT_MAX_SIZE +from cim.fill_fields import ALPHANUM, TEXT_MAX_SIZE from cim.iec61968.assets.test_asset_container import asset_container_kwargs, verify_asset_container_constructor_default, \ verify_asset_container_constructor_kwargs, verify_asset_container_constructor_args, asset_container_args from cim.private_collection_validator import validate_unordered diff --git a/test/cim/iec61968/metering/test_usage_point.py b/test/cim/iec61968/metering/test_usage_point.py index eeee96b3b..667845e93 100644 --- a/test/cim/iec61968/metering/test_usage_point.py +++ b/test/cim/iec61968/metering/test_usage_point.py @@ -12,7 +12,7 @@ from zepben.ewb.model.cim.iec61968.metering.usage_point import UsagePoint from zepben.ewb.model.cim.iec61968.metering.end_device import EndDevice -from cim.cim_creators import ALPHANUM, TEXT_MAX_SIZE, MIN_32_BIT_INTEGER, MAX_32_BIT_INTEGER +from cim.fill_fields import ALPHANUM, TEXT_MAX_SIZE, MIN_32_BIT_INTEGER, MAX_32_BIT_INTEGER from cim.iec61970.base.core.test_identified_object import identified_object_kwargs, verify_identified_object_constructor_default, \ verify_identified_object_constructor_kwargs, verify_identified_object_constructor_args, identified_object_args from cim.private_collection_validator import validate_unordered, validate_unordered_other diff --git a/test/cim/iec61970/base/auxiliaryequipment/test_current_transformer.py b/test/cim/iec61970/base/auxiliaryequipment/test_current_transformer.py index 0a7ba1b7f..b80cb1a05 100644 --- a/test/cim/iec61970/base/auxiliaryequipment/test_current_transformer.py +++ b/test/cim/iec61970/base/auxiliaryequipment/test_current_transformer.py @@ -7,7 +7,7 @@ from hypothesis.strategies import integers from zepben.ewb import CurrentTransformer, CurrentTransformerInfo, generate_id -from cim.cim_creators import MIN_32_BIT_INTEGER, MAX_32_BIT_INTEGER +from cim.fill_fields import MIN_32_BIT_INTEGER, MAX_32_BIT_INTEGER from cim.iec61970.base.auxiliaryequipment.test_sensor import sensor_kwargs, verify_sensor_constructor_default, \ verify_sensor_constructor_kwargs, verify_sensor_constructor_args, sensor_args from cim.property_validator import validate_property_accessor diff --git a/test/cim/iec61970/base/core/test_base_voltage.py b/test/cim/iec61970/base/core/test_base_voltage.py index 71a374a08..fc444a0ff 100644 --- a/test/cim/iec61970/base/core/test_base_voltage.py +++ b/test/cim/iec61970/base/core/test_base_voltage.py @@ -6,7 +6,7 @@ from hypothesis.strategies import integers from zepben.ewb import BaseVoltage, generate_id -from cim.cim_creators import MIN_32_BIT_INTEGER, MAX_32_BIT_INTEGER +from cim.fill_fields import MIN_32_BIT_INTEGER, MAX_32_BIT_INTEGER from cim.iec61970.base.core.test_identified_object import identified_object_kwargs, verify_identified_object_constructor_default, \ verify_identified_object_constructor_kwargs, verify_identified_object_constructor_args, identified_object_args diff --git a/test/cim/iec61970/base/core/test_curve_data.py b/test/cim/iec61970/base/core/test_curve_data.py index 80f7cd5ee..dc0006cf2 100644 --- a/test/cim/iec61970/base/core/test_curve_data.py +++ b/test/cim/iec61970/base/core/test_curve_data.py @@ -7,7 +7,7 @@ from pytest import raises from zepben.ewb import CurveData -from cim.cim_creators import FLOAT_MIN, FLOAT_MAX +from cim.fill_fields import FLOAT_MIN, FLOAT_MAX curve_data_kwargs = { "x_value": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), diff --git a/test/cim/iec61970/base/core/test_equipment.py b/test/cim/iec61970/base/core/test_equipment.py index 5a197a9a4..a6314d084 100644 --- a/test/cim/iec61970/base/core/test_equipment.py +++ b/test/cim/iec61970/base/core/test_equipment.py @@ -6,7 +6,7 @@ from hypothesis.strategies import booleans, lists, builds, datetimes -from cim.cim_creators import sampled_equipment_container, sampled_hvlv_feeder +from cim.fill_fields import sampled_equipment_container, sampled_hvlv_feeder from cim.iec61970.base.core.test_power_system_resource import power_system_resource_kwargs, verify_power_system_resource_constructor_default, \ verify_power_system_resource_constructor_kwargs, verify_power_system_resource_constructor_args, power_system_resource_args from cim.private_collection_validator import validate_unordered @@ -167,4 +167,4 @@ def test_equipmentContainerFilters(): assert [lv_feeder1, lv_feeder2] == list(equipment.normal_lv_feeders) assert [lv_feeder3, lv_feeder4] == list(equipment.current_lv_feeders) assert [substation1, substation2] == list(equipment.substations) - assert [lv_sub1, lv_sub2] == list(equipment.normal_lv_substations) \ No newline at end of file + assert [lv_sub1, lv_sub2] == list(equipment.normal_lv_substations) diff --git a/test/cim/iec61970/base/core/test_identified_object.py b/test/cim/iec61970/base/core/test_identified_object.py index 76ce1fe8b..b5d399622 100644 --- a/test/cim/iec61970/base/core/test_identified_object.py +++ b/test/cim/iec61970/base/core/test_identified_object.py @@ -7,8 +7,12 @@ import pytest from hypothesis.strategies import uuids, text, lists, builds + +from cim.fill_fields import ALPHANUM, TEXT_MAX_SIZE, create_name_type from zepben.ewb import IdentifiedObject, generate_id +from zepben.ewb.model.cim.iec61970.base.core.name_type import Name, NameType from zepben.ewb.model.cim.iec61970.base.wires.junction import Junction + # # NOTE: The following should be called in a chain through the inheritance hierarchy: # 1. verify...default verifies the constructor with no args. @@ -17,9 +21,6 @@ # There is a lot of overlap here, but calling both maximises the constructor combinations we check and should catch any breaking changes to # constructors. # -from zepben.ewb.model.cim.iec61970.base.core.name_type import Name, NameType - -from cim.cim_creators import ALPHANUM, TEXT_MAX_SIZE, create_name_type identified_object_kwargs = { "mrid": uuids(version=4).map(lambda x: str(x)), @@ -49,9 +50,12 @@ def verify_identified_object_constructor_kwargs(io: IdentifiedObject, mrid, name assert io.description == description # Assign identified object to the names we are checking against due to no identified object requirement on Name creation # Note: this is due to automatic two-way association introduced in the name rejig rework - for name in names: - name.identified_object = io - assert list(io.names) == names + if names is not None: + for name in names: + name.identified_object = io + assert list(io.names) == names + else: + assert not list(io.names) def verify_identified_object_constructor_args(io: IdentifiedObject): diff --git a/test/cim/iec61970/base/core/test_name.py b/test/cim/iec61970/base/core/test_name.py index d76f4cc59..1ec36ea2a 100644 --- a/test/cim/iec61970/base/core/test_name.py +++ b/test/cim/iec61970/base/core/test_name.py @@ -11,7 +11,7 @@ from zepben.ewb.model.cim.iec61970.base.core.name import Name from zepben.ewb.model.cim.iec61970.base.core.name_type import NameType -from cim.cim_creators import ALPHANUM, TEXT_MAX_SIZE, sampled_equipment +from cim.fill_fields import ALPHANUM, TEXT_MAX_SIZE, sampled_equipment from cim.iec61970.base.core.test_name_type import name_type_kwargs name_kwargs = { diff --git a/test/cim/iec61970/base/core/test_name_type.py b/test/cim/iec61970/base/core/test_name_type.py index 9d7c0ef53..ec58c98ed 100644 --- a/test/cim/iec61970/base/core/test_name_type.py +++ b/test/cim/iec61970/base/core/test_name_type.py @@ -11,7 +11,7 @@ from zepben.ewb.model.cim.iec61970.base.core.name_type import NameType from zepben.ewb.model.cim.iec61970.base.wires.junction import Junction -from cim.cim_creators import ALPHANUM, TEXT_MAX_SIZE +from cim.fill_fields import ALPHANUM, TEXT_MAX_SIZE name_type_kwargs = { "name": text(alphabet=ALPHANUM, max_size=TEXT_MAX_SIZE), diff --git a/test/cim/iec61970/base/core/test_power_system_resource.py b/test/cim/iec61970/base/core/test_power_system_resource.py index f801e877f..c679fbb2e 100644 --- a/test/cim/iec61970/base/core/test_power_system_resource.py +++ b/test/cim/iec61970/base/core/test_power_system_resource.py @@ -4,7 +4,7 @@ # file, You can obtain one at https://mozilla.org/MPL/2.0/. from hypothesis.strategies import builds, integers, lists -from cim.cim_creators import sampled_wire_info, MIN_32_BIT_INTEGER, MAX_32_BIT_INTEGER +from cim.fill_fields import sampled_wire_info, MIN_32_BIT_INTEGER, MAX_32_BIT_INTEGER from cim.iec61970.base.core.test_identified_object import identified_object_kwargs, verify_identified_object_constructor_default, \ verify_identified_object_constructor_kwargs, verify_identified_object_constructor_args, identified_object_args from cim.private_collection_validator import validate_unordered diff --git a/test/cim/iec61970/base/core/test_terminal.py b/test/cim/iec61970/base/core/test_terminal.py index 3ea4cb346..1c735438f 100644 --- a/test/cim/iec61970/base/core/test_terminal.py +++ b/test/cim/iec61970/base/core/test_terminal.py @@ -5,7 +5,7 @@ from hypothesis import given from hypothesis.strategies import builds, sampled_from, integers -from cim.cim_creators import MIN_32_BIT_INTEGER, MAX_32_BIT_INTEGER +from cim.fill_fields import MIN_32_BIT_INTEGER, MAX_32_BIT_INTEGER from cim.iec61970.base.core.test_ac_dc_terminal import ac_dc_terminal_kwargs, verify_ac_dc_terminal_constructor_default, \ verify_ac_dc_terminal_constructor_kwargs, verify_ac_dc_terminal_constructor_args, ac_dc_terminal_args from util import mrid_strategy diff --git a/test/cim/iec61970/base/diagramlayout/test_diagram_object.py b/test/cim/iec61970/base/diagramlayout/test_diagram_object.py index ec7c81a62..7c89a9a50 100644 --- a/test/cim/iec61970/base/diagramlayout/test_diagram_object.py +++ b/test/cim/iec61970/base/diagramlayout/test_diagram_object.py @@ -5,7 +5,7 @@ from hypothesis import given from hypothesis.strategies import lists, builds, text, floats -from cim.cim_creators import ALPHANUM, TEXT_MAX_SIZE, create_diagram_object_point +from cim.fill_fields import ALPHANUM, TEXT_MAX_SIZE, create_diagram_object_point from cim.iec61970.base.core.test_identified_object import identified_object_kwargs, verify_identified_object_constructor_default, \ verify_identified_object_constructor_kwargs, verify_identified_object_constructor_args, identified_object_args from cim.private_collection_validator import validate_ordered_other diff --git a/test/cim/iec61970/base/diagramlayout/test_diagram_object_point.py b/test/cim/iec61970/base/diagramlayout/test_diagram_object_point.py index 4c2f83f12..b5b103310 100644 --- a/test/cim/iec61970/base/diagramlayout/test_diagram_object_point.py +++ b/test/cim/iec61970/base/diagramlayout/test_diagram_object_point.py @@ -7,7 +7,7 @@ from pytest import raises from zepben.ewb.model.cim.iec61970.base.diagramlayout.diagram_object_point import DiagramObjectPoint -from cim.cim_creators import FLOAT_MIN, FLOAT_MAX +from cim.fill_fields import FLOAT_MIN, FLOAT_MAX diagram_object_point_kwargs = { "x_position": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), diff --git a/test/cim/iec61970/base/equivalents/test_equivalent_branch.py b/test/cim/iec61970/base/equivalents/test_equivalent_branch.py index 371dc0135..51d8f3f74 100644 --- a/test/cim/iec61970/base/equivalents/test_equivalent_branch.py +++ b/test/cim/iec61970/base/equivalents/test_equivalent_branch.py @@ -6,7 +6,7 @@ from hypothesis.strategies import floats from zepben.ewb import EquivalentBranch, generate_id -from cim.cim_creators import FLOAT_MIN, FLOAT_MAX +from cim.fill_fields import FLOAT_MIN, FLOAT_MAX from cim.iec61970.base.equivalents.test_equivalent_equipment import equivalent_equipment_kwargs, verify_equivalent_equipment_constructor_default, \ verify_equivalent_equipment_constructor_kwargs, verify_equivalent_equipment_constructor_args, equivalent_equipment_args diff --git a/test/cim/iec61970/base/meas/test_accumulator_value.py b/test/cim/iec61970/base/meas/test_accumulator_value.py index c5fa8fca2..b1f4c1b35 100644 --- a/test/cim/iec61970/base/meas/test_accumulator_value.py +++ b/test/cim/iec61970/base/meas/test_accumulator_value.py @@ -6,7 +6,7 @@ from hypothesis.strategies import integers, text from zepben.ewb.model.cim.iec61970.base.meas.accumulator_value import AccumulatorValue -from cim.cim_creators import MAX_32_BIT_INTEGER, ALPHANUM, TEXT_MAX_SIZE +from cim.fill_fields import MAX_32_BIT_INTEGER, ALPHANUM, TEXT_MAX_SIZE from cim.iec61970.base.meas.test_measurement_value import measurement_value_kwargs, verify_measurement_value_constructor_default, \ verify_measurement_value_constructor_kwargs, verify_measurement_value_constructor_args, measurement_value_args diff --git a/test/cim/iec61970/base/meas/test_analog_value.py b/test/cim/iec61970/base/meas/test_analog_value.py index fcf8366db..79533baca 100644 --- a/test/cim/iec61970/base/meas/test_analog_value.py +++ b/test/cim/iec61970/base/meas/test_analog_value.py @@ -6,7 +6,7 @@ from hypothesis.strategies import text, floats from zepben.ewb.model.cim.iec61970.base.meas.analog_value import AnalogValue -from cim.cim_creators import ALPHANUM, TEXT_MAX_SIZE, FLOAT_MIN, FLOAT_MAX +from cim.fill_fields import ALPHANUM, TEXT_MAX_SIZE, FLOAT_MIN, FLOAT_MAX from cim.iec61970.base.meas.test_measurement_value import measurement_value_kwargs, verify_measurement_value_constructor_default, \ verify_measurement_value_constructor_kwargs, verify_measurement_value_constructor_args, measurement_value_args diff --git a/test/cim/iec61970/base/meas/test_control.py b/test/cim/iec61970/base/meas/test_control.py index b21276994..3a1405fe7 100644 --- a/test/cim/iec61970/base/meas/test_control.py +++ b/test/cim/iec61970/base/meas/test_control.py @@ -8,7 +8,7 @@ from util import mrid_strategy from zepben.ewb import Control, RemoteControl, generate_id -from cim.cim_creators import ALPHANUM, TEXT_MAX_SIZE +from cim.fill_fields import ALPHANUM, TEXT_MAX_SIZE from cim.iec61970.base.meas.test_io_point import io_point_kwargs, verify_io_point_constructor_default, \ verify_io_point_constructor_kwargs, verify_io_point_constructor_args, io_point_args diff --git a/test/cim/iec61970/base/meas/test_discrete_value.py b/test/cim/iec61970/base/meas/test_discrete_value.py index 405b65270..8df8f0bf1 100644 --- a/test/cim/iec61970/base/meas/test_discrete_value.py +++ b/test/cim/iec61970/base/meas/test_discrete_value.py @@ -6,7 +6,7 @@ from hypothesis.strategies import integers, text from zepben.ewb.model.cim.iec61970.base.meas.discrete_value import DiscreteValue -from cim.cim_creators import MIN_32_BIT_INTEGER, MAX_32_BIT_INTEGER, ALPHANUM, TEXT_MAX_SIZE +from cim.fill_fields import MIN_32_BIT_INTEGER, MAX_32_BIT_INTEGER, ALPHANUM, TEXT_MAX_SIZE from cim.iec61970.base.meas.test_measurement_value import measurement_value_kwargs, verify_measurement_value_constructor_default, \ verify_measurement_value_constructor_kwargs, verify_measurement_value_constructor_args, measurement_value_args diff --git a/test/cim/iec61970/base/meas/test_measurement.py b/test/cim/iec61970/base/meas/test_measurement.py index 58753216b..49e6538aa 100644 --- a/test/cim/iec61970/base/meas/test_measurement.py +++ b/test/cim/iec61970/base/meas/test_measurement.py @@ -8,7 +8,7 @@ from util import mrid_strategy from zepben.ewb import Measurement, RemoteSource, PhaseCode, UnitSymbol, generate_id -from cim.cim_creators import ALPHANUM, TEXT_MAX_SIZE +from cim.fill_fields import ALPHANUM, TEXT_MAX_SIZE from cim.iec61970.base.core.test_identified_object import identified_object_kwargs, verify_identified_object_constructor_default, \ verify_identified_object_constructor_kwargs, verify_identified_object_constructor_args, identified_object_args diff --git a/test/cim/iec61970/base/protection/test_current_relay.py b/test/cim/iec61970/base/protection/test_current_relay.py index 734daed21..93d95288e 100644 --- a/test/cim/iec61970/base/protection/test_current_relay.py +++ b/test/cim/iec61970/base/protection/test_current_relay.py @@ -6,7 +6,7 @@ from hypothesis.strategies import floats, booleans from zepben.ewb import CurrentRelay, ProtectionKind, generate_id -from cim.cim_creators import FLOAT_MIN, FLOAT_MAX +from cim.fill_fields import FLOAT_MIN, FLOAT_MAX from cim.iec61970.base.protection.test_protection_relay_function import protection_relay_function_kwargs, protection_relay_function_args, \ verify_protection_relay_function_constructor_default, verify_protection_relay_function_constructor_kwargs, verify_protection_relay_function_constructor_args diff --git a/test/cim/iec61970/base/protection/test_distance_relay.py b/test/cim/iec61970/base/protection/test_distance_relay.py index e03a69cd2..aefd83348 100644 --- a/test/cim/iec61970/base/protection/test_distance_relay.py +++ b/test/cim/iec61970/base/protection/test_distance_relay.py @@ -6,7 +6,7 @@ from hypothesis.strategies import floats from zepben.ewb import DistanceRelay, generate_id -from cim.cim_creators import FLOAT_MIN, FLOAT_MAX +from cim.fill_fields import FLOAT_MIN, FLOAT_MAX from cim.iec61970.base.protection.test_protection_relay_function import protection_relay_function_kwargs, protection_relay_function_args, \ verify_protection_relay_function_constructor_default, verify_protection_relay_function_constructor_kwargs, verify_protection_relay_function_constructor_args diff --git a/test/cim/iec61970/base/protection/test_protection_relay_function.py b/test/cim/iec61970/base/protection/test_protection_relay_function.py index 20a22bbc8..8b3f345e4 100644 --- a/test/cim/iec61970/base/protection/test_protection_relay_function.py +++ b/test/cim/iec61970/base/protection/test_protection_relay_function.py @@ -2,9 +2,9 @@ # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at https://mozilla.org/MPL/2.0/. -from hypothesis.strategies import floats, sampled_from, booleans, lists, builds, text +from hypothesis.strategies import floats, sampled_from, booleans, lists, builds, text, one_of, none -from cim.cim_creators import FLOAT_MIN, FLOAT_MAX, ALPHANUM, TEXT_MAX_SIZE, boolean_or_none +from cim.fill_fields import FLOAT_MIN, FLOAT_MAX, ALPHANUM, TEXT_MAX_SIZE from cim.iec61970.base.core.test_power_system_resource import power_system_resource_kwargs, verify_power_system_resource_constructor_default, \ verify_power_system_resource_constructor_kwargs, verify_power_system_resource_constructor_args, power_system_resource_args from cim.private_collection_validator import validate_unordered, validate_ordered_other @@ -16,7 +16,7 @@ protection_relay_function_kwargs = { **power_system_resource_kwargs, "model": text(alphabet=ALPHANUM, max_size=TEXT_MAX_SIZE), - "reclosing": boolean_or_none(), + "reclosing": one_of(none(), booleans()), "relay_delay_time": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), "protection_kind": sampled_from(ProtectionKind), "directable": booleans(), diff --git a/test/cim/iec61970/base/wires/generation/production/test_battery_unit.py b/test/cim/iec61970/base/wires/generation/production/test_battery_unit.py index 3815f7fee..b2d97e1a9 100644 --- a/test/cim/iec61970/base/wires/generation/production/test_battery_unit.py +++ b/test/cim/iec61970/base/wires/generation/production/test_battery_unit.py @@ -5,7 +5,7 @@ from hypothesis import given from hypothesis.strategies import integers, sampled_from, builds, lists -from cim.cim_creators import MAX_32_BIT_INTEGER +from cim.fill_fields import MAX_32_BIT_INTEGER from cim.iec61970.base.wires.generation.production.test_power_electronics_unit import power_electronics_unit_kwargs, \ verify_power_electronics_unit_constructor_default, verify_power_electronics_unit_constructor_kwargs, verify_power_electronics_unit_constructor_args, \ power_electronics_unit_args diff --git a/test/cim/iec61970/base/wires/generation/production/test_power_electronics_unit.py b/test/cim/iec61970/base/wires/generation/production/test_power_electronics_unit.py index 4e9c2d024..601757649 100644 --- a/test/cim/iec61970/base/wires/generation/production/test_power_electronics_unit.py +++ b/test/cim/iec61970/base/wires/generation/production/test_power_electronics_unit.py @@ -7,7 +7,7 @@ from util import mrid_strategy from zepben.ewb import PowerElectronicsUnit, PowerElectronicsConnection, generate_id -from cim.cim_creators import MIN_32_BIT_INTEGER, MAX_32_BIT_INTEGER +from cim.fill_fields import MIN_32_BIT_INTEGER, MAX_32_BIT_INTEGER from cim.iec61970.base.core.test_equipment import equipment_kwargs, verify_equipment_constructor_default, \ verify_equipment_constructor_kwargs, verify_equipment_constructor_args, equipment_args diff --git a/test/cim/iec61970/base/wires/test_ac_line_segment_phase.py b/test/cim/iec61970/base/wires/test_ac_line_segment_phase.py index 422c0be45..ba48eab78 100644 --- a/test/cim/iec61970/base/wires/test_ac_line_segment_phase.py +++ b/test/cim/iec61970/base/wires/test_ac_line_segment_phase.py @@ -5,7 +5,7 @@ from hypothesis import given from hypothesis.strategies import integers, builds -from cim.cim_creators import sampled_single_phase_kind, MIN_SEQUENCE_NUMBER, MAX_SEQUENCE_NUMBER +from cim.fill_fields import sampled_single_phase_kind, MIN_SEQUENCE_NUMBER, MAX_SEQUENCE_NUMBER from cim.iec61970.base.core.test_identified_object import identified_object_kwargs from cim.iec61970.base.core.test_power_system_resource import verify_power_system_resource_constructor_default, verify_power_system_resource_constructor_kwargs, \ verify_power_system_resource_constructor_args, power_system_resource_kwargs, power_system_resource_args @@ -55,4 +55,3 @@ def test_ac_line_segment_phase_constructor_args(): als.sequence_number, als.ac_line_segment, ] - diff --git a/test/cim/iec61970/base/wires/test_breaker.py b/test/cim/iec61970/base/wires/test_breaker.py index f8336d5bb..17385fa18 100644 --- a/test/cim/iec61970/base/wires/test_breaker.py +++ b/test/cim/iec61970/base/wires/test_breaker.py @@ -7,7 +7,7 @@ from zepben.ewb import Breaker, Substation, Terminal, generate_id from zepben.ewb.model.cim.iec61970.base.core.feeder import Feeder -from cim.cim_creators import FLOAT_MIN, FLOAT_MAX +from cim.fill_fields import FLOAT_MIN, FLOAT_MAX from cim.iec61970.base.wires.test_protected_switch import verify_protected_switch_constructor_default, \ verify_protected_switch_constructor_kwargs, verify_protected_switch_constructor_args, protected_switch_kwargs, protected_switch_args diff --git a/test/cim/iec61970/base/wires/test_conductor.py b/test/cim/iec61970/base/wires/test_conductor.py index b51c2c142..25156af3a 100644 --- a/test/cim/iec61970/base/wires/test_conductor.py +++ b/test/cim/iec61970/base/wires/test_conductor.py @@ -7,7 +7,7 @@ from cim.iec61970.base.core.test_conducting_equipment import conducting_equipment_kwargs, verify_conducting_equipment_constructor_default, \ verify_conducting_equipment_constructor_kwargs, verify_conducting_equipment_constructor_args, conducting_equipment_args from cim.property_validator import validate_property_accessor -from cim.cim_creators import FLOAT_MIN, FLOAT_MAX, MIN_32_BIT_INTEGER, MAX_32_BIT_INTEGER +from cim.fill_fields import FLOAT_MIN, FLOAT_MAX, MIN_32_BIT_INTEGER, MAX_32_BIT_INTEGER from zepben.ewb import WireInfo from zepben.ewb.model.cim.iec61970.base.wires.conductor import Conductor diff --git a/test/cim/iec61970/base/wires/test_earth_fault_compensator.py b/test/cim/iec61970/base/wires/test_earth_fault_compensator.py index 4b0e5d92b..6c8f3bdf8 100644 --- a/test/cim/iec61970/base/wires/test_earth_fault_compensator.py +++ b/test/cim/iec61970/base/wires/test_earth_fault_compensator.py @@ -5,7 +5,7 @@ from hypothesis.strategies import floats, one_of, none from zepben.ewb import EarthFaultCompensator -from cim.cim_creators import FLOAT_MIN, FLOAT_MAX +from cim.fill_fields import FLOAT_MIN, FLOAT_MAX from cim.iec61970.base.core.test_conducting_equipment import conducting_equipment_kwargs, conducting_equipment_args, \ verify_conducting_equipment_constructor_default, verify_conducting_equipment_constructor_kwargs, verify_conducting_equipment_constructor_args diff --git a/test/cim/iec61970/base/wires/test_energy_consumer.py b/test/cim/iec61970/base/wires/test_energy_consumer.py index a91df63e8..187f39dd2 100644 --- a/test/cim/iec61970/base/wires/test_energy_consumer.py +++ b/test/cim/iec61970/base/wires/test_energy_consumer.py @@ -9,7 +9,7 @@ from zepben.ewb import EnergyConsumer, PhaseShuntConnectionKind, generate_id from zepben.ewb.model.cim.iec61970.base.wires.energy_consumer_phase import EnergyConsumerPhase -from cim.cim_creators import MIN_32_BIT_INTEGER, MAX_32_BIT_INTEGER, FLOAT_MIN, FLOAT_MAX +from cim.fill_fields import MIN_32_BIT_INTEGER, MAX_32_BIT_INTEGER, FLOAT_MIN, FLOAT_MAX from cim.iec61970.base.wires.test_energy_connection import verify_energy_connection_constructor_default, \ verify_energy_connection_constructor_kwargs, verify_energy_connection_constructor_args, energy_connection_kwargs, energy_connection_args from cim.private_collection_validator import validate_unordered diff --git a/test/cim/iec61970/base/wires/test_energy_source.py b/test/cim/iec61970/base/wires/test_energy_source.py index c645237af..58d9b4c06 100644 --- a/test/cim/iec61970/base/wires/test_energy_source.py +++ b/test/cim/iec61970/base/wires/test_energy_source.py @@ -8,7 +8,7 @@ from util import mrid_strategy from zepben.ewb import EnergySource, EnergySourcePhase, generate_id -from cim.cim_creators import FLOAT_MIN, FLOAT_MAX +from cim.fill_fields import FLOAT_MIN, FLOAT_MAX from cim.iec61970.base.wires.test_energy_connection import verify_energy_connection_constructor_default, \ verify_energy_connection_constructor_kwargs, verify_energy_connection_constructor_args, energy_connection_kwargs, energy_connection_args from cim.private_collection_validator import validate_unordered diff --git a/test/cim/iec61970/base/wires/test_grounding_impedance.py b/test/cim/iec61970/base/wires/test_grounding_impedance.py index 57de96a67..600b5eb94 100644 --- a/test/cim/iec61970/base/wires/test_grounding_impedance.py +++ b/test/cim/iec61970/base/wires/test_grounding_impedance.py @@ -6,7 +6,7 @@ from hypothesis.strategies import floats, one_of, none from zepben.ewb import GroundingImpedance -from cim.cim_creators import FLOAT_MIN, FLOAT_MAX +from cim.fill_fields import FLOAT_MIN, FLOAT_MAX from cim.iec61970.base.wires.test_earth_fault_compensator import earth_fault_compensator_kwargs, earth_fault_compensator_args, \ verify_earth_fault_compensator_constructor_default, verify_earth_fault_compensator_constructor_kwargs, verify_earth_fault_compensator_constructor_args diff --git a/test/cim/iec61970/base/wires/test_linear_shunt_compensator.py b/test/cim/iec61970/base/wires/test_linear_shunt_compensator.py index ea6fe736e..3404c4c66 100644 --- a/test/cim/iec61970/base/wires/test_linear_shunt_compensator.py +++ b/test/cim/iec61970/base/wires/test_linear_shunt_compensator.py @@ -4,22 +4,13 @@ # file, You can obtain one at https://mozilla.org/MPL/2.0/. from hypothesis import given -from hypothesis.strategies import floats -from zepben.ewb import generate_id +from zepben.ewb import generate_id, PhaseCode from zepben.ewb.model.cim.iec61970.base.wires.linear_shunt_compensator import LinearShuntCompensator -from cim.cim_creators import FLOAT_MIN, FLOAT_MAX +from cim.fill_fields import linear_shunt_compensator_kwargs from cim.iec61970.base.wires.test_shunt_compensator import verify_shunt_compensator_constructor_default, \ - verify_shunt_compensator_constructor_kwargs, verify_shunt_compensator_constructor_args, shunt_compensator_kwargs, shunt_compensator_args - -linear_shunt_compensator_kwargs = { - **shunt_compensator_kwargs, - "b0_per_section": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - "b_per_section": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - "g0_per_section": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - "g_per_section": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX) -} + verify_shunt_compensator_constructor_kwargs, verify_shunt_compensator_constructor_args, shunt_compensator_args linear_shunt_compensator_args = [*shunt_compensator_args, 1.1, 2.2, 3.3, 4.4] @@ -34,8 +25,18 @@ def test_linear_shunt_compensator_constructor_default(): assert lsc.g_per_section is None -@given(**linear_shunt_compensator_kwargs) +@given(**linear_shunt_compensator_kwargs()) def test_linear_shunt_compensator_constructor_kwargs(b0_per_section, b_per_section, g0_per_section, g_per_section, **kwargs): + # + # NOTE: The grounding terminal must be one of the included terminals, with phases N. If it isn't, the automated processes + # will add the terminal and cause the tests to fail. If the phases are N, it will reject the invalid phases. + # + if kwargs["terminals"]: + kwargs["grounding_terminal"] = kwargs["terminals"][-1] + kwargs["grounding_terminal"].phases = PhaseCode.N + else: + kwargs["grounding_terminal"] = None + lsc = LinearShuntCompensator( b0_per_section=b0_per_section, b_per_section=b_per_section, diff --git a/test/cim/iec61970/base/wires/test_per_length_sequence_impedance.py b/test/cim/iec61970/base/wires/test_per_length_sequence_impedance.py index a3d4040fa..5d19b8576 100644 --- a/test/cim/iec61970/base/wires/test_per_length_sequence_impedance.py +++ b/test/cim/iec61970/base/wires/test_per_length_sequence_impedance.py @@ -8,7 +8,7 @@ from zepben.ewb import generate_id from zepben.ewb.model.cim.iec61970.base.wires.per_length_sequence_impedance import PerLengthSequenceImpedance -from cim.cim_creators import FLOAT_MIN, FLOAT_MAX +from cim.fill_fields import FLOAT_MIN, FLOAT_MAX from cim.iec61970.base.wires.test_per_length_impedance import verify_per_length_impedance_constructor_default, \ verify_per_length_impedance_constructor_kwargs, verify_per_length_impedance_constructor_args, per_length_impedance_kwargs, per_length_impedance_args diff --git a/test/cim/iec61970/base/wires/test_petersen_coil.py b/test/cim/iec61970/base/wires/test_petersen_coil.py index 84935550b..ac81dcf22 100644 --- a/test/cim/iec61970/base/wires/test_petersen_coil.py +++ b/test/cim/iec61970/base/wires/test_petersen_coil.py @@ -6,7 +6,7 @@ from hypothesis.strategies import floats, one_of, none from zepben.ewb import PetersenCoil -from cim.cim_creators import FLOAT_MIN, FLOAT_MAX +from cim.fill_fields import FLOAT_MIN, FLOAT_MAX from cim.iec61970.base.wires.test_earth_fault_compensator import earth_fault_compensator_kwargs, earth_fault_compensator_args, \ verify_earth_fault_compensator_constructor_default, verify_earth_fault_compensator_constructor_kwargs, verify_earth_fault_compensator_constructor_args diff --git a/test/cim/iec61970/base/wires/test_phase_impedance_data.py b/test/cim/iec61970/base/wires/test_phase_impedance_data.py index ed7ce3d6e..6aae30618 100644 --- a/test/cim/iec61970/base/wires/test_phase_impedance_data.py +++ b/test/cim/iec61970/base/wires/test_phase_impedance_data.py @@ -7,7 +7,7 @@ from pytest import raises from zepben.ewb import SinglePhaseKind -from cim.cim_creators import FLOAT_MIN, FLOAT_MAX +from cim.fill_fields import FLOAT_MIN, FLOAT_MAX from zepben.ewb.model.cim.iec61970.base.wires.phase_impedance_data import PhaseImpedanceData phase_impedance_data_kwargs = { diff --git a/test/cim/iec61970/base/wires/test_power_electronics_connection.py b/test/cim/iec61970/base/wires/test_power_electronics_connection.py index 181e13355..bc62f8ebf 100644 --- a/test/cim/iec61970/base/wires/test_power_electronics_connection.py +++ b/test/cim/iec61970/base/wires/test_power_electronics_connection.py @@ -12,7 +12,7 @@ from zepben.ewb import PowerElectronicsUnit, BatteryUnit, PowerElectronicsConnection, generate_id from zepben.ewb.model.cim.iec61970.base.wires.power_electronics_connection_phase import PowerElectronicsConnectionPhase -from cim.cim_creators import MIN_32_BIT_INTEGER, MAX_32_BIT_INTEGER, FLOAT_MIN, FLOAT_MAX, ALPHANUM, TEXT_MAX_SIZE +from cim.fill_fields import MIN_32_BIT_INTEGER, MAX_32_BIT_INTEGER, FLOAT_MIN, FLOAT_MAX, ALPHANUM, TEXT_MAX_SIZE from cim.iec61970.base.wires.test_regulating_cond_eq import verify_regulating_cond_eq_constructor_default, \ verify_regulating_cond_eq_constructor_kwargs, verify_regulating_cond_eq_constructor_args, regulating_cond_eq_kwargs, regulating_cond_eq_args from cim.private_collection_validator import validate_unordered diff --git a/test/cim/iec61970/base/wires/test_power_transformer.py b/test/cim/iec61970/base/wires/test_power_transformer.py index d422ab302..f21496fae 100644 --- a/test/cim/iec61970/base/wires/test_power_transformer.py +++ b/test/cim/iec61970/base/wires/test_power_transformer.py @@ -10,7 +10,7 @@ from zepben.ewb import PowerTransformer, VectorGroup, PowerTransformerEnd, PowerTransformerInfo, TransformerConstructionKind, TransformerFunctionKind, \ Terminal, generate_id -from cim.cim_creators import FLOAT_MIN, FLOAT_MAX +from cim.fill_fields import FLOAT_MIN, FLOAT_MAX from cim.iec61970.base.core.test_conducting_equipment import verify_conducting_equipment_constructor_default, \ verify_conducting_equipment_constructor_kwargs, verify_conducting_equipment_constructor_args, conducting_equipment_kwargs, conducting_equipment_args from cim.property_validator import validate_property_accessor diff --git a/test/cim/iec61970/base/wires/test_power_transformer_end.py b/test/cim/iec61970/base/wires/test_power_transformer_end.py index d20214776..dfddf0699 100644 --- a/test/cim/iec61970/base/wires/test_power_transformer_end.py +++ b/test/cim/iec61970/base/wires/test_power_transformer_end.py @@ -13,7 +13,7 @@ from zepben.ewb import PowerTransformerEnd, PowerTransformer, WindingConnection, TransformerCoolingType, generate_id from zepben.ewb.model.cim.extensions.iec61970.base.wires.transformer_end_rated_s import TransformerEndRatedS -from cim.cim_creators import MIN_32_BIT_INTEGER, MAX_32_BIT_INTEGER, FLOAT_MIN, FLOAT_MAX +from cim.fill_fields import MIN_32_BIT_INTEGER, MAX_32_BIT_INTEGER, FLOAT_MIN, FLOAT_MAX from cim.iec61970.base.wires.test_transformer_end import verify_transformer_end_constructor_default, \ verify_transformer_end_constructor_kwargs, verify_transformer_end_constructor_args, transformer_end_kwargs, transformer_end_args from cim.private_collection_validator import validate_unordered_other diff --git a/test/cim/iec61970/base/wires/test_protected_switch.py b/test/cim/iec61970/base/wires/test_protected_switch.py index 82bfa5248..6c9478011 100644 --- a/test/cim/iec61970/base/wires/test_protected_switch.py +++ b/test/cim/iec61970/base/wires/test_protected_switch.py @@ -7,7 +7,7 @@ from util import mrid_strategy from zepben.ewb import ProtectionRelayFunction, ProtectedSwitch, generate_id -from cim.cim_creators import MIN_32_BIT_INTEGER, MAX_32_BIT_INTEGER +from cim.fill_fields import MIN_32_BIT_INTEGER, MAX_32_BIT_INTEGER from cim.iec61970.base.wires.test_switch import switch_kwargs, verify_switch_constructor_default, verify_switch_constructor_kwargs, \ verify_switch_constructor_args, switch_args from cim.private_collection_validator import validate_unordered diff --git a/test/cim/iec61970/base/wires/test_ratio_tap_changer.py b/test/cim/iec61970/base/wires/test_ratio_tap_changer.py index 1c740d259..e4051fc4b 100644 --- a/test/cim/iec61970/base/wires/test_ratio_tap_changer.py +++ b/test/cim/iec61970/base/wires/test_ratio_tap_changer.py @@ -10,7 +10,7 @@ from zepben.ewb.model.cim.iec61970.base.wires.transformer_end import TransformerEnd from zepben.ewb.model.cim.iec61970.base.wires.ratio_tap_changer import RatioTapChanger -from cim.cim_creators import FLOAT_MIN, FLOAT_MAX +from cim.fill_fields import FLOAT_MIN, FLOAT_MAX from cim.iec61970.base.wires.test_tap_changer import verify_tap_changer_constructor_default, \ verify_tap_changer_constructor_kwargs, verify_tap_changer_constructor_args, tap_changer_kwargs, tap_changer_args, assume_step_values diff --git a/test/cim/iec61970/base/wires/test_regulating_control.py b/test/cim/iec61970/base/wires/test_regulating_control.py index ac8d1dc60..72ef1c4d0 100644 --- a/test/cim/iec61970/base/wires/test_regulating_control.py +++ b/test/cim/iec61970/base/wires/test_regulating_control.py @@ -4,7 +4,7 @@ # file, You can obtain one at https://mozilla.org/MPL/2.0/. from hypothesis.strategies import booleans, sampled_from, floats, builds, lists -from cim.cim_creators import sampled_phase_code, FLOAT_MAX, FLOAT_MIN +from cim.fill_fields import sampled_phase_code, FLOAT_MAX, FLOAT_MIN from cim.iec61970.base.core.test_power_system_resource import power_system_resource_args, verify_power_system_resource_constructor_default, \ verify_power_system_resource_constructor_kwargs, power_system_resource_kwargs, verify_power_system_resource_constructor_args from cim.private_collection_validator import validate_unordered diff --git a/test/cim/iec61970/base/wires/test_rotating_machine.py b/test/cim/iec61970/base/wires/test_rotating_machine.py index 6c6cafe14..1cf98fac0 100644 --- a/test/cim/iec61970/base/wires/test_rotating_machine.py +++ b/test/cim/iec61970/base/wires/test_rotating_machine.py @@ -5,7 +5,7 @@ from hypothesis.strategies import floats, one_of, none, integers from zepben.ewb import RotatingMachine -from cim.cim_creators import FLOAT_MIN, FLOAT_MAX, MIN_32_BIT_INTEGER, MAX_32_BIT_INTEGER +from cim.fill_fields import FLOAT_MIN, FLOAT_MAX, MIN_32_BIT_INTEGER, MAX_32_BIT_INTEGER from cim.iec61970.base.wires.test_regulating_cond_eq import regulating_cond_eq_kwargs, regulating_cond_eq_args, \ verify_regulating_cond_eq_constructor_default, verify_regulating_cond_eq_constructor_kwargs, verify_regulating_cond_eq_constructor_args diff --git a/test/cim/iec61970/base/wires/test_series_compensator.py b/test/cim/iec61970/base/wires/test_series_compensator.py index 5a08a56df..59624fe81 100644 --- a/test/cim/iec61970/base/wires/test_series_compensator.py +++ b/test/cim/iec61970/base/wires/test_series_compensator.py @@ -7,7 +7,7 @@ from hypothesis.strategies import floats, integers from zepben.ewb import SeriesCompensator, generate_id -from cim.cim_creators import FLOAT_MIN, FLOAT_MAX, MIN_32_BIT_INTEGER, MAX_32_BIT_INTEGER +from cim.fill_fields import FLOAT_MIN, FLOAT_MAX, MIN_32_BIT_INTEGER, MAX_32_BIT_INTEGER from cim.iec61970.base.core.test_conducting_equipment import verify_conducting_equipment_constructor_default, \ verify_conducting_equipment_constructor_kwargs, verify_conducting_equipment_constructor_args, conducting_equipment_kwargs, conducting_equipment_args diff --git a/test/cim/iec61970/base/wires/test_shunt_compensator.py b/test/cim/iec61970/base/wires/test_shunt_compensator.py index 29b87c506..e4429d76f 100644 --- a/test/cim/iec61970/base/wires/test_shunt_compensator.py +++ b/test/cim/iec61970/base/wires/test_shunt_compensator.py @@ -3,24 +3,10 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at https://mozilla.org/MPL/2.0/. -from hypothesis.strategies import floats, booleans, integers, sampled_from, builds - -from util import mrid_strategy -from zepben.ewb import ShuntCompensator, PhaseShuntConnectionKind, ShuntCompensatorInfo, Terminal, generate_id - -from cim.cim_creators import MIN_32_BIT_INTEGER, MAX_32_BIT_INTEGER -from cim.iec61970.base.wires.test_regulating_cond_eq import regulating_cond_eq_kwargs, verify_regulating_cond_eq_constructor_default, \ +from cim.iec61970.base.wires.test_regulating_cond_eq import verify_regulating_cond_eq_constructor_default, \ verify_regulating_cond_eq_constructor_kwargs, verify_regulating_cond_eq_constructor_args, regulating_cond_eq_args from cim.property_validator import validate_property_accessor - -shunt_compensator_kwargs = { - **regulating_cond_eq_kwargs, - "grounded": booleans(), - "nom_u": integers(min_value=MIN_32_BIT_INTEGER, max_value=MAX_32_BIT_INTEGER), - "phase_connection": sampled_from(PhaseShuntConnectionKind), - "grounding_terminal": builds(Terminal, mrid=mrid_strategy), - "sections": floats(min_value=-100.0, max_value=100.0), -} +from zepben.ewb import ShuntCompensator, PhaseShuntConnectionKind, ShuntCompensatorInfo, Terminal, generate_id shunt_compensator_args = [*regulating_cond_eq_args, True, 1, PhaseShuntConnectionKind.G, Terminal(mrid=generate_id()), 2.2] diff --git a/test/cim/iec61970/base/wires/test_static_var_compensator.py b/test/cim/iec61970/base/wires/test_static_var_compensator.py index f5066ad96..8c59ba1c8 100644 --- a/test/cim/iec61970/base/wires/test_static_var_compensator.py +++ b/test/cim/iec61970/base/wires/test_static_var_compensator.py @@ -6,7 +6,7 @@ from hypothesis.strategies import floats, integers, sampled_from from zepben.ewb import SVCControlMode, StaticVarCompensator, generate_id -from cim.cim_creators import MIN_32_BIT_INTEGER, MAX_32_BIT_INTEGER, FLOAT_MAX, FLOAT_MIN +from cim.fill_fields import MIN_32_BIT_INTEGER, MAX_32_BIT_INTEGER, FLOAT_MAX, FLOAT_MIN from cim.iec61970.base.wires.test_regulating_cond_eq import regulating_cond_eq_kwargs, verify_regulating_cond_eq_constructor_default, \ verify_regulating_cond_eq_constructor_kwargs, verify_regulating_cond_eq_constructor_args, regulating_cond_eq_args diff --git a/test/cim/iec61970/base/wires/test_switch.py b/test/cim/iec61970/base/wires/test_switch.py index 6e592c63a..3fc9fa933 100644 --- a/test/cim/iec61970/base/wires/test_switch.py +++ b/test/cim/iec61970/base/wires/test_switch.py @@ -5,7 +5,7 @@ from hypothesis.strategies import integers, floats from zepben.ewb import Switch, SinglePhaseKind, SwitchInfo, generate_id -from cim.cim_creators import MAX_32_BIT_INTEGER +from cim.fill_fields import MAX_32_BIT_INTEGER from cim.iec61970.base.core.test_conducting_equipment import conducting_equipment_kwargs, verify_conducting_equipment_constructor_default, \ verify_conducting_equipment_constructor_kwargs, verify_conducting_equipment_constructor_args, conducting_equipment_args from cim.property_validator import validate_property_accessor diff --git a/test/cim/iec61970/base/wires/test_synchronous_machine.py b/test/cim/iec61970/base/wires/test_synchronous_machine.py index 830f2efda..8170d7b89 100644 --- a/test/cim/iec61970/base/wires/test_synchronous_machine.py +++ b/test/cim/iec61970/base/wires/test_synchronous_machine.py @@ -8,7 +8,7 @@ from util import mrid_strategy from zepben.ewb import SynchronousMachine, SynchronousMachineKind, ReactiveCapabilityCurve -from cim.cim_creators import FLOAT_MIN, FLOAT_MAX, MIN_32_BIT_INTEGER, MAX_32_BIT_INTEGER +from cim.fill_fields import FLOAT_MIN, FLOAT_MAX, MIN_32_BIT_INTEGER, MAX_32_BIT_INTEGER from cim.iec61970.base.wires.test_rotating_machine import rotating_machine_kwargs, rotating_machine_args, \ verify_rotating_machine_constructor_default, verify_rotating_machine_constructor_kwargs, verify_rotating_machine_constructor_args from cim.private_collection_validator import validate_unordered diff --git a/test/cim/iec61970/base/wires/test_tap_changer.py b/test/cim/iec61970/base/wires/test_tap_changer.py index fafb111ef..8d2f10b16 100644 --- a/test/cim/iec61970/base/wires/test_tap_changer.py +++ b/test/cim/iec61970/base/wires/test_tap_changer.py @@ -12,7 +12,7 @@ from zepben.ewb import TapChangerControl, generate_id from zepben.ewb.model.cim.iec61970.base.wires.tap_changer import TapChanger -from cim.cim_creators import MIN_32_BIT_INTEGER, MAX_32_BIT_INTEGER +from cim.fill_fields import MIN_32_BIT_INTEGER, MAX_32_BIT_INTEGER from cim.iec61970.base.core.test_power_system_resource import power_system_resource_kwargs, verify_power_system_resource_constructor_default, \ verify_power_system_resource_constructor_kwargs, verify_power_system_resource_constructor_args, power_system_resource_args diff --git a/test/cim/iec61970/base/wires/test_tap_changer_control.py b/test/cim/iec61970/base/wires/test_tap_changer_control.py index da5694d30..6aef029ad 100644 --- a/test/cim/iec61970/base/wires/test_tap_changer_control.py +++ b/test/cim/iec61970/base/wires/test_tap_changer_control.py @@ -3,24 +3,24 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at https://mozilla.org/MPL/2.0/. from hypothesis import given -from hypothesis.strategies import integers, floats +from hypothesis.strategies import integers, floats, one_of, none, booleans from zepben.ewb import TapChangerControl, generate_id -from cim.cim_creators import MIN_32_BIT_INTEGER, MAX_32_BIT_INTEGER, FLOAT_MIN, FLOAT_MAX, boolean_or_none +from cim.fill_fields import MIN_32_BIT_INTEGER, MAX_32_BIT_INTEGER, FLOAT_MIN, FLOAT_MAX from cim.iec61970.base.wires.test_regulating_control import regulating_control_kwargs, regulating_control_args, verify_regulating_control_constructor_default, \ verify_regulating_control_constructor_kwargs, verify_regulating_control_constructor_args tap_changer_control_kwargs = { **regulating_control_kwargs, "limit_voltage": integers(min_value=MIN_32_BIT_INTEGER, max_value=MAX_32_BIT_INTEGER), - "line_drop_compensation": boolean_or_none(), + "line_drop_compensation": one_of(none(), booleans()), "line_drop_r": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), "line_drop_x": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), "reverse_line_drop_r": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), "reverse_line_drop_x": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - "forward_ldc_blocking": boolean_or_none(), + "forward_ldc_blocking": one_of(none(), booleans()), "time_delay": floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), - "co_generation_enabled": boolean_or_none() + "co_generation_enabled": one_of(none(), booleans()) } tap_changer_control_args = [*regulating_control_args, 1, False, 2.2, 3.3, 4.4, 5.5, True, 6.6, False] diff --git a/test/cim/iec61970/base/wires/test_transformer_end.py b/test/cim/iec61970/base/wires/test_transformer_end.py index 1422cad24..69295a1a3 100644 --- a/test/cim/iec61970/base/wires/test_transformer_end.py +++ b/test/cim/iec61970/base/wires/test_transformer_end.py @@ -10,7 +10,7 @@ from zepben.ewb.model.cim.iec61970.base.wires.transformer_end import TransformerEnd from zepben.ewb.model.cim.iec61970.base.wires.ratio_tap_changer import RatioTapChanger -from cim.cim_creators import FLOAT_MIN, FLOAT_MAX, MIN_32_BIT_INTEGER, MAX_32_BIT_INTEGER +from cim.fill_fields import FLOAT_MIN, FLOAT_MAX, MIN_32_BIT_INTEGER, MAX_32_BIT_INTEGER from cim.iec61970.base.core.test_identified_object import identified_object_kwargs, verify_identified_object_constructor_default, \ verify_identified_object_constructor_kwargs, verify_identified_object_constructor_args, identified_object_args diff --git a/test/cim/iec61970/base/wires/test_transformer_star_impedance.py b/test/cim/iec61970/base/wires/test_transformer_star_impedance.py index 3df767930..0bb65f6c7 100644 --- a/test/cim/iec61970/base/wires/test_transformer_star_impedance.py +++ b/test/cim/iec61970/base/wires/test_transformer_star_impedance.py @@ -8,7 +8,7 @@ from util import mrid_strategy from zepben.ewb import TransformerStarImpedance, TransformerEndInfo, generate_id -from cim.cim_creators import FLOAT_MIN, FLOAT_MAX +from cim.fill_fields import FLOAT_MIN, FLOAT_MAX from cim.iec61970.base.core.test_identified_object import identified_object_kwargs, verify_identified_object_constructor_default, \ verify_identified_object_constructor_kwargs, verify_identified_object_constructor_args, identified_object_args diff --git a/test/database/sqlite/customer/test_customer_database_schema.py b/test/database/sqlite/customer/test_customer_database_schema.py index 9b611fb8e..d9bb95c91 100644 --- a/test/database/sqlite/customer/test_customer_database_schema.py +++ b/test/database/sqlite/customer/test_customer_database_schema.py @@ -7,7 +7,7 @@ from hypothesis import given, settings, HealthCheck -from cim.cim_creators import create_organisation, create_customer, create_customer_agreement, create_pricing_structure, create_tariffs +from cim.fill_fields import create_organisation, create_customer, create_customer_agreement, create_pricing_structure, create_tariffs from database.sqlite.common.cim_database_schema_common_tests import CimDatabaseSchemaCommonTests, TComparator, TService, TReader, TWriter from database.sqlite.schema_utils import SchemaNetworks from zepben.ewb import IdentifiedObject, CustomerAgreement, PricingStructure, Tariff, Organisation, Customer, CustomerDatabaseReader, \ diff --git a/test/database/sqlite/diagram/test_diagram_database_schema.py b/test/database/sqlite/diagram/test_diagram_database_schema.py index 781ab9169..593df8d46 100644 --- a/test/database/sqlite/diagram/test_diagram_database_schema.py +++ b/test/database/sqlite/diagram/test_diagram_database_schema.py @@ -7,7 +7,7 @@ from hypothesis import given, settings, HealthCheck -from cim.cim_creators import create_diagram, create_diagram_object +from cim.fill_fields import create_diagram, create_diagram_object from database.sqlite.common.cim_database_schema_common_tests import CimDatabaseSchemaCommonTests, TComparator, TService, TReader, TWriter from database.sqlite.schema_utils import SchemaNetworks from zepben.ewb import IdentifiedObject, DiagramDatabaseReader, DiagramDatabaseWriter, DiagramService diff --git a/test/database/sqlite/network/test_network_database_schema.py b/test/database/sqlite/network/test_network_database_schema.py index fbc1ecf47..236b67979 100644 --- a/test/database/sqlite/network/test_network_database_schema.py +++ b/test/database/sqlite/network/test_network_database_schema.py @@ -13,7 +13,7 @@ import pytest from hypothesis import given, settings, HealthCheck, assume -from cim.cim_creators import create_cable_info, create_no_load_test, create_open_circuit_test, create_overhead_wire_info, create_power_transformer_info, \ +from cim.fill_fields import create_cable_info, create_no_load_test, create_open_circuit_test, create_overhead_wire_info, create_power_transformer_info, \ create_short_circuit_test, create_shunt_compensator_info, create_transformer_end_info, create_transformer_tank_info, create_asset_owner, create_pole, \ create_streetlight, create_location, create_organisation, create_meter, create_usage_point, create_operational_restriction, create_fault_indicator, \ create_base_voltage, create_connectivity_node, create_feeder, create_geographical_region, create_site, create_sub_geographical_region, create_substation, \ diff --git a/test/services/customer/translator/test_customer_translator.py b/test/services/customer/translator/test_customer_translator.py index 08d25d27e..9dc4dce11 100644 --- a/test/services/customer/translator/test_customer_translator.py +++ b/test/services/customer/translator/test_customer_translator.py @@ -9,7 +9,7 @@ from zepben.ewb.services.common.translator.base_proto2cim import get_nullable from zepben.ewb.services.customer.customer_service_comparator import CustomerServiceComparator -from cim.cim_creators import * +from cim.fill_fields import * from services.common.translator.base_test_translator import validate_service_translations T = TypeVar("T", bound=IdentifiedObject) diff --git a/test/services/diagram/translator/test_diagram_translator.py b/test/services/diagram/translator/test_diagram_translator.py index 568201262..0401967cf 100644 --- a/test/services/diagram/translator/test_diagram_translator.py +++ b/test/services/diagram/translator/test_diagram_translator.py @@ -8,7 +8,7 @@ from zepben.ewb.services.common.translator.base_proto2cim import get_nullable from zepben.ewb.services.diagram.diagram_service_comparator import DiagramServiceComparator -from cim.cim_creators import * +from cim.fill_fields import * from services.common.translator.base_test_translator import validate_service_translations T = TypeVar("T", bound=IdentifiedObject) diff --git a/test/services/network/translator/test_network_translator.py b/test/services/network/translator/test_network_translator.py index fc3fa69c7..c4052ce77 100644 --- a/test/services/network/translator/test_network_translator.py +++ b/test/services/network/translator/test_network_translator.py @@ -6,9 +6,8 @@ import pytest -from cim.cim_creators import create_directional_current_relay, create_hv_customer, create_ac_line_segment_phase, create_lv_substation from services.common.translator.base_test_translator import validate_service_translations -from test.cim.cim_creators import * +from test.cim.fill_fields import * from zepben.ewb import IdentifiedObject, PowerTransformerEnd, PowerTransformer, NetworkService, NetworkServiceComparator, NameType, \ NetworkDatabaseTables, TableAssetOrganisationRolesAssets, TableCircuitsSubstations, TableCircuitsTerminals, \ TableEquipmentEquipmentContainers, TableEquipmentOperationalRestrictions, TableEquipmentUsagePoints, TableLoopsSubstations, \ From 926f8806cdb41b001fe41cef2730d026f4fbf212 Mon Sep 17 00:00:00 2001 From: Anthony Charlton Date: Thu, 26 Mar 2026 09:24:04 +1100 Subject: [PATCH 10/26] Fixed typing with private validators Signed-off-by: Anthony Charlton --- .../iec61968/common/test_contact_details.py | 6 +- test/cim/iec61968/assets/test_pole.py | 2 +- test/cim/iec61968/customers/test_customer.py | 2 +- .../customers/test_pricing_structure.py | 2 +- test/cim/iec61968/metering/test_end_device.py | 4 +- .../cim/iec61968/metering/test_usage_point.py | 6 +- test/cim/iec61970/base/core/test_equipment.py | 8 +- .../base/core/test_power_system_resource.py | 2 +- .../test_protection_relay_function.py | 6 +- .../production/test_battery_unit.py | 2 +- .../base/wires/test_energy_consumer.py | 2 +- .../iec61970/base/wires/test_energy_source.py | 2 +- .../test_power_electronics_connection.py | 4 +- .../base/wires/test_protected_switch.py | 2 +- .../base/wires/test_regulating_control.py | 2 +- .../base/wires/test_synchronous_machine.py | 2 +- test/cim/private_collection_validator.py | 141 +++++++++--------- 17 files changed, 98 insertions(+), 97 deletions(-) diff --git a/test/cim/extensions/iec61968/common/test_contact_details.py b/test/cim/extensions/iec61968/common/test_contact_details.py index 38482f830..631a2e80b 100644 --- a/test/cim/extensions/iec61968/common/test_contact_details.py +++ b/test/cim/extensions/iec61968/common/test_contact_details.py @@ -111,9 +111,11 @@ def get_phone_number(it: ContactDetails, number: str): return tn raise KeyError(number) + # ContactDetails isn't an IdentifiedObject, but it has an `id` as its first arg, so it works (just with lots of type errors). + # noinspection PyTypeChecker validate_unordered_other( ContactDetails, - lambda it: TelephoneNumber(local_number=it), + lambda it: TelephoneNumber(local_number=str(it)), ContactDetails.phone_numbers, ContactDetails.num_phone_numbers, get_phone_number, @@ -131,6 +133,8 @@ def get_electronic_address(it: ContactDetails, number: str): return tn raise KeyError(number) + # ContactDetails isn't an IdentifiedObject, but it has an `id` as its first arg, so it works (just with lots of type errors). + # noinspection PyTypeChecker validate_unordered_other( ContactDetails, lambda it: ElectronicAddress(email1=it), diff --git a/test/cim/iec61968/assets/test_pole.py b/test/cim/iec61968/assets/test_pole.py index a2ee313a4..633836bc1 100644 --- a/test/cim/iec61968/assets/test_pole.py +++ b/test/cim/iec61968/assets/test_pole.py @@ -54,7 +54,7 @@ def test_pole_constructor_args(): def test_streetlights_collection(): validate_unordered( Pole, - lambda mrid: Streetlight(mrid), + Streetlight, Pole.streetlights, Pole.num_streetlights, Pole.get_streetlight, diff --git a/test/cim/iec61968/customers/test_customer.py b/test/cim/iec61968/customers/test_customer.py index 78d11b3a3..3a40023d2 100644 --- a/test/cim/iec61968/customers/test_customer.py +++ b/test/cim/iec61968/customers/test_customer.py @@ -63,7 +63,7 @@ def test_customer_constructor_args(): def test_customer_agreements_collection(): validate_unordered( Customer, - lambda mrid: CustomerAgreement(mrid), + CustomerAgreement, Customer.agreements, Customer.num_agreements, Customer.get_agreement, diff --git a/test/cim/iec61968/customers/test_pricing_structure.py b/test/cim/iec61968/customers/test_pricing_structure.py index f52c61161..8ae6adacf 100644 --- a/test/cim/iec61968/customers/test_pricing_structure.py +++ b/test/cim/iec61968/customers/test_pricing_structure.py @@ -57,7 +57,7 @@ def test_pricing_structure_constructor_args(): def test_tariffs_collection(): validate_unordered( PricingStructure, - lambda mrid: Tariff(mrid), + Tariff, PricingStructure.tariffs, PricingStructure.num_tariffs, PricingStructure.get_tariff, diff --git a/test/cim/iec61968/metering/test_end_device.py b/test/cim/iec61968/metering/test_end_device.py index 450354131..c05a93e31 100644 --- a/test/cim/iec61968/metering/test_end_device.py +++ b/test/cim/iec61968/metering/test_end_device.py @@ -51,7 +51,7 @@ def verify_end_device_constructor_args(ed: EndDevice): def test_usage_points_collection(): validate_unordered( EndDevice, - lambda mrid: UsagePoint(mrid), + UsagePoint, EndDevice.usage_points, EndDevice.num_usage_points, EndDevice.get_usage_point, @@ -64,7 +64,7 @@ def test_usage_points_collection(): def test_end_device_function_collection(): validate_unordered( EndDevice, - lambda mrid: EndDeviceFunction(mrid), + EndDeviceFunction, EndDevice.functions, EndDevice.num_functions, EndDevice.get_function, diff --git a/test/cim/iec61968/metering/test_usage_point.py b/test/cim/iec61968/metering/test_usage_point.py index 667845e93..d0d339091 100644 --- a/test/cim/iec61968/metering/test_usage_point.py +++ b/test/cim/iec61968/metering/test_usage_point.py @@ -98,7 +98,7 @@ def test_usage_point_constructor_args(): def test_equipment_collection(): validate_unordered( UsagePoint, - lambda mrid: Equipment(mrid), + Equipment, UsagePoint.equipment, UsagePoint.num_equipment, UsagePoint.get_equipment, @@ -111,7 +111,7 @@ def test_equipment_collection(): def test_end_devices_collection(): validate_unordered( UsagePoint, - lambda mrid: EndDevice(mrid), + EndDevice, UsagePoint.end_devices, UsagePoint.num_end_devices, UsagePoint.get_end_device, @@ -123,7 +123,7 @@ def test_end_devices_collection(): def test_contacts_collection(): validate_unordered_other( UsagePoint, - lambda _id: ContactDetails(_id), + lambda _id: ContactDetails(mrid=str(_id)), UsagePoint.contacts, UsagePoint.num_contacts, UsagePoint.get_contact, diff --git a/test/cim/iec61970/base/core/test_equipment.py b/test/cim/iec61970/base/core/test_equipment.py index a6314d084..5cea2969a 100644 --- a/test/cim/iec61970/base/core/test_equipment.py +++ b/test/cim/iec61970/base/core/test_equipment.py @@ -78,7 +78,7 @@ def verify_equipment_constructor_args(eq: Equipment): def test_usage_points_collection(): validate_unordered( Equipment, - lambda mrid: UsagePoint(mrid), + UsagePoint, Equipment.usage_points, Equipment.num_usage_points, Equipment.get_usage_point, @@ -91,7 +91,7 @@ def test_usage_points_collection(): def test_equipment_containers_collection(): validate_unordered( Equipment, - lambda mrid: EquipmentContainer(mrid), + EquipmentContainer, Equipment.containers, Equipment.num_containers, Equipment.get_container, @@ -104,7 +104,7 @@ def test_equipment_containers_collection(): def test_operational_restrictions_collection(): validate_unordered( Equipment, - lambda mrid: OperationalRestriction(mrid), + OperationalRestriction, Equipment.operational_restrictions, Equipment.num_operational_restrictions, Equipment.get_operational_restriction, @@ -117,7 +117,7 @@ def test_operational_restrictions_collection(): def test_current_containers_collection(): validate_unordered( Equipment, - lambda mrid: EquipmentContainer(mrid), + EquipmentContainer, Equipment.current_containers, Equipment.num_current_containers, Equipment.get_current_container, diff --git a/test/cim/iec61970/base/core/test_power_system_resource.py b/test/cim/iec61970/base/core/test_power_system_resource.py index c679fbb2e..092334e95 100644 --- a/test/cim/iec61970/base/core/test_power_system_resource.py +++ b/test/cim/iec61970/base/core/test_power_system_resource.py @@ -57,7 +57,7 @@ def verify_power_system_resource_constructor_args(psr: PowerSystemResource): def test_assets_collection(): validate_unordered( PowerSystemResource, - lambda mrid: Asset(mrid), + Asset, PowerSystemResource.assets, PowerSystemResource.num_assets, PowerSystemResource.get_asset, diff --git a/test/cim/iec61970/base/protection/test_protection_relay_function.py b/test/cim/iec61970/base/protection/test_protection_relay_function.py index 8b3f345e4..bf630e199 100644 --- a/test/cim/iec61970/base/protection/test_protection_relay_function.py +++ b/test/cim/iec61970/base/protection/test_protection_relay_function.py @@ -108,7 +108,7 @@ def verify_protection_relay_function_constructor_args(prf: ProtectionRelayFuncti def test_sensors_collection(): validate_unordered( ProtectionRelayFunction, - lambda mrid: Sensor(mrid), + Sensor, ProtectionRelayFunction.sensors, ProtectionRelayFunction.num_sensors, ProtectionRelayFunction.get_sensor, @@ -121,7 +121,7 @@ def test_sensors_collection(): def test_protected_switches_collection(): validate_unordered( ProtectionRelayFunction, - lambda mrid: ProtectedSwitch(mrid), + ProtectedSwitch, ProtectionRelayFunction.protected_switches, ProtectionRelayFunction.num_protected_switches, ProtectionRelayFunction.get_protected_switch, @@ -134,7 +134,7 @@ def test_protected_switches_collection(): def test_scheme_collection(): validate_unordered( ProtectionRelayFunction, - lambda mrid: ProtectionRelayScheme(mrid), + ProtectionRelayScheme, ProtectionRelayFunction.schemes, ProtectionRelayFunction.num_schemes, ProtectionRelayFunction.get_scheme, diff --git a/test/cim/iec61970/base/wires/generation/production/test_battery_unit.py b/test/cim/iec61970/base/wires/generation/production/test_battery_unit.py index b2d97e1a9..c4eaaac3d 100644 --- a/test/cim/iec61970/base/wires/generation/production/test_battery_unit.py +++ b/test/cim/iec61970/base/wires/generation/production/test_battery_unit.py @@ -66,7 +66,7 @@ def test_battery_unit_constructor_args(): def test_battery_control_collection(): validate_unordered( BatteryUnit, - lambda mrid: BatteryControl(mrid), + BatteryControl, BatteryUnit.controls, BatteryUnit.num_battery_controls, BatteryUnit.get_control, diff --git a/test/cim/iec61970/base/wires/test_energy_consumer.py b/test/cim/iec61970/base/wires/test_energy_consumer.py index 187f39dd2..c1811995b 100644 --- a/test/cim/iec61970/base/wires/test_energy_consumer.py +++ b/test/cim/iec61970/base/wires/test_energy_consumer.py @@ -87,7 +87,7 @@ def test_energy_consumer_constructor_args(): def test_phases_collection(): validate_unordered( EnergyConsumer, - lambda mrid: EnergyConsumerPhase(mrid), + EnergyConsumerPhase, EnergyConsumer.phases, EnergyConsumer.num_phases, EnergyConsumer.get_phase, diff --git a/test/cim/iec61970/base/wires/test_energy_source.py b/test/cim/iec61970/base/wires/test_energy_source.py index 58d9b4c06..0c9229c38 100644 --- a/test/cim/iec61970/base/wires/test_energy_source.py +++ b/test/cim/iec61970/base/wires/test_energy_source.py @@ -206,7 +206,7 @@ def test_energy_source_constructor_args(): def test_phases_collection(): validate_unordered( EnergySource, - lambda mrid: EnergySourcePhase(mrid), + EnergySourcePhase, EnergySource.phases, EnergySource.num_phases, EnergySource.get_phase, diff --git a/test/cim/iec61970/base/wires/test_power_electronics_connection.py b/test/cim/iec61970/base/wires/test_power_electronics_connection.py index bc62f8ebf..cd9f31197 100644 --- a/test/cim/iec61970/base/wires/test_power_electronics_connection.py +++ b/test/cim/iec61970/base/wires/test_power_electronics_connection.py @@ -285,7 +285,7 @@ def test_power_electronics_connection_constructor_args(): def test_power_electronics_units_collection(): validate_unordered( PowerElectronicsConnection, - lambda mrid: PowerElectronicsUnit(mrid), + PowerElectronicsUnit, PowerElectronicsConnection.units, PowerElectronicsConnection.num_units, PowerElectronicsConnection.get_unit, @@ -298,7 +298,7 @@ def test_power_electronics_units_collection(): def test_power_electronics_connection_phases_collection(): validate_unordered( PowerElectronicsConnection, - lambda mrid: PowerElectronicsConnectionPhase(mrid), + PowerElectronicsConnectionPhase, PowerElectronicsConnection.phases, PowerElectronicsConnection.num_phases, PowerElectronicsConnection.get_phase, diff --git a/test/cim/iec61970/base/wires/test_protected_switch.py b/test/cim/iec61970/base/wires/test_protected_switch.py index 6c9478011..7cfbb8a8a 100644 --- a/test/cim/iec61970/base/wires/test_protected_switch.py +++ b/test/cim/iec61970/base/wires/test_protected_switch.py @@ -46,7 +46,7 @@ def verify_protected_switch_constructor_args(ps: ProtectedSwitch): def test_relay_function_collection(): validate_unordered( ProtectedSwitch, - lambda mrid: ProtectionRelayFunction(mrid), + ProtectionRelayFunction, ProtectedSwitch.relay_functions, ProtectedSwitch.num_relay_functions, ProtectedSwitch.get_relay_function, diff --git a/test/cim/iec61970/base/wires/test_regulating_control.py b/test/cim/iec61970/base/wires/test_regulating_control.py index 72ef1c4d0..92728f687 100644 --- a/test/cim/iec61970/base/wires/test_regulating_control.py +++ b/test/cim/iec61970/base/wires/test_regulating_control.py @@ -119,7 +119,7 @@ def test_regulating_control_regulating_conducting_equipment(): # noinspection PyArgumentList validate_unordered( RegulatingControl, - lambda mrid: RegulatingCondEq(mrid), + RegulatingCondEq, RegulatingControl.regulating_conducting_equipment, RegulatingControl.num_regulating_cond_eq, RegulatingControl.get_regulating_cond_eq, diff --git a/test/cim/iec61970/base/wires/test_synchronous_machine.py b/test/cim/iec61970/base/wires/test_synchronous_machine.py index 8170d7b89..754b4dee6 100644 --- a/test/cim/iec61970/base/wires/test_synchronous_machine.py +++ b/test/cim/iec61970/base/wires/test_synchronous_machine.py @@ -183,7 +183,7 @@ def verify_synchronous_machine_constructor_args(): def test_curves_collection(): validate_unordered( SynchronousMachine, - lambda mrid: ReactiveCapabilityCurve(mrid), + ReactiveCapabilityCurve, SynchronousMachine.curves, SynchronousMachine.num_curves, SynchronousMachine.get_curve, diff --git a/test/cim/private_collection_validator.py b/test/cim/private_collection_validator.py index 372c4d5ca..b9cd7a2ca 100644 --- a/test/cim/private_collection_validator.py +++ b/test/cim/private_collection_validator.py @@ -6,7 +6,6 @@ from collections import Counter from enum import Enum from typing import TypeVar, Callable, Generator, List, Dict, Union, Type, Tuple, Any -from unittest import case import pytest @@ -37,44 +36,44 @@ class DuplicateBehaviour(Enum): def validate_unordered( - create_it: Union[Callable[[str], TIdentifiedObject], Type[IdentifiedObject]], - create_other: Callable[[str], UIdentifiedObject], - get_all: property, # Callable[[TIdentifiedObject], Generator[UIdentifiedObject, None, None]] - num: Callable[..., int], # Callable[[TIdentifiedObject], int] - get_by_id: Callable[..., UIdentifiedObject], # Callable[[TIdentifiedObject, str], UIdentifiedObject] - add: Callable[..., TIdentifiedObject], # Callable[[TIdentifiedObject, UIdentifiedObject], TIdentifiedObject] - remove: Callable[..., TIdentifiedObject], # Callable[[TIdentifiedObject, UIdentifiedObject], TIdentifiedObject] - clear: Callable[..., TIdentifiedObject], # Callable[[TIdentifiedObject], TIdentifiedObject] + create_it: Type[IdentifiedObject] | Callable[[str], TIdentifiedObject], + create_other: Type[UIdentifiedObject] | Callable[[str], UIdentifiedObject], + get_all: Callable[[TIdentifiedObject], Generator[UIdentifiedObject, None, None]] | Callable[[], Generator[UIdentifiedObject, None, None]] | property, + num: Callable[[TIdentifiedObject], int] | Callable[[], int], + get_by_id: Callable[[TIdentifiedObject, str], UIdentifiedObject] | Callable[[str], UIdentifiedObject], + add: Callable[[TIdentifiedObject, UIdentifiedObject], TIdentifiedObject] | Callable[[UIdentifiedObject], TIdentifiedObject], + remove: Callable[[TIdentifiedObject, UIdentifiedObject], TIdentifiedObject] | Callable[[UIdentifiedObject], TIdentifiedObject], + clear: Callable[[TIdentifiedObject], TIdentifiedObject] | Callable[[], TIdentifiedObject], ): """ Validate the internal collection for an associated :class:`IdentifiedObject` that has no order significance. - NOTE: The callables using `...` do so to work around bugs in the type checking of both the IDE and mypy, where passing a reference to the - class method doesn't recognise it needs the `self` parameter, and therefore marks the parameter as having the incorrect type. Actual - signatures are stored in comments against the arguments. + NOTE: The callables below use unions with a second callable to work around bugs in the type checking of both the IDE and mypy, where passing a reference to + the class method doesn't recognise it needs the `self` parameter, and would otherwise mark the parameter as having the incorrect type. If we move to a + newer version where this is resolved, the second callable should be removed. """ _validate_unordered(create_it, create_other, get_all.fget, num, get_by_id, add, remove, clear) def validate_unordered_other( - create_it: Union[Callable[[str], TIdentifiedObject], Type[IdentifiedObject]], + create_it: Union[Callable[[str], TIdentifiedObject], Type[TIdentifiedObject]], create_other: Callable[[int], UOther], - get_all: property, # Callable[[TIdentifiedObject], Generator[UOther, None, None]] - num: Callable[..., int], # Callable[[TIdentifiedObject], int] - get_by_key: Callable[..., UOther], # Callable[[TIdentifiedObject, K], UOther] - add: Callable[..., TIdentifiedObject], # Callable[[TIdentifiedObject, UOther], TIdentifiedObject] - remove: Callable[..., TIdentifiedObject], # Callable[[TIdentifiedObject, UOther], TIdentifiedObject] - clear: Callable[..., TIdentifiedObject], # Callable[[TIdentifiedObject], TIdentifiedObject] - get_key: Callable[..., K], # Callable[[UOther], K] + get_all: Callable[[TIdentifiedObject], Generator[UOther, None, None]] | Callable[[], Generator[UOther, None, None]] | property, + num: Callable[[TIdentifiedObject], int] | Callable[[], int], + get_by_key: Callable[[TIdentifiedObject, K], UOther] | Callable[[K], UOther], + add: Callable[[TIdentifiedObject, UOther], TIdentifiedObject] | Callable[[UOther], TIdentifiedObject], + remove: Callable[[TIdentifiedObject, UOther], TIdentifiedObject] | Callable[[UOther], TIdentifiedObject], + clear: Callable[[TIdentifiedObject], TIdentifiedObject] | Callable[[], TIdentifiedObject], + get_key: Callable[[UOther], K] | Callable[[], K], key_to_str: Callable[[K], str] = str, duplicate_behaviour: Type[DuplicateBehaviour] = DuplicateBehaviour.THROWS, ): """ Validate the internal collection for an associated object that is not an [IdentifiedObject] that has no order significance. - NOTE: The callables using `...` do so to work around bugs in the type checking of both the IDE and mypy, where passing a reference to the - class method doesn't recognise it needs the `self` parameter, and therefore marks the parameter as having the incorrect type. Actual - signatures are stored in comments against the arguments. + NOTE: The callables below use unions with a second callable to work around bugs in the type checking of both the IDE and mypy, where passing a reference to + the class method doesn't recognise it needs the `self` parameter, and would otherwise mark the parameter as having the incorrect type. If we move to a + newer version where this is resolved, the second callable should be removed. """ _validate_unordered_other(create_it, create_other, get_all.fget, num, get_by_key, add, remove, clear, get_key, key_to_str, duplicate_behaviour) @@ -82,14 +81,14 @@ class method doesn't recognise it needs the `self` parameter, and therefore mark def validate_ordered( create_it: Union[Callable[[str], TIdentifiedObject], Type[IdentifiedObject]], create_other: Callable[[str, int], UIdentifiedObject], - get_all: property, # Callable[[TIdentifiedObject], Generator[UIdentifiedObject, None, None]] - num: Callable[..., int], # Callable[[TIdentifiedObject], int] - get_by_id: Callable[..., UIdentifiedObject], # Callable[[TIdentifiedObject, str], UIdentifiedObject] - get_by_index: Callable[..., UIdentifiedObject], # Callable[[TIdentifiedObject, int], UIdentifiedObject] - add: Callable[..., TIdentifiedObject], # Callable[[TIdentifiedObject, UIdentifiedObject], TIdentifiedObject] - remove: Callable[..., TIdentifiedObject], # Callable[[TIdentifiedObject, UIdentifiedObject], TIdentifiedObject] - clear: Callable[..., TIdentifiedObject], # Callable[[TIdentifiedObject], TIdentifiedObject] - index_of: Callable[..., int], # Callable[[UIdentifiedObject], int] + get_all: Callable[[TIdentifiedObject], Generator[UIdentifiedObject, None, None]] | Callable[[], Generator[UIdentifiedObject, None, None]] | property, + num: Callable[[TIdentifiedObject], int] | Callable[[], int], + get_by_id: Callable[[TIdentifiedObject, str], UIdentifiedObject] | Callable[[str], UIdentifiedObject], + get_by_index: Callable[[TIdentifiedObject, int], UIdentifiedObject] | Callable[[int], UIdentifiedObject], + add: Callable[[TIdentifiedObject, UIdentifiedObject], TIdentifiedObject] | Callable[[UIdentifiedObject], TIdentifiedObject], + remove: Callable[[TIdentifiedObject, UIdentifiedObject], TIdentifiedObject] | Callable[[UIdentifiedObject], TIdentifiedObject], + clear: Callable[[TIdentifiedObject], TIdentifiedObject] | Callable[[], TIdentifiedObject], + index_of: Callable[[UIdentifiedObject], int] | Callable[[], int] ): """ Validate the internal collection for an associated :class:`IdentifiedObject` that has order significance, baked into the object itself, not just @@ -97,9 +96,9 @@ def validate_ordered( NOTE: Baked in index is expected to be 1-based, not 0-based. - NOTE: The callables using `...` do so to work around bugs in the type checking of both the IDE and mypy, where passing a reference to the - class method doesn't recognise it needs the `self` parameter, and therefore marks the parameter as having the incorrect type. Actual - signatures are stored in comments against the arguments. + NOTE: The callables below use unions with a second callable to work around bugs in the type checking of both the IDE and mypy, where passing a reference to + the class method doesn't recognise it needs the `self` parameter, and would otherwise mark the parameter as having the incorrect type. If we move to a + newer version where this is resolved, the second callable should be removed. """ _validate_ordered(create_it, create_other, get_all.fget, num, get_by_id, get_by_index, add, remove, clear, index_of) @@ -107,24 +106,24 @@ class method doesn't recognise it needs the `self` parameter, and therefore mark def validate_ordered_other( create_it: Union[Callable[[str], TIdentifiedObject], Type[IdentifiedObject]], create_other: Callable[[int], UOther], - get_all: property, # Callable[[TIdentifiedObject], Generator[UOther, None, None]] - num: Callable[..., int], # Callable[[TIdentifiedObject], int] - get_by_index: Callable[..., UOther], # Callable[[TIdentifiedObject, int], UOther] - for_each: Callable[..., None], # Callable[[TIdentifiedObject, Callable[[int, UOther], None]], None] - add: Callable[..., TIdentifiedObject], # Callable[[TIdentifiedObject, UOther], TIdentifiedObject] - add_with_index: Callable[..., TIdentifiedObject], # Callable[[TIdentifiedObject, UOther, int], TIdentifiedObject] - remove: Callable[..., TIdentifiedObject], # Callable[[TIdentifiedObject, UOther], TIdentifiedObject] - remove_at_index: Callable[..., UOther], # Callable[[TIdentifiedObject, int], UOther] - clear: Callable[..., TIdentifiedObject], # Callable[[TIdentifiedObject], TIdentifiedObject] + get_all: Callable[[TIdentifiedObject], Generator[UOther, None, None]] | Callable[[], Generator[UOther, None, None]] | property, + num: Callable[[TIdentifiedObject], int] | Callable[[], int], + get_by_index: Callable[[TIdentifiedObject, int], UOther] | Callable[[int], UOther], + for_each: Callable[[TIdentifiedObject, Callable[[int, UOther], None]], None] | Callable[[Callable[[int, UOther], None]], None], + add: Callable[[TIdentifiedObject, UOther], TIdentifiedObject] | Callable[[UOther], TIdentifiedObject], + add_with_index: Callable[[TIdentifiedObject, UOther, int], TIdentifiedObject] | Callable[[UOther, int], TIdentifiedObject], + remove: Callable[[TIdentifiedObject, UOther], TIdentifiedObject] | Callable[[UOther], TIdentifiedObject], + remove_at_index: Callable[[TIdentifiedObject, int], UOther] | Callable[[int], UOther], + clear: Callable[[TIdentifiedObject], TIdentifiedObject] | Callable[[], TIdentifiedObject], ): """ Validate the internal collection for an associated object that is not an :class:`IdentifiedObject` that has order significance. NOTE: Positional index is expected to be 0-based, not 1-based. - NOTE: The callables using `...` do so to work around bugs in the type checking of both the IDE and mypy, where passing a reference to the - class method doesn't recognise it needs the `self` parameter, and therefore marks the parameter as having the incorrect type. Actual - signatures are stored in comments against the arguments. + NOTE: The callables below use unions with a second callable to work around bugs in the type checking of both the IDE and mypy, where passing a reference to + the class method doesn't recognise it needs the `self` parameter, and would otherwise mark the parameter as having the incorrect type. If we move to a + newer version where this is resolved, the second callable should be removed. """ _validate_ordered_other(create_it, create_other, get_all.fget, num, get_by_index, for_each, add, add_with_index, remove, remove_at_index, clear) @@ -142,9 +141,9 @@ def _validate_unordered( """ Validate the internal collection for an associated :class:`IdentifiedObject` that has no order significance. - NOTE: The callables using `...` do so to work around bugs in the type checking of both the IDE and mypy, where passing a reference to the - class method doesn't recognise it needs the `self` parameter, and therefore marks the parameter as having the incorrect type. Actual - signatures are stored in comments against the arguments. + NOTE: The callables below use unions with a second callable to work around bugs in the type checking of both the IDE and mypy, where passing a reference to + the class method doesn't recognise it needs the `self` parameter, and would otherwise mark the parameter as having the incorrect type. If we move to a + newer version where this is resolved, the second callable should be removed. """ it = create_it("test") other1 = create_other("1") @@ -187,26 +186,25 @@ def validate_after_removal(): ) -# -# NOTE: The callables using `...` do so to work around bugs in the type checking of both the IDE and mypy, where passing a reference to the -# class method doesn't recognise it needs the `self` parameter, and therefore marks the parameter as having the incorrect type. Actual -# signatures are stored in comments against the arguments. -# def _validate_unordered_other( create_it: Union[Callable[[str], TIdentifiedObject], Type[IdentifiedObject]], create_other: Callable[[int], UOther], get_all: Callable[[TIdentifiedObject], Generator[UOther, None, None]], - num: Callable[..., int], # Callable[[TIdentifiedObject], int] - get_by_key: Callable[..., UOther], # Callable[[TIdentifiedObject, K], UOther] - add: Callable[..., TIdentifiedObject], # Callable[[TIdentifiedObject, UOther], TIdentifiedObject] - remove: Callable[..., TIdentifiedObject], # Callable[[TIdentifiedObject, UOther], TIdentifiedObject] - clear: Callable[..., TIdentifiedObject], # Callable[[TIdentifiedObject], TIdentifiedObject] - get_key: Callable[..., K], # Callable[[UOther], K] + num: Callable[[TIdentifiedObject], int] | Callable[[], int], + get_by_key: Callable[[TIdentifiedObject, K], UOther] | Callable[[K], UOther], + add: Callable[[TIdentifiedObject, UOther], TIdentifiedObject] | Callable[[UOther], TIdentifiedObject], + remove: Callable[[TIdentifiedObject, UOther], TIdentifiedObject] | Callable[[UOther], TIdentifiedObject], + clear: Callable[[TIdentifiedObject], TIdentifiedObject] | Callable[[], TIdentifiedObject], + get_key: Callable[[UOther], K] | Callable[[], K], key_to_str: Callable[[K], str] = str, duplicate_behaviour: Type[DuplicateBehaviour] = DuplicateBehaviour.THROWS ): """ Validate the internal collection for an associated object that is not an [IdentifiedObject] that has no order significance. + + NOTE: The callables below use unions with a second callable to work around bugs in the type checking of both the IDE and mypy, where passing a reference to + the class method doesn't recognise it needs the `self` parameter, and would otherwise mark the parameter as having the incorrect type. If we move to a + newer version where this is resolved, the second callable should be removed. """ it = create_it("test") other1 = create_other(1) @@ -258,27 +256,26 @@ def duplicate_behaviour_func() -> Callable: ) -# -# NOTE: The callables using `...` do so to work around bugs in the type checking of both the IDE and mypy, where passing a reference to the -# class method doesn't recognise it needs the `self` parameter, and therefore marks the parameter as having the incorrect type. Actual -# signatures are stored in comments against the arguments. -# def _validate_ordered( create_it: Union[Callable[[str], TIdentifiedObject], Type[IdentifiedObject]], create_other: Callable[[str, int], UIdentifiedObject], get_all: Callable[[TIdentifiedObject], Generator[UIdentifiedObject, None, None]], - num: Callable[..., int], # Callable[[TIdentifiedObject], int] - get_by_id: Callable[[..., str], UIdentifiedObject], # Callable[[TIdentifiedObject, str], UIdentifiedObject] - get_by_index: Callable[[..., int], UIdentifiedObject], # Callable[[TIdentifiedObject, int], UIdentifiedObject] - add: Callable[[..., UIdentifiedObject], TIdentifiedObject], # Callable[[TIdentifiedObject, UIdentifiedObject], TIdentifiedObject] - remove: Callable[[..., UIdentifiedObject], TIdentifiedObject], # Callable[[TIdentifiedObject, UIdentifiedObject], TIdentifiedObject] - clear: Callable[..., TIdentifiedObject], # Callable[[TIdentifiedObject], TIdentifiedObject] - index_of: Callable[..., int], # Callable[[UIdentifiedObject], int] + num: Callable[[TIdentifiedObject], int] | Callable[[], int], + get_by_id: Callable[[TIdentifiedObject, str], UIdentifiedObject] | Callable[[str], UIdentifiedObject], + get_by_index: Callable[[TIdentifiedObject, int], UIdentifiedObject] | Callable[[int], UIdentifiedObject], + add: Callable[[TIdentifiedObject, UIdentifiedObject], TIdentifiedObject] | Callable[[UIdentifiedObject], TIdentifiedObject], + remove: Callable[[TIdentifiedObject, UIdentifiedObject], TIdentifiedObject] | Callable[[UIdentifiedObject], TIdentifiedObject], + clear: Callable[[TIdentifiedObject], TIdentifiedObject] | Callable[[], TIdentifiedObject], + index_of: Callable[[UIdentifiedObject], int] | Callable[[], int], ): """ Validate the internal collection for an associated :class:`IdentifiedObject` that has order significance, baked into the object itself, not just the placement in the collection. + NOTE: The callables below use unions with a second callable to work around bugs in the type checking of both the IDE and mypy, where passing a reference to + the class method doesn't recognise it needs the `self` parameter, and would otherwise mark the parameter as having the incorrect type. If we move to a + newer version where this is resolved, the second callable should be removed. + NOTE: Baked in index is expected to be 1-based, not 0-based. """ it = create_it("test") From cf9b9ca8a7f8cfbb7f282f0e131a23945bce8b6e Mon Sep 17 00:00:00 2001 From: Anthony Charlton Date: Thu, 26 Mar 2026 09:28:00 +1100 Subject: [PATCH 11/26] Fixed errors in network translator testing of LvFeeder to LvSubstation. Signed-off-by: Anthony Charlton --- .../common/translator/base_test_translator.py | 1 + .../test_network_service_comparator.py | 226 +++++++++--------- .../translator/test_network_translator.py | 2 + 3 files changed, 119 insertions(+), 110 deletions(-) diff --git a/test/services/common/translator/base_test_translator.py b/test/services/common/translator/base_test_translator.py index 43a169193..e0543a8e1 100644 --- a/test/services/common/translator/base_test_translator.py +++ b/test/services/common/translator/base_test_translator.py @@ -56,6 +56,7 @@ def validate_service_translations( try: for desc, cim_builder in types_to_test.items(): print(desc) + processing = f"generating given {desc}" @given(cim_builder) def run_test(cim): diff --git a/test/services/network/test_network_service_comparator.py b/test/services/network/test_network_service_comparator.py index d4a9efd81..601812d70 100644 --- a/test/services/network/test_network_service_comparator.py +++ b/test/services/network/test_network_service_comparator.py @@ -27,8 +27,7 @@ TransformerCoolingType, ProtectionRelayFunction, ProtectionRelayScheme, RelaySetting, DistanceRelay, VoltageRelay, ProtectionKind, \ ProtectionRelaySystem, Ground, GroundDisconnector, SeriesCompensator, BatteryControl, BatteryControlMode, AssetFunction, PanDemandResponseFunction, \ StaticVarCompensator, SVCControlMode, PerLengthPhaseImpedance, ReactiveCapabilityCurve, Curve, CurveData, \ - PhaseImpedanceData, EarthFaultCompensator, GroundingImpedance, PetersenCoil, RotatingMachine, SynchronousMachine, SynchronousMachineKind, LvSubstation, \ - PhaseStatus + PhaseImpedanceData, EarthFaultCompensator, GroundingImpedance, PetersenCoil, RotatingMachine, SynchronousMachine, SynchronousMachineKind, LvSubstation from zepben.ewb.model.cim.extensions.iec61970.base.core.hv_customer import HvCustomer from zepben.ewb.model.cim.extensions.iec61970.base.protection.directional_current_relay import DirectionalCurrentRelay from zepben.ewb.model.cim.extensions.iec61970.base.protection.polarizing_quantity_type import PolarizingQuantityType @@ -90,7 +89,7 @@ def test_compare_relay_info(self): RelayInfo.add_delay, RelayInfo, lambda _: [0.1, 0.2], - lambda _: [0.1, 0.3] + lambda _: [0.1, 0.3], ) ################################ @@ -104,7 +103,7 @@ def test_compare_pan_demand_response_function(self): PanDemandResponseFunction.kind, PanDemandResponseFunction, lambda _: EndDeviceFunctionKind.demandResponse, - lambda _: EndDeviceFunctionKind.onRequestRead + lambda _: EndDeviceFunctionKind.onRequestRead, ) self.validator.validate_property(PanDemandResponseFunction._appliance_bitmask, PanDemandResponseFunction, lambda _: 1, lambda _: 2) @@ -132,34 +131,39 @@ def test_compare_loop(self): Loop.add_energizing_substation, Loop, lambda _: Substation(mrid="s1"), - lambda _: Substation(mrid="s2") + lambda _: Substation(mrid="s2"), ) def test_compare_lv_feeder(self): self._compare_equipment_container(LvFeeder) self.validator.validate_property(LvFeeder.normal_head_terminal, LvFeeder, lambda _: Terminal(mrid="t1"), lambda _: Terminal(mrid="t2")) - self.validator.validate_property(LvFeeder.normal_energizing_lv_substation, LvFeeder, lambda _: LvSubstation(mrid="lvs1"), lambda _: LvSubstation(mrid="lvs2")) + self.validator.validate_property( + LvFeeder.normal_energizing_lv_substation, + LvFeeder, + lambda _: LvSubstation(mrid="lvs1"), + lambda _: LvSubstation(mrid="lvs2"), + ) self.validator.validate_collection( LvFeeder.normal_energizing_feeders, LvFeeder.add_normal_energizing_feeder, LvFeeder, lambda _: Feeder(mrid="f1"), - lambda _: Feeder(mrid="f2") + lambda _: Feeder(mrid="f2"), ) self.validator.validate_collection( LvFeeder.current_energizing_feeders, LvFeeder.add_current_energizing_feeder, LvFeeder, lambda _: Feeder(mrid="f1"), - lambda _: Feeder(mrid="f2") + lambda _: Feeder(mrid="f2"), ) self.validator.validate_collection( LvFeeder.current_equipment, LvFeeder.add_current_equipment, LvFeeder, lambda _: Junction(mrid="j1"), - lambda _: Junction(mrid="j2") + lambda _: Junction(mrid="j2"), ) def test_compare_lv_substation(self): @@ -170,21 +174,21 @@ def test_compare_lv_substation(self): LvSubstation.add_normal_energizing_feeder, LvSubstation, lambda _: Feeder(mrid="lvf1"), - lambda _: Feeder(mrid="lvf2") + lambda _: Feeder(mrid="lvf2"), ) self.validator.validate_collection( LvSubstation.current_energizing_feeders, LvSubstation.add_current_energizing_feeder, LvSubstation, lambda _: Feeder(mrid="lvf1"), - lambda _: Feeder(mrid="lvf2") + lambda _: Feeder(mrid="lvf2"), ) self.validator.validate_collection( LvSubstation.normal_energized_lv_feeders, LvSubstation.add_normal_energized_lv_feeder, LvSubstation, - lambda _: Feeder(mrid="lvf1"), - lambda _: Feeder(mrid="lvf2") + lambda _: LvFeeder(mrid="lvf1"), + lambda _: LvFeeder(mrid="lvf2"), ) ################################################## @@ -204,7 +208,7 @@ def test_compare_directional_current_relay(self): DirectionalCurrentRelay.polarizing_quantity_type, DirectionalCurrentRelay, lambda _: PolarizingQuantityType.NEGATIVE_SEQUENCE_VOLTAGE, - lambda _: PolarizingQuantityType.QUADRATURE_VOLTAGE + lambda _: PolarizingQuantityType.QUADRATURE_VOLTAGE, ) self.validator.validate_property(DirectionalCurrentRelay.relay_element_phase, DirectionalCurrentRelay, lambda _: PhaseCode.A, lambda _: PhaseCode.B) self.validator.validate_property(DirectionalCurrentRelay.minimum_pickup_current, DirectionalCurrentRelay, lambda _: 1.1, lambda _: 2.2) @@ -234,7 +238,7 @@ def _compare_protection_relay_function(self, creator: Type[ProtectionRelayFuncti ProtectionRelayFunction.protection_kind, creator, lambda _: ProtectionKind.JGGG, - lambda _: ProtectionKind.NEGATIVE_OVERCURRENT + lambda _: ProtectionKind.NEGATIVE_OVERCURRENT, ) self.validator.validate_property(ProtectionRelayFunction.relay_delay_time, creator, lambda _: 1.1, lambda _: 2.2) self.validator.validate_property(ProtectionRelayFunction.directable, creator, lambda _: False, lambda _: True) @@ -242,7 +246,7 @@ def _compare_protection_relay_function(self, creator: Type[ProtectionRelayFuncti ProtectionRelayFunction.power_direction, creator, lambda _: PowerDirectionKind.FORWARD, - lambda _: PowerDirectionKind.REVERSE + lambda _: PowerDirectionKind.REVERSE, ) self.validator.validate_collection( @@ -250,7 +254,7 @@ def _compare_protection_relay_function(self, creator: Type[ProtectionRelayFuncti ProtectionRelayFunction.add_sensor, creator, lambda _: CurrentTransformer(mrid="ct1"), - lambda _: CurrentTransformer(mrid="ct2") + lambda _: CurrentTransformer(mrid="ct2"), ) self.validator.validate_collection( @@ -258,7 +262,7 @@ def _compare_protection_relay_function(self, creator: Type[ProtectionRelayFuncti ProtectionRelayFunction.add_protected_switch, creator, lambda _: Breaker(mrid="b1"), - lambda _: Breaker(mrid="b2") + lambda _: Breaker(mrid="b2"), ) self.validator.validate_collection( @@ -266,7 +270,7 @@ def _compare_protection_relay_function(self, creator: Type[ProtectionRelayFuncti ProtectionRelayFunction.add_scheme, creator, lambda _: ProtectionRelayScheme(mrid="prs1"), - lambda _: ProtectionRelayScheme(mrid="prs2") + lambda _: ProtectionRelayScheme(mrid="prs2"), ) self.validator.validate_indexed_collection( @@ -290,7 +294,7 @@ def _compare_protection_relay_function(self, creator: Type[ProtectionRelayFuncti creator, lambda _: RelayInfo(mrid="ari1"), lambda _: RelayInfo(mrid="ari2"), - expected_differences={"relay_info"} + expected_differences={"relay_info"}, ) self.validator.validate_property( @@ -298,7 +302,7 @@ def _compare_protection_relay_function(self, creator: Type[ProtectionRelayFuncti creator, lambda _: RelayInfo(mrid="ri1"), lambda _: RelayInfo(mrid="ri2"), - expected_differences={"asset_info"} + expected_differences={"asset_info"}, ) def test_compare_protection_relay_scheme(self): @@ -307,7 +311,7 @@ def test_compare_protection_relay_scheme(self): ProtectionRelayScheme.system, ProtectionRelayScheme, lambda _: ProtectionRelaySystem(mrid="prs1"), - lambda _: ProtectionRelaySystem(mrid="prs2") + lambda _: ProtectionRelaySystem(mrid="prs2"), ) self.validator.validate_collection( @@ -315,7 +319,7 @@ def test_compare_protection_relay_scheme(self): ProtectionRelayScheme.add_function, ProtectionRelayScheme, lambda _: ProtectionRelayFunction(mrid="prf1"), - lambda _: ProtectionRelayFunction(mrid="prf2") + lambda _: ProtectionRelayFunction(mrid="prf2"), ) def test_compare_protection_relay_system(self): @@ -324,7 +328,7 @@ def test_compare_protection_relay_system(self): ProtectionRelaySystem.protection_kind, ProtectionRelaySystem, lambda _: ProtectionKind.JDIFF, - lambda _: ProtectionKind.SECTIONALIZER + lambda _: ProtectionKind.SECTIONALIZER, ) self.validator.validate_collection( @@ -332,7 +336,7 @@ def test_compare_protection_relay_system(self): ProtectionRelaySystem.add_scheme, ProtectionRelaySystem, lambda _: ProtectionRelayScheme(mrid="prs1"), - lambda _: ProtectionRelayScheme(mrid="prs2") + lambda _: ProtectionRelayScheme(mrid="prs2"), ) def test_compare_voltage_relay(self): @@ -387,7 +391,7 @@ def test_compare_power_transformer_info(self): PowerTransformerInfo.add_transformer_tank_info, PowerTransformerInfo, lambda _: TransformerTankInfo(mrid="tti1"), - lambda _: TransformerTankInfo(mrid="tti2") + lambda _: TransformerTankInfo(mrid="tti2"), ) def test_compare_short_circuit_test(self): @@ -432,7 +436,7 @@ def test_compare_transformer_end_info(self): TransformerEndInfo.transformer_star_impedance, TransformerEndInfo, lambda _: TransformerStarImpedance(mrid="tsi1"), - lambda _: TransformerStarImpedance(mrid="tsi2") + lambda _: TransformerStarImpedance(mrid="tsi2"), ) def test_compare_transformer_tank_info(self): @@ -443,7 +447,7 @@ def test_compare_transformer_tank_info(self): TransformerTankInfo.add_transformer_end_info, TransformerTankInfo, lambda _: TransformerEndInfo(mrid="tei1"), - lambda _: TransformerEndInfo(mrid="tei2") + lambda _: TransformerEndInfo(mrid="tei2"), ) def _compare_transformer_test(self, creator: Type[TransformerTest]): @@ -461,7 +465,12 @@ def _compare_wire_info(self, creator: Type[WireInfo]): self.validator.validate_property(WireInfo.strand_count, creator, lambda _: "3", lambda _: "4") self.validator.validate_property(WireInfo.core_strand_count, creator, lambda _: "5", lambda _: "6") self.validator.validate_property(WireInfo.insulated, creator, lambda _: True, lambda _: False) - self.validator.validate_property(WireInfo.insulation_material, creator, lambda _: WireInsulationKind.doubleWireArmour, lambda _: WireInsulationKind.beltedPilc) + self.validator.validate_property( + WireInfo.insulation_material, + creator, + lambda _: WireInsulationKind.doubleWireArmour, + lambda _: WireInsulationKind.beltedPilc, + ) self.validator.validate_property(WireInfo.insulation_thickness, creator, lambda _: 1.0, lambda _: 2.0) ################### @@ -476,14 +485,14 @@ def _compare_asset(self, creator: Type[Asset]): Asset.add_organisation_role, creator, lambda _: AssetOwner(mrid="a1"), - lambda _: AssetOwner(mrid="a2") + lambda _: AssetOwner(mrid="a2"), ) self.validator.validate_collection( Asset.power_system_resources, Asset.add_power_system_resource, creator, lambda _: Junction(mrid="j1"), - lambda _: Junction(mrid="j2") + lambda _: Junction(mrid="j2"), ) self.validator.validate_property(Asset.location, creator, lambda _: Location(mrid="l1"), lambda _: Location(mrid="l2")) @@ -509,7 +518,7 @@ def test_compare_streetlight(self): Streetlight.lamp_kind, Streetlight, lambda _: StreetlightLampKind.HIGH_PRESSURE_SODIUM, - lambda _: StreetlightLampKind.MERCURY_VAPOR + lambda _: StreetlightLampKind.MERCURY_VAPOR, ) self.validator.validate_property(Streetlight.light_rating, Streetlight, lambda _: 1, lambda _: 2) self.validator.validate_property(Streetlight.pole, Streetlight, lambda _: Pole(mrid="x"), lambda _: Pole(mrid="y")) @@ -529,7 +538,7 @@ def test_compare_location(self): Location.main_address, Location, lambda _: StreetAddress("1234", TownDetail("town", "state")), - lambda _: StreetAddress("1234", TownDetail("other", "state")) + lambda _: StreetAddress("1234", TownDetail("other", "state")), ) # noinspection PyArgumentList self.validator.validate_indexed_collection( @@ -537,7 +546,7 @@ def test_compare_location(self): Location.add_point, Location, lambda _: PositionPoint(1.0, 2.0), - lambda _: PositionPoint(3.0, 4.0) + lambda _: PositionPoint(3.0, 4.0), ) ##################################### @@ -596,7 +605,7 @@ def _compare_end_device(self, creator: Type[EndDevice]): lambda _: UsagePoint(mrid="up1"), lambda _: UsagePoint(mrid="up2"), NetworkServiceComparatorOptions(compare_lv_simplification=False), - options_stop_compare=True + options_stop_compare=True, ) self.validator.validate_collection( EndDevice.functions, @@ -604,7 +613,7 @@ def _compare_end_device(self, creator: Type[EndDevice]): creator, lambda _: EndDeviceFunction(mrid="edf1"), lambda _: EndDeviceFunction(mrid="edf2"), - NetworkServiceComparatorOptions(compare_lv_simplification=False) + NetworkServiceComparatorOptions(compare_lv_simplification=False), ) def _compare_end_device_function(self, creator: Type[EndDeviceFunction]): @@ -630,7 +639,7 @@ def test_compare_usage_point(self): lambda _: Meter(mrid="m1"), lambda _: Meter(mrid="m2"), NetworkServiceComparatorOptions(compare_lv_simplification=False), - options_stop_compare=True + options_stop_compare=True, ) self.validator.validate_collection( UsagePoint.equipment, @@ -639,7 +648,7 @@ def test_compare_usage_point(self): lambda _: Junction(mrid="j1"), lambda _: Junction(mrid="j2"), NetworkServiceComparatorOptions(compare_lv_simplification=False), - options_stop_compare=True + options_stop_compare=True, ) ####################### @@ -654,7 +663,7 @@ def test_compare_operational_restriction(self): OperationalRestriction.add_equipment, OperationalRestriction, lambda _: Junction(mrid="j1"), - lambda _: Junction(mrid="j2") + lambda _: Junction(mrid="j2"), ) ##################################### @@ -670,7 +679,7 @@ def _compare_auxiliary_equipment(self, creator: Type[AuxiliaryEquipment]): lambda _: Terminal(mrid="t1"), lambda _: Terminal(mrid="t2"), NetworkServiceComparatorOptions(compare_terminals=False), - options_stop_compare=True + options_stop_compare=True, ) def test_compare_current_transformer(self): @@ -682,14 +691,14 @@ def test_compare_current_transformer(self): CurrentTransformer, lambda _: CurrentTransformerInfo(mrid="acti1"), lambda _: CurrentTransformerInfo(mrid="acti2"), - expected_differences={"current_transformer_info"} + expected_differences={"current_transformer_info"}, ) self.validator.validate_property( CurrentTransformer.current_transformer_info, CurrentTransformer, lambda _: CurrentTransformerInfo(mrid="acti1"), lambda _: CurrentTransformerInfo(mrid="acti2"), - expected_differences={"asset_info"} + expected_differences={"asset_info"}, ) def test_compare_fault_indicator(self): @@ -702,21 +711,21 @@ def test_compare_potential_transformer(self): PotentialTransformer.type, PotentialTransformer, lambda _: PotentialTransformerKind.capacitiveCoupling, - lambda _: PotentialTransformerKind.inductive + lambda _: PotentialTransformerKind.inductive, ) self.validator.validate_property( PotentialTransformer.asset_info, PotentialTransformer, lambda _: PotentialTransformerInfo(mrid="avti1"), lambda _: PotentialTransformerInfo(mrid="avti2"), - expected_differences={"potential_transformer_info"} + expected_differences={"potential_transformer_info"}, ) self.validator.validate_property( PotentialTransformer.potential_transformer_info, PotentialTransformer, lambda _: PotentialTransformerInfo(mrid="vti1"), lambda _: PotentialTransformerInfo(mrid="vti2"), - expected_differences={"asset_info"} + expected_differences={"asset_info"}, ) def _compare_sensor(self, creator: Type[Sensor]): @@ -725,7 +734,7 @@ def _compare_sensor(self, creator: Type[Sensor]): Sensor.add_relay_function, creator, lambda _: ProtectionRelayFunction(mrid="prf1"), - lambda _: ProtectionRelayFunction(mrid="prf2") + lambda _: ProtectionRelayFunction(mrid="prf2"), ) self._compare_auxiliary_equipment(creator) @@ -752,7 +761,7 @@ def _compare_conducting_equipment(self, creator: Type[ConductingEquipment]): lambda _: Terminal(mrid="1"), lambda _: Terminal(mrid="2"), NetworkServiceComparatorOptions(compare_terminals=False), - options_stop_compare=True + options_stop_compare=True, ) def test_compare_connectivity_node(self): @@ -763,7 +772,7 @@ def test_compare_connectivity_node(self): ConnectivityNode.add_terminal, ConnectivityNode, lambda _: Terminal(mrid="1"), - lambda _: Terminal(mrid="2") + lambda _: Terminal(mrid="2"), ) def _compare_connectivity_node_container(self, creator: Type[ConnectivityNodeContainer]): @@ -789,28 +798,28 @@ def _compare_equipment(self, creator: Type[Equipment]): Equipment.commissioned_date, creator, lambda _: datetime.datetime.fromtimestamp(0), - lambda _: datetime.datetime.fromtimestamp(1) + lambda _: datetime.datetime.fromtimestamp(1), ) self.validator.validate_collection(Equipment.containers, Equipment.add_container, creator, lambda _: Site(mrid="s1"), lambda _: Site(mrid="s2")) self.validator.validate_collection( Equipment.usage_points, Equipment.add_usage_point, creator, lambda _: UsagePoint(mrid="u1"), - lambda _: UsagePoint(mrid="u2") + lambda _: UsagePoint(mrid="u2"), ) self.validator.validate_collection( Equipment.operational_restrictions, Equipment.add_operational_restriction, creator, lambda _: OperationalRestriction(mrid="o1"), - lambda _: OperationalRestriction(mrid="o2") + lambda _: OperationalRestriction(mrid="o2"), ) self.validator.validate_collection( Equipment.current_containers, Equipment.add_current_container, creator, lambda _: Feeder(mrid="f1"), - lambda _: Feeder(mrid="f2") + lambda _: Feeder(mrid="f2"), ) def _compare_equipment_container(self, creator: Type[EquipmentContainer]): @@ -821,7 +830,7 @@ def _compare_equipment_container(self, creator: Type[EquipmentContainer]): EquipmentContainer.add_equipment, creator, lambda _: Junction(mrid="j1"), - lambda _: Junction(mrid="j2") + lambda _: Junction(mrid="j2"), ) def test_compare_feeder(self): @@ -834,35 +843,35 @@ def test_compare_feeder(self): Feeder.add_current_equipment, Feeder, lambda _: Junction(mrid="j1"), - lambda _: Junction(mrid="j2") + lambda _: Junction(mrid="j2"), ) self.validator.validate_collection( Feeder.normal_energized_lv_feeders, Feeder.add_normal_energized_lv_feeder, Feeder, lambda _: LvFeeder(mrid="lvf1"), - lambda _: LvFeeder(mrid="lvf2") + lambda _: LvFeeder(mrid="lvf2"), ) self.validator.validate_collection( Feeder.current_energized_lv_feeders, Feeder.add_current_energized_lv_feeder, Feeder, lambda _: LvFeeder(mrid="lvf1"), - lambda _: LvFeeder(mrid="lvf2") + lambda _: LvFeeder(mrid="lvf2"), ) self.validator.validate_collection( Feeder.normal_energized_lv_substations, Feeder.add_normal_energized_lv_substation, Feeder, - lambda _: LvFeeder(mrid="lvs1"), - lambda _: LvFeeder(mrid="lvs2") + lambda _: LvSubstation(mrid="lvs1"), + lambda _: LvSubstation(mrid="lvs2"), ) self.validator.validate_collection( Feeder.current_energized_lv_substations, Feeder.add_current_energized_lv_substation, Feeder, - lambda _: LvFeeder(mrid="lvs1"), - lambda _: LvFeeder(mrid="lvs2") + lambda _: LvSubstation(mrid="lvs1"), + lambda _: LvSubstation(mrid="lvs2"), ) def test_compare_geographical_region(self): @@ -873,7 +882,7 @@ def test_compare_geographical_region(self): GeographicalRegion.add_sub_geographical_region, GeographicalRegion, lambda _: SubGeographicalRegion(mrid="sg1"), - lambda _: SubGeographicalRegion(mrid="sg2") + lambda _: SubGeographicalRegion(mrid="sg2"), ) def _compare_power_system_resource(self, creator: Type[PowerSystemResource]): @@ -885,7 +894,7 @@ def _compare_power_system_resource(self, creator: Type[PowerSystemResource]): PowerSystemResource.add_asset, creator, lambda _: Pole(mrid="p1"), - lambda _: Pole(mrid="p2") + lambda _: Pole(mrid="p2"), ) def test_compare_sub_geographical_region(self): @@ -895,14 +904,14 @@ def test_compare_sub_geographical_region(self): SubGeographicalRegion.geographical_region, SubGeographicalRegion, lambda _: GeographicalRegion(mrid="g1"), - lambda _: GeographicalRegion(mrid="g2") + lambda _: GeographicalRegion(mrid="g2"), ) self.validator.validate_collection( SubGeographicalRegion.substations, SubGeographicalRegion.add_substation, SubGeographicalRegion, lambda _: Substation(mrid="s1"), - lambda _: Substation(mrid="s2") + lambda _: Substation(mrid="s2"), ) def test_compare_substation(self): @@ -912,7 +921,7 @@ def test_compare_substation(self): Substation.sub_geographical_region, Substation, lambda _: SubGeographicalRegion(mrid="sg1"), - lambda _: SubGeographicalRegion(mrid="sg2") + lambda _: SubGeographicalRegion(mrid="sg2"), ) self.validator.validate_collection(Substation.feeders, Substation.add_feeder, Substation, lambda _: Feeder(mrid="f1"), lambda _: Feeder(mrid="f2")) @@ -931,19 +940,15 @@ def test_compare_terminal(self): self.validator.validate_property(Terminal.current_feeder_direction, Terminal, lambda _: FeederDirection.UPSTREAM, lambda _: FeederDirection.DOWNSTREAM) def _change_state(prop, val): - setattr(prop, '_phase_status_internal', val) + setattr(prop, '_phase_status_internal', val) - for first, second in ( + phase_difference_pairs = ( (0x00000001, 0x00000002), (0x00000010, 0x00000020), (0x00000100, 0x00000200), (0x00001000, 0x00002000), - ): - #expected_diff = ObjectDifference() - #expected_diff.differences["normal_phases"] = ValueDifference(1, 2) - - #self.validator.validate_compare(closed_switch, open_switch, expect_modification=difference) - + ) + for first, second in phase_difference_pairs: for state in (Terminal.normal_phases, Terminal.current_phases): self.validator.validate_val_property( state, @@ -956,7 +961,7 @@ def _change_state(prop, val): Terminal.connectivity_node, Terminal, lambda terminal, _: terminal.connect(cn1), - lambda terminal, _: terminal.connect(cn2) + lambda terminal, _: terminal.connect(cn2), ) self.validator.validate_property(Terminal.conducting_equipment, Terminal, lambda _: Junction(mrid="j1"), lambda _: Junction(mrid="j2")) @@ -1008,7 +1013,7 @@ def _compare_power_electronics_unit(self, creator: Type[PowerElectronicsUnit]): PowerElectronicsUnit.power_electronics_connection, creator, lambda _: PowerElectronicsConnection(mrid="pec1"), - lambda _: PowerElectronicsConnection(mrid="pec2") + lambda _: PowerElectronicsConnection(mrid="pec2"), ) self.validator.validate_property(PowerElectronicsUnit.max_p, creator, lambda _: 1, lambda _: 2) self.validator.validate_property(PowerElectronicsUnit.min_p, creator, lambda _: 1, lambda _: 2) @@ -1069,7 +1074,7 @@ def test_compare_remote_source(self): RemoteSource.measurement, RemoteSource, lambda _: Measurement(mrid="m1"), - lambda _: Measurement(mrid="m2") + lambda _: Measurement(mrid="m2"), ) ####################### @@ -1083,28 +1088,28 @@ def test_compare_ac_line_segment(self): AcLineSegment.per_length_impedance, AcLineSegment, lambda _: PerLengthSequenceImpedance(mrid="p1"), - lambda _: PerLengthSequenceImpedance(mrid="p2") + lambda _: PerLengthSequenceImpedance(mrid="p2"), ) self.validator.validate_collection( AcLineSegment.cuts, AcLineSegment.add_cut, AcLineSegment, lambda _: Cut(mrid="cut1"), - lambda _: Cut(mrid="cut2") + lambda _: Cut(mrid="cut2"), ) self.validator.validate_collection( AcLineSegment.clamps, AcLineSegment.add_clamp, AcLineSegment, lambda _: Clamp(mrid="clamp1"), - lambda _: Clamp(mrid="clamp2") + lambda _: Clamp(mrid="clamp2"), ) self.validator.validate_collection( AcLineSegment.phases, AcLineSegment.add_phase, AcLineSegment, lambda _: AcLineSegmentPhase(mrid="p1"), - lambda _: AcLineSegmentPhase(mrid="p2") + lambda _: AcLineSegmentPhase(mrid="p2"), ) def test_ac_line_segment_phase(self): @@ -1114,7 +1119,7 @@ def test_ac_line_segment_phase(self): AcLineSegmentPhase.ac_line_segment, AcLineSegmentPhase, lambda _: AcLineSegment(mrid="c1"), - lambda _: AcLineSegment(mrid="c2") + lambda _: AcLineSegment(mrid="c2"), ) self.validator.validate_property(AcLineSegmentPhase.asset_info, AcLineSegmentPhase, lambda _: CableInfo(mrid="c1"), lambda _: CableInfo(mrid="c2")) self.validator.validate_property(AcLineSegmentPhase.phase, AcLineSegmentPhase, lambda _: SinglePhaseKind.A, lambda _: SinglePhaseKind.B) @@ -1176,7 +1181,7 @@ def test_compare_energy_consumer(self): EnergyConsumer.phase_connection, EnergyConsumer, lambda _: PhaseShuntConnectionKind.I, - lambda _: PhaseShuntConnectionKind.D + lambda _: PhaseShuntConnectionKind.D, ) self.validator.validate_property(EnergyConsumer.q, EnergyConsumer, lambda _: 1.0, lambda _: 2.0) self.validator.validate_property(EnergyConsumer.q_fixed, EnergyConsumer, lambda _: 1.0, lambda _: 2.0) @@ -1185,7 +1190,7 @@ def test_compare_energy_consumer(self): EnergyConsumer.add_phase, EnergyConsumer, lambda _: EnergyConsumerPhase(mrid="ecp1"), - lambda _: EnergyConsumerPhase(mrid="ecp2") + lambda _: EnergyConsumerPhase(mrid="ecp2"), ) def test_compare_energy_consumer_phase(self): @@ -1195,7 +1200,7 @@ def test_compare_energy_consumer_phase(self): EnergyConsumerPhase.energy_consumer, EnergyConsumerPhase, lambda _: EnergyConsumer(mrid="ec1"), - lambda _: EnergyConsumer(mrid="ec2") + lambda _: EnergyConsumer(mrid="ec2"), ) self.validator.validate_property(EnergyConsumerPhase.phase, EnergyConsumerPhase, lambda _: SinglePhaseKind.A, lambda _: SinglePhaseKind.B) self.validator.validate_property(EnergyConsumerPhase.p, EnergyConsumerPhase, lambda _: 1.0, lambda _: 2.0) @@ -1236,7 +1241,7 @@ def test_compare_energy_source(self): EnergySource.add_phase, EnergySource, lambda _: EnergySourcePhase(mrid="ecp1"), - lambda _: EnergySourcePhase(mrid="ecp2") + lambda _: EnergySourcePhase(mrid="ecp2"), ) def test_compare_energy_source_phase(self): @@ -1247,7 +1252,7 @@ def test_compare_energy_source_phase(self): EnergySourcePhase.energy_source, EnergySourcePhase, lambda _: EnergySource(mrid="es1"), - lambda _: EnergySource(mrid="es2") + lambda _: EnergySource(mrid="es2"), ) def test_compare_fuse(self): @@ -1256,7 +1261,7 @@ def test_compare_fuse(self): Fuse.function, Fuse, lambda _: ProtectionRelayFunction(mrid="prf1"), - lambda _: ProtectionRelayFunction(mrid="prf2") + lambda _: ProtectionRelayFunction(mrid="prf2"), ) def test_compare_ground(self): @@ -1331,14 +1336,14 @@ def test_compare_power_electronics_connection(self): PowerElectronicsConnection.add_phase, PowerElectronicsConnection, lambda _: PowerElectronicsConnectionPhase(mrid="pecp1"), - lambda _: PowerElectronicsConnectionPhase(mrid="pecp2") + lambda _: PowerElectronicsConnectionPhase(mrid="pecp2"), ) self.validator.validate_collection( PowerElectronicsConnection.units, PowerElectronicsConnection.add_unit, PowerElectronicsConnection, lambda _: PowerElectronicsUnit(mrid="peu1"), - lambda _: PowerElectronicsUnit(mrid="peu2") + lambda _: PowerElectronicsUnit(mrid="peu2"), ) self.validator.validate_property(PowerElectronicsConnection.max_i_fault, PowerElectronicsConnection, lambda _: 1, lambda _: 2) self.validator.validate_property(PowerElectronicsConnection.max_q, PowerElectronicsConnection, lambda _: 1.0, lambda _: 2.0) @@ -1379,13 +1384,13 @@ def test_compare_power_electronics_connection_phase(self): PowerElectronicsConnectionPhase.phase, PowerElectronicsConnectionPhase, lambda _: SinglePhaseKind.A, - lambda _: SinglePhaseKind.B + lambda _: SinglePhaseKind.B, ) self.validator.validate_property( PowerElectronicsConnectionPhase.power_electronics_connection, PowerElectronicsConnectionPhase, lambda _: PowerElectronicsConnection(mrid="pec1"), - lambda _: PowerElectronicsConnection(mrid="pec2") + lambda _: PowerElectronicsConnection(mrid="pec2"), ) def test_compare_power_transformer(self): @@ -1410,7 +1415,7 @@ def test_compare_power_transformer(self): PowerTransformer, lambda _: PowerTransformerInfo(mrid="apti1"), lambda _: PowerTransformerInfo(mrid="apti2"), - expected_differences={"power_transformer_info"} + expected_differences={"power_transformer_info"}, ) self.validator.validate_property( @@ -1418,7 +1423,7 @@ def test_compare_power_transformer(self): PowerTransformer, lambda _: PowerTransformerInfo(mrid="pti1"), lambda _: PowerTransformerInfo(mrid="pti2"), - expected_differences={"asset_info"} + expected_differences={"asset_info"}, ) def test_compare_power_transformer_end(self): @@ -1428,7 +1433,7 @@ def test_compare_power_transformer_end(self): PowerTransformerEnd.power_transformer, PowerTransformerEnd, lambda _: PowerTransformer(mrid="pt1"), - lambda _: PowerTransformer(mrid="pt2") + lambda _: PowerTransformer(mrid="pt2"), ) self.validator.validate_property(PowerTransformerEnd.b, PowerTransformerEnd, lambda _: 1.0, lambda _: 2.0) self.validator.validate_property(PowerTransformerEnd.b0, PowerTransformerEnd, lambda _: 1.0, lambda _: 2.0) @@ -1453,7 +1458,7 @@ def test_compare_power_transformer_end(self): PowerTransformerEnd, lambda _: TransformerEndRatedS(TransformerCoolingType.UNKNOWN, 1), lambda _: TransformerEndRatedS(TransformerCoolingType.UNKNOWN, 2), - expected_differences={"rated_s"} + expected_differences={"rated_s"}, ) def _compare_protected_switch(self, creator: Type[ProtectedSwitch]): @@ -1465,7 +1470,7 @@ def _compare_protected_switch(self, creator: Type[ProtectedSwitch]): ProtectedSwitch.add_relay_function, creator, lambda _: CurrentRelay(mrid="cr1"), - lambda _: CurrentRelay(mrid="cr2") + lambda _: CurrentRelay(mrid="cr2"), ) def test_compare_ratio_tap_changer(self): @@ -1475,7 +1480,7 @@ def test_compare_ratio_tap_changer(self): RatioTapChanger.transformer_end, RatioTapChanger, lambda _: PowerTransformerEnd(mrid="pte1"), - lambda _: PowerTransformerEnd(mrid="pte2") + lambda _: PowerTransformerEnd(mrid="pte2"), ) self.validator.validate_property(RatioTapChanger.step_voltage_increment, RatioTapChanger, lambda _: 1.0, lambda _: 2.0) @@ -1493,7 +1498,7 @@ def _compare_regulating_cond_eq(self, creator: Type[RegulatingCondEq]): RegulatingCondEq.regulating_control, creator, lambda _: RegulatingControl(mrid="rc1"), - lambda _: RegulatingControl(mrid="rc2") + lambda _: RegulatingControl(mrid="rc2"), ) def _compare_regulating_control(self, creator: Type[RegulatingControl]): @@ -1501,9 +1506,10 @@ def _compare_regulating_control(self, creator: Type[RegulatingControl]): self.validator.validate_property(RegulatingControl.discrete, creator, lambda _: False, lambda _: True) self.validator.validate_property( - RegulatingControl.mode, creator, + RegulatingControl.mode, + creator, lambda _: RegulatingControlModeKind.voltage, - lambda _: RegulatingControlModeKind.currentFlow + lambda _: RegulatingControlModeKind.currentFlow, ) self.validator.validate_property(RegulatingControl.monitored_phase, creator, lambda _: PhaseCode.ABC, lambda _: PhaseCode.ABCN) self.validator.validate_property(RegulatingControl.target_deadband, creator, lambda _: 1.0, lambda _: 2.0) @@ -1520,7 +1526,7 @@ def _compare_regulating_control(self, creator: Type[RegulatingControl]): RegulatingControl.add_regulating_cond_eq, creator, lambda _: RegulatingCondEq(mrid="rce1"), - lambda _: RegulatingCondEq(mrid="rce2") + lambda _: RegulatingCondEq(mrid="rce2"), ) def _compare_rotating_machine(self, creator: Type[RotatingMachine]): @@ -1551,7 +1557,7 @@ def _compare_shunt_compensator(self, creator: Type[ShuntCompensator]): ShuntCompensator.phase_connection, creator, lambda _: PhaseShuntConnectionKind.D, - lambda _: PhaseShuntConnectionKind.G + lambda _: PhaseShuntConnectionKind.G, ) self.validator.validate_property(ShuntCompensator.sections, creator, lambda _: 1.0, lambda _: 2.0) self.validator.validate_property(ShuntCompensator.asset_info, creator, lambda _: ShuntCompensatorInfo(mrid="asci1"), @@ -1570,7 +1576,7 @@ def test_compare_static_var_compensator(self): StaticVarCompensator.svc_control_mode, StaticVarCompensator, lambda _: SVCControlMode.reactivePower, - lambda _: SVCControlMode.voltage + lambda _: SVCControlMode.voltage, ) self.validator.validate_property(StaticVarCompensator.voltage_set_point, StaticVarCompensator, lambda _: 1, lambda _: 2) @@ -1594,12 +1600,12 @@ def _compare_switch(self, creator: Type[Switch]): difference = ObjectDifference(closed_switch, open_switch) difference.differences["isNormallyOpen"] = ValueDifference( {p: False for p in PhaseCode.ABCN.single_phases}, - {p: True for p in PhaseCode.ABCN.single_phases} + {p: True for p in PhaseCode.ABCN.single_phases}, ) difference.differences["isOpen"] = ValueDifference( {p: True for p in PhaseCode.ABCN.single_phases}, - {p: False for p in PhaseCode.ABCN.single_phases} + {p: False for p in PhaseCode.ABCN.single_phases}, ) self.validator.validate_compare(closed_switch, open_switch, expect_modification=difference) @@ -1636,7 +1642,7 @@ def test_compare_synchronous_machine(self): SynchronousMachine.add_curve, SynchronousMachine, lambda _: ReactiveCapabilityCurve(mrid="c1"), - lambda _: ReactiveCapabilityCurve(mrid="c2") + lambda _: ReactiveCapabilityCurve(mrid="c2"), ) def _compare_tap_changer(self, creator: Type[TapChanger]): @@ -1676,7 +1682,7 @@ def _compare_transformer_end(self, creator: Type[TransformerEnd]): TransformerEnd.ratio_tap_changer, creator, lambda _: RatioTapChanger(mrid="rtc1"), - lambda _: RatioTapChanger(mrid="rtc2") + lambda _: RatioTapChanger(mrid="rtc2"), ) self.validator.validate_property(TransformerEnd.terminal, creator, lambda _: Terminal(mrid="t1", conducting_equipment=PowerTransformer(mrid="t1-pt1")), lambda _: Terminal(mrid="t2", conducting_equipment=PowerTransformer(mrid="t2-pt2"))) @@ -1684,7 +1690,7 @@ def _compare_transformer_end(self, creator: Type[TransformerEnd]): TransformerEnd.star_impedance, creator, lambda _: TransformerStarImpedance(mrid="tsi1"), - lambda _: TransformerStarImpedance(mrid="tsi2") + lambda _: TransformerStarImpedance(mrid="tsi2"), ) def test_compare_transformer_star_impedance(self): @@ -1710,12 +1716,12 @@ def test_compare_circuit(self): Circuit.add_end_terminal, Circuit, lambda _: Terminal(mrid="t1"), - lambda _: Terminal(mrid="t2") + lambda _: Terminal(mrid="t2"), ) self.validator.validate_collection( Circuit.end_substations, Circuit.add_end_substation, Circuit, lambda _: Substation(mrid="s1"), - lambda _: Substation(mrid="s2") + lambda _: Substation(mrid="s2"), ) diff --git a/test/services/network/translator/test_network_translator.py b/test/services/network/translator/test_network_translator.py index c4052ce77..f28f7c8fe 100644 --- a/test/services/network/translator/test_network_translator.py +++ b/test/services/network/translator/test_network_translator.py @@ -230,6 +230,7 @@ "create_circuit": create_circuit(), } + @pytest.mark.timeout(20000) def test_network_service_translations(): validate_service_translations( @@ -272,6 +273,7 @@ def test_network_service_translations(): types_to_test=types_to_test, ) + # NOTE: NameType is not sent via any grpc messages at this stage, so test it separately def test_creates_new_name_type(): # noinspection PyArgumentList, PyUnresolvedReferences From e505e1af50af52412200df73a03434fa51d99726 Mon Sep 17 00:00:00 2001 From: Anthony Charlton Date: Thu, 26 Mar 2026 11:07:53 +1100 Subject: [PATCH 12/26] Fixed imports in set direction after changes Signed-off-by: Anthony Charlton --- .../ewb/services/network/tracing/feeder/set_direction.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/zepben/ewb/services/network/tracing/feeder/set_direction.py b/src/zepben/ewb/services/network/tracing/feeder/set_direction.py index a239b88ae..c0817e7ad 100644 --- a/src/zepben/ewb/services/network/tracing/feeder/set_direction.py +++ b/src/zepben/ewb/services/network/tracing/feeder/set_direction.py @@ -11,6 +11,7 @@ from logging import Logger from typing import Optional, TYPE_CHECKING, Type +from zepben.ewb.model.cim.iec61970.base.core.conducting_equipment import ConductingEquipment from zepben.ewb.model.cim.iec61970.base.core.feeder import Feeder from zepben.ewb.model.cim.iec61970.base.core.terminal import Terminal from zepben.ewb.model.cim.iec61970.base.wires.busbar_section import BusbarSection @@ -26,7 +27,7 @@ from zepben.ewb.services.network.tracing.traversal.weighted_priority_queue import WeightedPriorityQueue if TYPE_CHECKING: - from zepben.ewb import NetworkService, Switch, ConductingEquipment + from zepben.ewb import NetworkService, Switch class SetDirection: From ad4e9f434cc60865d3d27cb5ce6e82bed60032a2 Mon Sep 17 00:00:00 2001 From: Anthony Charlton Date: Thu, 26 Mar 2026 20:09:23 +1100 Subject: [PATCH 13/26] Renamed `PanDemandResponseFunction` constructor argument `appliances` -> `appliance` to match the class property. Signed-off-by: Anthony Charlton --- changelog.md | 1 + .../iec61968/metering/pan_demand_reponse_function.py | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/changelog.md b/changelog.md index 648c1121f..1b70cab4b 100644 --- a/changelog.md +++ b/changelog.md @@ -5,6 +5,7 @@ call with `run`. * `EquipmentTreeBuilder.roots` is now a `dict` keyed by the `start_item` rather than a `Generator`. This allows better lookup of root items when you are looking for an explicit items tree. +* Renamed `PanDemandResponseFunction` constructor argument `appliances` -> `appliance` to match the class property. ### New Features * None. diff --git a/src/zepben/ewb/model/cim/extensions/iec61968/metering/pan_demand_reponse_function.py b/src/zepben/ewb/model/cim/extensions/iec61968/metering/pan_demand_reponse_function.py index 6207f67b0..929360de9 100644 --- a/src/zepben/ewb/model/cim/extensions/iec61968/metering/pan_demand_reponse_function.py +++ b/src/zepben/ewb/model/cim/extensions/iec61968/metering/pan_demand_reponse_function.py @@ -25,10 +25,10 @@ class PanDemandResponseFunction(EndDeviceFunction): _appliance_bitmask: Optional[int] = None - def __init__(self, appliances: Union[int, ControlledAppliance] = None, **kwargs): + def __init__(self, appliance: Union[int, ControlledAppliance] = None, **kwargs): super(PanDemandResponseFunction, self).__init__(**kwargs) - if appliances is not None: - self.appliance = appliances + if appliance is not None: + self.appliance = appliance @property def appliance(self) -> Optional[ControlledAppliance]: From 0af41815adba5c20ac85c57650d9de10a07df0c7 Mon Sep 17 00:00:00 2001 From: Anthony Charlton Date: Thu, 26 Mar 2026 21:34:39 +1100 Subject: [PATCH 14/26] Fixed types on all overrides for `PowerSystemResource.asset_info` Signed-off-by: Anthony Charlton --- changelog.md | 9 ++ .../sqlite/network/network_cim_writer.py | 10 +- .../protection/protection_relay_function.py | 30 +++-- .../auxiliaryequipment/current_transformer.py | 9 ++ .../potential_transformer.py | 9 ++ .../iec61970/base/wires/ac_line_segment.py | 23 ++-- .../cim/iec61970/base/wires/conductor.py | 13 +- .../iec61970/base/wires/power_transformer.py | 18 ++- .../iec61970/base/wires/shunt_compensator.py | 14 +- .../model/cim/iec61970/base/wires/switch.py | 9 ++ .../network/network_service_comparator.py | 8 -- test/cim/fill_fields.py | 5 +- test/database/sqlite/schema_utils.py | 35 ++--- test/services/common/test_base_service.py | 2 +- .../test_network_service_comparator.py | 120 +++++++++--------- 15 files changed, 181 insertions(+), 133 deletions(-) diff --git a/changelog.md b/changelog.md index 1b70cab4b..ec977569b 100644 --- a/changelog.md +++ b/changelog.md @@ -6,12 +6,21 @@ * `EquipmentTreeBuilder.roots` is now a `dict` keyed by the `start_item` rather than a `Generator`. This allows better lookup of root items when you are looking for an explicit items tree. * Renamed `PanDemandResponseFunction` constructor argument `appliances` -> `appliance` to match the class property. +* Deprecated the following side-hustle shadowy names for `PowerSystemResource.asset_info`, just use `asset_info` directly: + * `Conductor.wire_info` + * `CurrentTransformer.current_transformer_info` + * `PotentialTransformer.potential_transformer_info` + * `PowerTransformer.power_transformer_info` + * `ProtectionRelayFunction.relay_info` + * `ShuntCompensator.shunt_compensator_info` + * `Switch.switch_info` ### New Features * None. ### Enhancements * `SetDirection.run` now supports `ConductingEquipment`. +* Fixed types on all overrides for `PowerSystemResource.asset_info`, removing the need to shadow them with type specific variants. ### Fixes * None. diff --git a/src/zepben/ewb/database/sqlite/network/network_cim_writer.py b/src/zepben/ewb/database/sqlite/network/network_cim_writer.py index 1be1c5f68..34a0cdbdd 100644 --- a/src/zepben/ewb/database/sqlite/network/network_cim_writer.py +++ b/src/zepben/ewb/database/sqlite/network/network_cim_writer.py @@ -1251,7 +1251,7 @@ def save_current_transformer(self, current_transformer: CurrentTransformer) -> b table = self._database_tables.get_table(TableCurrentTransformers) insert = self._database_tables.get_insert(TableCurrentTransformers) - insert.add_value(table.current_transformer_info_mrid.query_index, self._mrid_or_none(current_transformer.current_transformer_info)) + insert.add_value(table.current_transformer_info_mrid.query_index, self._mrid_or_none(current_transformer.asset_info)) insert.add_value(table.core_burden.query_index, current_transformer.core_burden) return self._save_sensor(table, insert, current_transformer, "current transformer") @@ -1280,7 +1280,7 @@ def save_potential_transformer(self, potential_transformer: PotentialTransformer table = self._database_tables.get_table(TablePotentialTransformers) insert = self._database_tables.get_insert(TablePotentialTransformers) - insert.add_value(table.potential_transformer_info_mrid.query_index, self._mrid_or_none(potential_transformer.potential_transformer_info)) + insert.add_value(table.potential_transformer_info_mrid.query_index, self._mrid_or_none(potential_transformer.asset_info)) insert.add_value(table.type.query_index, potential_transformer.type.short_name) return self._save_sensor(table, insert, potential_transformer, "potential transformer") @@ -1805,7 +1805,7 @@ def _save_conductor(self, table: TableConductors, insert: PreparedStatement, con insert.add_value(table.length.query_index, conductor.length) insert.add_value(table.design_temperature.query_index, conductor.design_temperature) insert.add_value(table.design_rating.query_index, conductor.design_rating) - insert.add_value(table.wire_info_mrid.query_index, self._mrid_or_none(conductor.wire_info)) + insert.add_value(table.wire_info_mrid.query_index, self._mrid_or_none(conductor.asset_info)) return self._save_conducting_equipment(table, insert, conductor, description) @@ -2243,7 +2243,7 @@ def save_power_transformer(self, power_transformer: PowerTransformer) -> bool: insert.add_value(table.transformer_utilisation.query_index, power_transformer.transformer_utilisation) insert.add_value(table.construction_kind.query_index, power_transformer.construction_kind.short_name) insert.add_value(table.function.query_index, power_transformer.function.short_name) - insert.add_value(table.power_transformer_info_mrid.query_index, self._mrid_or_none(power_transformer.power_transformer_info)) + insert.add_value(table.power_transformer_info_mrid.query_index, self._mrid_or_none(power_transformer.asset_info)) return self._save_conducting_equipment(table, insert, power_transformer, "power transformer") @@ -2440,7 +2440,7 @@ def _save_switch(self, table: TableSwitches, insert: PreparedStatement, switch: # noinspection PyProtectedMember insert.add_value(table.open.query_index, switch._open) insert.add_value(table.rated_current.query_index, switch.rated_current) - insert.add_value(table.switch_info_mrid.query_index, self._mrid_or_none(switch.switch_info)) + insert.add_value(table.switch_info_mrid.query_index, self._mrid_or_none(switch.asset_info)) return self._save_conducting_equipment(table, insert, switch, description) diff --git a/src/zepben/ewb/model/cim/extensions/iec61970/base/protection/protection_relay_function.py b/src/zepben/ewb/model/cim/extensions/iec61970/base/protection/protection_relay_function.py index da57a5a21..25d30e41f 100644 --- a/src/zepben/ewb/model/cim/extensions/iec61970/base/protection/protection_relay_function.py +++ b/src/zepben/ewb/model/cim/extensions/iec61970/base/protection/protection_relay_function.py @@ -7,7 +7,13 @@ __all__ = ["ProtectionRelayFunction"] +import sys +import warnings from typing import Optional, List, Generator, Iterable, Callable, TYPE_CHECKING +if sys.version_info >= (3, 13): + from warnings import deprecated +else: + from typing_extensions import deprecated from zepben.ewb.model.cim.extensions.iec61970.base.protection.power_direction_kind import PowerDirectionKind from zepben.ewb.model.cim.extensions.iec61970.base.protection.protection_kind import ProtectionKind @@ -30,6 +36,8 @@ class ProtectionRelayFunction(PowerSystemResource): A function that a relay implements to protect equipment. """ + asset_info: Optional[RelayInfo] = None + model: Optional[str] = None """[ZBEX] The protection equipment type name(manufacturer information).""" @@ -58,13 +66,16 @@ class ProtectionRelayFunction(PowerSystemResource): _thresholds: Optional[List[RelaySetting]] = None - def __init__(self, - sensors: Iterable[Sensor] = None, - protected_switches: Iterable[ProtectedSwitch] = None, - schemes: Iterable[ProtectionRelayScheme] = None, - time_limits: Iterable[float] = None, - thresholds: Iterable[RelaySetting] = None, - relay_info: RelayInfo = None, **kwargs): + def __init__( + self, + sensors: Iterable[Sensor] = None, + protected_switches: Iterable[ProtectedSwitch] = None, + schemes: Iterable[ProtectionRelayScheme] = None, + time_limits: Iterable[float] = None, + thresholds: Iterable[RelaySetting] = None, + relay_info: RelayInfo | None = None, + **kwargs + ): super(ProtectionRelayFunction, self).__init__(**kwargs) if sensors is not None: @@ -83,14 +94,17 @@ def __init__(self, for threshold in thresholds: self.add_threshold(threshold) if relay_info is not None: - self.relay_info = relay_info + warnings.warn("relay_info is deprecated, use asset_info instead.") + self.asset_info = relay_info @property + @deprecated("use asset_info instead.") def relay_info(self): """Datasheet information for this CurrentRelay""" return self.asset_info @relay_info.setter + @deprecated("use asset_info instead.") def relay_info(self, relay_info: Optional[RelayInfo]): self.asset_info = relay_info diff --git a/src/zepben/ewb/model/cim/iec61970/base/auxiliaryequipment/current_transformer.py b/src/zepben/ewb/model/cim/iec61970/base/auxiliaryequipment/current_transformer.py index 8e259e339..439a0e3eb 100644 --- a/src/zepben/ewb/model/cim/iec61970/base/auxiliaryequipment/current_transformer.py +++ b/src/zepben/ewb/model/cim/iec61970/base/auxiliaryequipment/current_transformer.py @@ -5,7 +5,12 @@ __all__ = ["CurrentTransformer"] +import sys from typing import Optional, TYPE_CHECKING +if sys.version_info >= (3, 13): + from warnings import deprecated +else: + from typing_extensions import deprecated from zepben.ewb.model.cim.iec61970.base.auxiliaryequipment.sensor import Sensor @@ -20,15 +25,19 @@ class CurrentTransformer(Sensor): A typical secondary current rating would be 5A. """ + asset_info: 'CurrentTransformerInfo | None' = None + core_burden: Optional[int] = None """Power burden of the CT core in watts.""" @property + @deprecated("use asset_info instead.") def current_transformer_info(self) -> Optional['CurrentTransformerInfo']: """The `CurrentTransformerInfo` for this `CurrentTransformer`""" return self.asset_info @current_transformer_info.setter + @deprecated("use asset_info instead.") def current_transformer_info(self, cti: Optional['CurrentTransformerInfo']): """ Set the `CurrentTransformerInfo` for this `CurrentTransformer` diff --git a/src/zepben/ewb/model/cim/iec61970/base/auxiliaryequipment/potential_transformer.py b/src/zepben/ewb/model/cim/iec61970/base/auxiliaryequipment/potential_transformer.py index 222c3ce25..d7a6b7a91 100644 --- a/src/zepben/ewb/model/cim/iec61970/base/auxiliaryequipment/potential_transformer.py +++ b/src/zepben/ewb/model/cim/iec61970/base/auxiliaryequipment/potential_transformer.py @@ -5,7 +5,12 @@ __all__ = ["PotentialTransformer"] +import sys from typing import Optional, TYPE_CHECKING +if sys.version_info >= (3, 13): + from warnings import deprecated +else: + from typing_extensions import deprecated from zepben.ewb.model.cim.iec61970.base.auxiliaryequipment.potential_transformer_kind import PotentialTransformerKind from zepben.ewb.model.cim.iec61970.base.auxiliaryequipment.sensor import Sensor @@ -21,15 +26,19 @@ class PotentialTransformer(Sensor): sometimes auxiliary substation supply. A typical secondary voltage rating would be 120V. """ + asset_info: 'PotentialTransformerInfo | None' = None + type: PotentialTransformerKind = PotentialTransformerKind.UNKNOWN """Potential transformer construction type.""" @property + @deprecated("use asset_info instead.") def potential_transformer_info(self) -> Optional['PotentialTransformerInfo']: """The `PotentialTransformerInfo` for this `PotentialTransformer`""" return self.asset_info @potential_transformer_info.setter + @deprecated("use asset_info instead.") def potential_transformer_info(self, vti: Optional['PotentialTransformerInfo']): """ Set the `PotentialTransformerInfo` for this `PotentialTransformer` diff --git a/src/zepben/ewb/model/cim/iec61970/base/wires/ac_line_segment.py b/src/zepben/ewb/model/cim/iec61970/base/wires/ac_line_segment.py index 28fa68d50..0081f3c28 100644 --- a/src/zepben/ewb/model/cim/iec61970/base/wires/ac_line_segment.py +++ b/src/zepben/ewb/model/cim/iec61970/base/wires/ac_line_segment.py @@ -7,11 +7,10 @@ __all__ = ["AcLineSegment"] -from functools import singledispatchmethod -from typing import Optional, List, Generator, TYPE_CHECKING +from typing import Optional, Generator, TYPE_CHECKING -from zepben.ewb.model.cim.iec61970.base.wires.conductor import Conductor from zepben.ewb.model.cim.iec61970.base.wires.ac_line_segment_phase import AcLineSegmentPhase +from zepben.ewb.model.cim.iec61970.base.wires.conductor import Conductor from zepben.ewb.model.cim.iec61970.base.wires.single_phase_kind import SinglePhaseKind from zepben.ewb.util import nlen, ngen, get_by_mrid, safe_remove, require @@ -42,7 +41,7 @@ class AcLineSegment(Conductor): per_length_impedance: 'PerLengthImpedance | None' = None """A `zepben.ewb.model.cim.iec61970.base.wires.PerLengthImpedance` describing this AcLineSegment""" - _cuts: list['Cut'] | None= None + _cuts: list['Cut'] | None = None _clamps: list['Clamp'] | None = None _phases: list['AcLineSegmentPhase'] | None = None @@ -198,8 +197,10 @@ def _validate_cut(self, cut: 'Cut') -> bool: if not cut.ac_line_segment: cut.ac_line_segment = self - require(cut.ac_line_segment is self, - lambda: f"Cut {cut} references another AcLineSegment {cut.ac_line_segment}, expected {str(self)}.") + require( + cut.ac_line_segment is self, + lambda: f"Cut {cut} references another AcLineSegment {cut.ac_line_segment}, expected {str(self)}.", + ) return False def _validate_clamp(self, clamp: 'Clamp') -> bool: @@ -216,12 +217,14 @@ def _validate_clamp(self, clamp: 'Clamp') -> bool: if not clamp.ac_line_segment: clamp.ac_line_segment = self - require(clamp.ac_line_segment is self, - lambda: f"Clamp {clamp} references another AcLineSegment {clamp.ac_line_segment}, expected {str(self)}.") + require( + clamp.ac_line_segment is self, + lambda: f"Clamp {clamp} references another AcLineSegment {clamp.ac_line_segment}, expected {str(self)}.", + ) return False @property - def phases(self) -> Generator['Phase', None, None]: + def phases(self) -> Generator['AcLineSegmentPhase', None, None]: """ The individual phase models for this AcLineSegment. The returned collection is read only. """ @@ -300,4 +303,4 @@ def wire_info_for_phase(self, phase: SinglePhaseKind) -> 'WireInfo | None': for it in self._phases: if it.phase == phase: return it.asset_info - return self.wire_info + return self.asset_info diff --git a/src/zepben/ewb/model/cim/iec61970/base/wires/conductor.py b/src/zepben/ewb/model/cim/iec61970/base/wires/conductor.py index eddeaae6f..7300379eb 100644 --- a/src/zepben/ewb/model/cim/iec61970/base/wires/conductor.py +++ b/src/zepben/ewb/model/cim/iec61970/base/wires/conductor.py @@ -5,10 +5,15 @@ __all__ = ["Conductor"] +import sys from typing import Optional, TYPE_CHECKING +if sys.version_info >= (3, 13): + from warnings import deprecated +else: + from typing_extensions import deprecated -from zepben.ewb.model.cim.iec61970.base.core.conducting_equipment import ConductingEquipment from zepben.ewb.model.cim.iec61968.assetinfo.cable_info import CableInfo +from zepben.ewb.model.cim.iec61970.base.core.conducting_equipment import ConductingEquipment if TYPE_CHECKING: from zepben.ewb.model.cim.iec61968.assetinfo.wire_info import WireInfo @@ -20,6 +25,8 @@ class Conductor(ConductingEquipment): system, used to carry current between points in the power system. """ + asset_info: 'WireInfo | None' = None + length: Optional[float] = None """Segment length for calculating line section capabilities.""" @@ -30,11 +37,13 @@ class Conductor(ConductingEquipment): """[ZBEX] The current rating in Amperes at the specified design temperature that can be used without the conductor breaching physical network""" @property + @deprecated("use asset_info instead.") def wire_info(self): """The `WireInfo` for this `Conductor`""" return self.asset_info @wire_info.setter + @deprecated("use asset_info instead.") def wire_info(self, wi: Optional['WireInfo']): """ Set the `WireInfo` for this `Conductor` @@ -46,4 +55,4 @@ def is_underground(self): """ :return: True if this `Conductor` is underground. """ - return isinstance(self.wire_info, CableInfo) + return isinstance(self.asset_info, CableInfo) diff --git a/src/zepben/ewb/model/cim/iec61970/base/wires/power_transformer.py b/src/zepben/ewb/model/cim/iec61970/base/wires/power_transformer.py index 3a14ebca4..5fa1ea9eb 100644 --- a/src/zepben/ewb/model/cim/iec61970/base/wires/power_transformer.py +++ b/src/zepben/ewb/model/cim/iec61970/base/wires/power_transformer.py @@ -7,7 +7,12 @@ __all__ = ["PowerTransformer"] +import sys from typing import List, Optional, Generator, TYPE_CHECKING +if sys.version_info >= (3, 13): + from warnings import deprecated +else: + from typing_extensions import deprecated from zepben.ewb.model.cim.extensions.iec61970.base.wires.vector_group import VectorGroup from zepben.ewb.model.cim.iec61968.infiec61968.infassetinfo.transformer_construction_kind import TransformerConstructionKind @@ -37,9 +42,10 @@ class PowerTransformer(ConductingEquipment): Attributes - vector_group : `zepben.protobuf.cim.iec61970.base.wires.VectorGroup` of the transformer for protective relaying. power_transformer_ends : - - """ + + asset_info: PowerTransformerInfo | None = None + vector_group: VectorGroup = VectorGroup.UNKNOWN """ Vector group of the transformer for protective relaying, e.g., Dyn1. For unbalanced transformers, this may not be simply @@ -98,11 +104,13 @@ def ends(self) -> Generator[PowerTransformerEnd, None, None]: return ngen(self._power_transformer_ends) @property + @deprecated("use asset_info instead.") def power_transformer_info(self) -> Optional[PowerTransformerInfo]: """The `PowerTransformerInfo` for this `PowerTransformer`""" return self.asset_info @power_transformer_info.setter + @deprecated("use asset_info instead.") def power_transformer_info(self, pti: Optional[PowerTransformerInfo]): """ Set the `PowerTransformerInfo` for this `PowerTransformer` @@ -212,6 +220,8 @@ def _validate_end(self, end: PowerTransformerEnd) -> bool: if not end.power_transformer: end.power_transformer = self - require(end.power_transformer is self, - lambda: f"PowerTransformerEnd {end} references another PowerTransformer {end.power_transformer}, expected {str(self)}.") + require( + end.power_transformer is self, + lambda: f"PowerTransformerEnd {end} references another PowerTransformer {end.power_transformer}, expected {str(self)}.", + ) return False diff --git a/src/zepben/ewb/model/cim/iec61970/base/wires/shunt_compensator.py b/src/zepben/ewb/model/cim/iec61970/base/wires/shunt_compensator.py index a80e8da0b..2a1916225 100644 --- a/src/zepben/ewb/model/cim/iec61970/base/wires/shunt_compensator.py +++ b/src/zepben/ewb/model/cim/iec61970/base/wires/shunt_compensator.py @@ -5,7 +5,12 @@ __all__ = ["ShuntCompensator"] +import sys from typing import Optional, TYPE_CHECKING +if sys.version_info >= (3, 13): + from warnings import deprecated +else: + from typing_extensions import deprecated from zepben.ewb.model.cim.iec61970.base.wires.phase_shunt_connection_kind import PhaseShuntConnectionKind from zepben.ewb.model.cim.iec61970.base.wires.regulating_cond_eq import RegulatingCondEq @@ -36,22 +41,23 @@ class ShuntCompensator(RegulatingCondEq): For `NonlinearShuntCompensator`s shall only be set to one of the NonlinearShuntCompensatorPoint.sectionNumber. There is no interpolation between NonlinearShuntCompensatorPoint-s. """ - grounded: Optional[bool] = None - nom_u: Optional[int] = None + asset_info: 'ShuntCompensatorInfo | None' = None + grounded: Optional[bool] = None + nom_u: Optional[int] = None phase_connection: PhaseShuntConnectionKind = PhaseShuntConnectionKind.UNKNOWN - grounding_terminal: 'Terminal | None' = None - sections: Optional[float] = None @property + @deprecated("use asset_info instead.") def shunt_compensator_info(self) -> Optional['ShuntCompensatorInfo']: """The `ShuntCompensatorInfo` for this `ShuntCompensator`""" return self.asset_info @shunt_compensator_info.setter + @deprecated("use asset_info instead.") def shunt_compensator_info(self, sci: Optional['ShuntCompensatorInfo']): """ Set the `ShuntCompensatorInfo` for this `ShuntCompensator` diff --git a/src/zepben/ewb/model/cim/iec61970/base/wires/switch.py b/src/zepben/ewb/model/cim/iec61970/base/wires/switch.py index 9935071fa..c34c80eaa 100644 --- a/src/zepben/ewb/model/cim/iec61970/base/wires/switch.py +++ b/src/zepben/ewb/model/cim/iec61970/base/wires/switch.py @@ -7,7 +7,12 @@ __all__ = ["Switch"] +import sys from typing import Optional, TYPE_CHECKING +if sys.version_info >= (3, 13): + from warnings import deprecated +else: + from typing_extensions import deprecated from zepben.ewb.model.cim.iec61970.base.core.conducting_equipment import ConductingEquipment from zepben.ewb.model.cim.iec61970.base.wires.single_phase_kind import SinglePhaseKind @@ -45,6 +50,8 @@ class Switch(ConductingEquipment): value for each phase of the switch. """ + asset_info: SwitchInfo | None = None + rated_current: Optional[float] = None """The maximum continuous current carrying capacity in amps governed by the device material and construction. The attribute shall be a positive value.""" @@ -56,11 +63,13 @@ class Switch(ConductingEquipment): is expected to match with the Switch.normalOpen.""" @property + @deprecated("use asset_info instead.") def switch_info(self) -> Optional[SwitchInfo]: """Datasheet information for this Switch.""" return self.asset_info @switch_info.setter + @deprecated("use asset_info instead.") def switch_info(self, si: Optional[SwitchInfo]): """ Set the :class:`SwitchInfo` for this :class:`Switch` diff --git a/src/zepben/ewb/services/network/network_service_comparator.py b/src/zepben/ewb/services/network/network_service_comparator.py index c9fa7e591..ad1fe6aae 100644 --- a/src/zepben/ewb/services/network/network_service_comparator.py +++ b/src/zepben/ewb/services/network/network_service_comparator.py @@ -7,7 +7,6 @@ from zepben.ewb import BatteryControl, PanDemandResponseFunction, StaticVarCompensator from zepben.ewb.model.cim.extensions.iec61968.assetinfo.relay_info import RelayInfo -from zepben.ewb.model.cim.extensions.iec61968.common.contact_details import ContactDetails from zepben.ewb.model.cim.extensions.iec61970.base.core.hv_customer import HvCustomer from zepben.ewb.model.cim.extensions.iec61970.base.core.site import Site from zepben.ewb.model.cim.extensions.iec61970.base.feeder.loop import Loop @@ -288,7 +287,6 @@ def _compare_protection_relay_function(self, diff: ObjectDifference) -> ObjectDi ProtectionRelayFunction.sensors, ProtectionRelayFunction.schemes, ) - self._compare_id_references(diff, ProtectionRelayFunction.relay_info) return self._compare_power_system_resource(diff) @@ -637,7 +635,6 @@ def _compare_current_transformer(self, source: CurrentTransformer, target: Curre diff = ObjectDifference(source, target) self._compare_values(diff, CurrentTransformer.core_burden) - self._compare_id_references(diff, CurrentTransformer.current_transformer_info) return self._compare_sensor(diff) @@ -648,7 +645,6 @@ def _compare_potential_transformer(self, source: PotentialTransformer, target: P diff = ObjectDifference(source, target) self._compare_values(diff, PotentialTransformer.type) - self._compare_id_references(diff, PotentialTransformer.potential_transformer_info) return self._compare_sensor(diff) @@ -936,7 +932,6 @@ def _compare_clamp(self, source: Clamp, target: Clamp) -> ObjectDifference: def _compare_conductor(self, diff: ObjectDifference) -> ObjectDifference: self._compare_floats(diff, Conductor.length, Conductor.design_rating) self._compare_values(diff, Conductor.design_temperature) - self._compare_id_references(diff, Conductor.wire_info) return self._compare_conducting_equipment(diff) @@ -1161,7 +1156,6 @@ def _compare_power_transformer(self, source: PowerTransformer, target: PowerTran self._compare_indexed_id_reference_collections(diff, PowerTransformer.ends) self._compare_values(diff, PowerTransformer.vector_group, PowerTransformer.construction_kind, PowerTransformer.function) self._compare_floats(diff, PowerTransformer.transformer_utilisation) - self._compare_id_references(diff, PowerTransformer.power_transformer_info) return self._compare_conducting_equipment(diff) @@ -1256,7 +1250,6 @@ def _compare_series_compensator(self, source: SeriesCompensator, target: SeriesC def _compare_shunt_compensator(self, diff: ObjectDifference) -> ObjectDifference: self._compare_values(diff, ShuntCompensator.grounded, ShuntCompensator.nom_u, ShuntCompensator.phase_connection) self._compare_floats(diff, ShuntCompensator.sections) - self._compare_id_references(diff, ShuntCompensator.shunt_compensator_info) self._compare_id_references(diff, ShuntCompensator.grounding_terminal) return self._compare_regulating_cond_eq(diff) @@ -1277,7 +1270,6 @@ def _compare_switch(self, diff: ObjectDifference) -> ObjectDifference: self._compare_floats(diff, Switch.rated_current) self._add_if_different(diff, "isNormallyOpen", self._compare_open_status(diff, lambda it, phase: it.is_normally_open(phase))) self._add_if_different(diff, "isOpen", self._compare_open_status(diff, lambda it, phase: it.is_open())) - self._compare_id_references(diff, Switch.switch_info) return self._compare_conducting_equipment(diff) diff --git a/test/cim/fill_fields.py b/test/cim/fill_fields.py index a5be38689..75aadbd46 100644 --- a/test/cim/fill_fields.py +++ b/test/cim/fill_fields.py @@ -306,7 +306,7 @@ def protection_relay_function_kwargs(include_runtime: bool = True): "schemes": lists(builds(ProtectionRelayScheme, mrid=mrid_strategy), max_size=2), "time_limits": lists(floats(min_value=FLOAT_MIN, max_value=FLOAT_MAX), min_size=4, max_size=4), "thresholds": lists(create_relay_setting(), min_size=4, max_size=4), - "relay_info": builds(RelayInfo, mrid=mrid_strategy), + "asset_info": builds(RelayInfo, mrid=mrid_strategy), } @@ -2202,9 +2202,10 @@ def switch_kwargs(include_runtime: bool): "rated_current": floats(min_value=1, max_value=FLOAT_MAX), # NOTE: These are not currently encoded properly in protobuf so we can only use all or none. "_normally_open": sampled_from([0, 15]), - "_open": sampled_from([0, 15]) + "_open": sampled_from([0, 15]), # "_normally_open": integers(min_value=0, max_value=15), # "_open": integers(min_value=0, max_value=15), + "asset_info": builds(SwitchInfo, **identified_object_kwargs(include_runtime)), } diff --git a/test/database/sqlite/schema_utils.py b/test/database/sqlite/schema_utils.py index e9b4e9f2e..aa0704d60 100644 --- a/test/database/sqlite/schema_utils.py +++ b/test/database/sqlite/schema_utils.py @@ -8,14 +8,12 @@ from hypothesis import assume from zepben.ewb import MetadataCollection, NetworkService, DiagramService, CustomerService, NameType, DataSource, IdentifiedObject, EnergyConsumer, \ - EnergySourcePhase, EnergySource, BaseService, PowerTransformerInfo, TransformerEndInfo, TransformerTankInfo, Asset, Pole, Streetlight, \ - OrganisationRole, Customer, CustomerAgreement, PricingStructure, OperationalRestriction, AuxiliaryEquipment, ConductingEquipment, \ - ConnectivityNode, Equipment, EquipmentContainer, Name, PowerSystemResource, Substation, Terminal, \ - Control, Measurement, RemoteControl, RemoteSource, PowerElectronicsUnit, AcLineSegment, PowerElectronicsConnection, \ - PowerTransformer, ShuntCompensator, TransformerStarImpedance, \ - Circuit, Loop, LvFeeder, ProtectedSwitch, CurrentTransformer, PotentialTransformer, RegulatingCondEq, RegulatingControl, \ - ProtectionRelayFunction, Sensor, ProtectionRelayScheme, ProtectionRelaySystem, Fuse, TBaseService, TIdentifiedObject, SynchronousMachine, BatteryUnit, \ - generate_id, LinearShuntCompensator + EnergySourcePhase, EnergySource, BaseService, PowerTransformerInfo, TransformerEndInfo, TransformerTankInfo, Asset, Pole, Streetlight, OrganisationRole, \ + Customer, CustomerAgreement, PricingStructure, OperationalRestriction, AuxiliaryEquipment, ConductingEquipment, ConnectivityNode, Equipment, \ + EquipmentContainer, Name, PowerSystemResource, Substation, Terminal, Control, Measurement, RemoteControl, RemoteSource, PowerElectronicsUnit, \ + AcLineSegment, PowerElectronicsConnection, PowerTransformer, TransformerStarImpedance, Circuit, Loop, LvFeeder, ProtectedSwitch, RegulatingCondEq, \ + RegulatingControl, ProtectionRelayFunction, Sensor, ProtectionRelayScheme, ProtectionRelaySystem, Fuse, TBaseService, TIdentifiedObject, \ + SynchronousMachine, BatteryUnit, generate_id, LinearShuntCompensator from zepben.ewb.model.cim.iec61968.common.street_address import StreetAddress from zepben.ewb.model.cim.iec61968.metering.end_device import EndDevice from zepben.ewb.model.cim.iec61968.metering.usage_point import UsagePoint @@ -26,7 +24,6 @@ from zepben.ewb.model.cim.iec61970.base.diagramlayout.diagram_object import DiagramObject from zepben.ewb.model.cim.iec61970.base.wires.ac_line_segment_phase import AcLineSegmentPhase from zepben.ewb.model.cim.iec61970.base.wires.clamp import Clamp -from zepben.ewb.model.cim.iec61970.base.wires.conductor import Conductor from zepben.ewb.model.cim.iec61970.base.wires.cut import Cut from zepben.ewb.model.cim.iec61970.base.wires.energy_consumer_phase import EnergyConsumerPhase from zepben.ewb.model.cim.iec61970.base.wires.power_electronics_connection_phase import PowerElectronicsConnectionPhase @@ -52,7 +49,7 @@ def create_name_test_services(service_type: Type[TBaseService], object_type: Typ name_type.description = "type description" services.add_name_type(name_type) - obj: object_type + obj: TIdentifiedObject try: obj = object_type(mrid="obj1") except Exception as ex: @@ -172,7 +169,6 @@ def _add_with_references(filled: T, service: BaseService): for it in filled.schemes: it.add_function(filled) service.add(it) - service.add(filled.relay_info) if isinstance(filled, ProtectionRelayScheme): if filled.system is not None: @@ -314,12 +310,6 @@ def _add_with_references(filled: T, service: BaseService): if isinstance(filled, AuxiliaryEquipment): service.add(filled.terminal) - if isinstance(filled, CurrentTransformer): - service.add(filled.asset_info) - - if isinstance(filled, PotentialTransformer): - service.add(filled.asset_info) - ###################### # IEC61970 Base Core # ###################### @@ -369,6 +359,8 @@ def _add_with_references(filled: T, service: BaseService): service.add_name_type(filled.type) if isinstance(filled, PowerSystemResource): + if filled.asset_info is not None: + service.add(filled.asset_info) service.add(filled.location) for it in filled.assets: it.add_power_system_resource(filled) @@ -484,8 +476,6 @@ def _add_with_references(filled: T, service: BaseService): service.add(it) if isinstance(filled, AcLineSegmentPhase): - if filled.asset_info is not None: - service.add(filled.asset_info) filled.ac_line_segment.add_phase(filled) service.add(filled.ac_line_segment) @@ -493,9 +483,6 @@ def _add_with_references(filled: T, service: BaseService): filled.ac_line_segment.add_clamp(filled) service.add(filled.ac_line_segment) - if isinstance(filled, Conductor): - service.add(filled.asset_info) - if isinstance(filled, Cut): filled.ac_line_segment.add_cut(filled) service.add(filled.ac_line_segment) @@ -548,7 +535,6 @@ def _add_with_references(filled: T, service: BaseService): service.add(filled.power_electronics_connection) if isinstance(filled, PowerTransformer): - service.add(filled.asset_info) for it in filled.ends: it.power_transformer = filled service.add(it) @@ -567,9 +553,6 @@ def _add_with_references(filled: T, service: BaseService): service.add(filled.transformer_end) service.add(filled.tap_changer_control) - if isinstance(filled, ShuntCompensator): - service.add(filled.asset_info) - if isinstance(filled, SynchronousMachine): # The curves use a one way link, so we just need to add them. for it in filled.curves: diff --git a/test/services/common/test_base_service.py b/test/services/common/test_base_service.py index 3168f0c10..163e453bc 100644 --- a/test/services/common/test_base_service.py +++ b/test/services/common/test_base_service.py @@ -179,7 +179,7 @@ def test_unresolved_references(service: BaseService): assert service.num_unresolved_references() == 4 _add_and_check(service, plsi1, acls1, "per_length_impedance") assert service.num_unresolved_references() == 3 - _add_and_check(service, ci1, acls1, "wire_info") + _add_and_check(service, ci1, acls1, "asset_info") assert service.num_unresolved_references() == 2 _add_and_check(service, t1, acls1, "terminals") assert service.num_unresolved_references() == 1 diff --git a/test/services/network/test_network_service_comparator.py b/test/services/network/test_network_service_comparator.py index 601812d70..2d9825d13 100644 --- a/test/services/network/test_network_service_comparator.py +++ b/test/services/network/test_network_service_comparator.py @@ -72,7 +72,7 @@ class TestNetworkServiceComparator(TestBaseServiceComparator): validator = ServiceComparatorValidator[NetworkService, NetworkServiceComparator]( create_service=lambda: NetworkService(), - create_comparator=lambda options: NetworkServiceComparator(options) + create_comparator=lambda options: NetworkServiceComparator(options), ) ################################## @@ -294,15 +294,6 @@ def _compare_protection_relay_function(self, creator: Type[ProtectionRelayFuncti creator, lambda _: RelayInfo(mrid="ari1"), lambda _: RelayInfo(mrid="ari2"), - expected_differences={"relay_info"}, - ) - - self.validator.validate_property( - ProtectionRelayFunction.relay_info, - creator, - lambda _: RelayInfo(mrid="ri1"), - lambda _: RelayInfo(mrid="ri2"), - expected_differences={"asset_info"}, ) def test_compare_protection_relay_scheme(self): @@ -352,8 +343,12 @@ def test_compare_battery_control(self): self.validator.validate_property(BatteryControl.charging_rate, BatteryControl, lambda _: 1.0, lambda _: 2.0) self.validator.validate_property(BatteryControl.discharging_rate, BatteryControl, lambda _: 1.0, lambda _: 2.0) self.validator.validate_property(BatteryControl.reserve_percent, BatteryControl, lambda _: 1.0, lambda _: 2.0) - self.validator.validate_property(BatteryControl.control_mode, BatteryControl, lambda _: BatteryControlMode.peakShaveCharge, - lambda _: BatteryControlMode.peakShaveDischarge) + self.validator.validate_property( + BatteryControl.control_mode, + BatteryControl, + lambda _: BatteryControlMode.peakShaveCharge, + lambda _: BatteryControlMode.peakShaveDischarge, + ) ####################### # IEC61968 Asset Info # @@ -691,14 +686,6 @@ def test_compare_current_transformer(self): CurrentTransformer, lambda _: CurrentTransformerInfo(mrid="acti1"), lambda _: CurrentTransformerInfo(mrid="acti2"), - expected_differences={"current_transformer_info"}, - ) - self.validator.validate_property( - CurrentTransformer.current_transformer_info, - CurrentTransformer, - lambda _: CurrentTransformerInfo(mrid="acti1"), - lambda _: CurrentTransformerInfo(mrid="acti2"), - expected_differences={"asset_info"}, ) def test_compare_fault_indicator(self): @@ -718,14 +705,6 @@ def test_compare_potential_transformer(self): PotentialTransformer, lambda _: PotentialTransformerInfo(mrid="avti1"), lambda _: PotentialTransformerInfo(mrid="avti2"), - expected_differences={"potential_transformer_info"}, - ) - self.validator.validate_property( - PotentialTransformer.potential_transformer_info, - PotentialTransformer, - lambda _: PotentialTransformerInfo(mrid="vti1"), - lambda _: PotentialTransformerInfo(mrid="vti2"), - expected_differences={"asset_info"}, ) def _compare_sensor(self, creator: Type[Sensor]): @@ -1145,10 +1124,7 @@ def _compare_conductor(self, creator: Type[Conductor]): self.validator.validate_property(Conductor.length, creator, lambda _: 1.0, lambda _: 2.0) self.validator.validate_property(Conductor.design_temperature, creator, lambda _: 1, lambda _: 2) self.validator.validate_property(Conductor.design_rating, creator, lambda _: 1.0, lambda _: 2.0) - self.validator.validate_property(Conductor.asset_info, creator, lambda _: CableInfo(mrid="c1"), lambda _: CableInfo(mrid="c2"), - expected_differences={"wire_info"}) - self.validator.validate_property(Conductor.wire_info, creator, lambda _: OverheadWireInfo(mrid="owi1"), lambda _: OverheadWireInfo(mrid="c2"), - expected_differences={"asset_info"}) + self.validator.validate_property(Conductor.asset_info, creator, lambda _: CableInfo(mrid="c1"), lambda _: CableInfo(mrid="c2")) def _compare_connector(self, creator: Type[Connector]): self._compare_conducting_equipment(creator) @@ -1398,10 +1374,18 @@ def test_compare_power_transformer(self): self.validator.validate_property(PowerTransformer.vector_group, PowerTransformer, lambda _: VectorGroup.DYN11, lambda _: VectorGroup.D0) self.validator.validate_property(PowerTransformer.transformer_utilisation, PowerTransformer, lambda _: 0.1, lambda _: 0.9) - self.validator.validate_property(PowerTransformer.construction_kind, PowerTransformer, lambda _: TransformerConstructionKind.subway, - lambda _: TransformerConstructionKind.overhead) - self.validator.validate_property(PowerTransformer.function, PowerTransformer, lambda _: TransformerFunctionKind.isolationTransformer, - lambda _: TransformerFunctionKind.voltageRegulator) + self.validator.validate_property( + PowerTransformer.construction_kind, + PowerTransformer, + lambda _: TransformerConstructionKind.subway, + lambda _: TransformerConstructionKind.overhead, + ) + self.validator.validate_property( + PowerTransformer.function, + PowerTransformer, + lambda _: TransformerFunctionKind.isolationTransformer, + lambda _: TransformerFunctionKind.voltageRegulator, + ) self.validator.validate_indexed_collection( PowerTransformer.ends, PowerTransformer.add_end, @@ -1415,15 +1399,6 @@ def test_compare_power_transformer(self): PowerTransformer, lambda _: PowerTransformerInfo(mrid="apti1"), lambda _: PowerTransformerInfo(mrid="apti2"), - expected_differences={"power_transformer_info"}, - ) - - self.validator.validate_property( - PowerTransformer.power_transformer_info, - PowerTransformer, - lambda _: PowerTransformerInfo(mrid="pti1"), - lambda _: PowerTransformerInfo(mrid="pti2"), - expected_differences={"asset_info"}, ) def test_compare_power_transformer_end(self): @@ -1560,10 +1535,12 @@ def _compare_shunt_compensator(self, creator: Type[ShuntCompensator]): lambda _: PhaseShuntConnectionKind.G, ) self.validator.validate_property(ShuntCompensator.sections, creator, lambda _: 1.0, lambda _: 2.0) - self.validator.validate_property(ShuntCompensator.asset_info, creator, lambda _: ShuntCompensatorInfo(mrid="asci1"), - lambda _: ShuntCompensatorInfo(mrid="asci2"), expected_differences={"shunt_compensator_info"}) - self.validator.validate_property(ShuntCompensator.shunt_compensator_info, creator, lambda _: ShuntCompensatorInfo(mrid="sci1"), - lambda _: ShuntCompensatorInfo(mrid="sci2"), expected_differences={"asset_info"}) + self.validator.validate_property( + ShuntCompensator.asset_info, + creator, + lambda _: ShuntCompensatorInfo(mrid="asci1"), + lambda _: ShuntCompensatorInfo(mrid="asci2"), + ) self.validator.validate_property(ShuntCompensator.grounding_terminal, creator, lambda _: Terminal(mrid="t1"), lambda _: Terminal(mrid="t2")) def test_compare_static_var_compensator(self): @@ -1584,10 +1561,7 @@ def _compare_switch(self, creator: Type[Switch]): self._compare_conducting_equipment(creator) self.validator.validate_property(Switch.rated_current, creator, lambda _: 1.1, lambda _: 2.2) - self.validator.validate_property(Switch.asset_info, creator, lambda _: SwitchInfo(mrid="asi1"), lambda _: SwitchInfo(mrid="sai2"), - expected_differences={"switch_info"}) - self.validator.validate_property(Switch.switch_info, creator, lambda _: SwitchInfo(mrid="si1"), lambda _: SwitchInfo(mrid="si2"), - expected_differences={"asset_info"}) + self.validator.validate_property(Switch.asset_info, creator, lambda _: SwitchInfo(mrid="asi1"), lambda _: SwitchInfo(mrid="sai2")) closed_switch = Jumper(mrid="mRID") closed_switch.set_normally_open(False) @@ -1632,10 +1606,18 @@ def test_compare_synchronous_machine(self): self.validator.validate_property(SynchronousMachine.sat_direct_trans_x, SynchronousMachine, lambda _: 1.0, lambda _: 2.0) self.validator.validate_property(SynchronousMachine.x0, SynchronousMachine, lambda _: 1.0, lambda _: 2.0) self.validator.validate_property(SynchronousMachine.x2, SynchronousMachine, lambda _: 1.0, lambda _: 2.0) - self.validator.validate_property(SynchronousMachine.type, SynchronousMachine, lambda _: SynchronousMachineKind.generator, - lambda _: SynchronousMachineKind.motor) - self.validator.validate_property(SynchronousMachine.operating_mode, SynchronousMachine, lambda _: SynchronousMachineKind.generator, - lambda _: SynchronousMachineKind.motor) + self.validator.validate_property( + SynchronousMachine.type, + SynchronousMachine, + lambda _: SynchronousMachineKind.generator, + lambda _: SynchronousMachineKind.motor, + ) + self.validator.validate_property( + SynchronousMachine.operating_mode, + SynchronousMachine, + lambda _: SynchronousMachineKind.generator, + lambda _: SynchronousMachineKind.motor, + ) self.validator.validate_collection( SynchronousMachine.curves, @@ -1655,8 +1637,12 @@ def _compare_tap_changer(self, creator: Type[TapChanger]): self.validator.validate_property(TapChanger.neutral_u, creator, lambda _: 0, lambda _: 1) self.validator.validate_property(TapChanger.normal_step, creator, lambda _: 0, lambda _: 1) self.validator.validate_property(TapChanger.step, creator, lambda _: 0, lambda _: 1) - self.validator.validate_property(TapChanger.tap_changer_control, creator, lambda _: TapChangerControl(mrid="tcc1"), - lambda _: TapChangerControl(mrid="tcc2")) + self.validator.validate_property( + TapChanger.tap_changer_control, + creator, + lambda _: TapChangerControl(mrid="tcc1"), + lambda _: TapChangerControl(mrid="tcc2"), + ) def test_compare_tap_changer_control(self): self._compare_regulating_control(TapChangerControl) @@ -1684,8 +1670,12 @@ def _compare_transformer_end(self, creator: Type[TransformerEnd]): lambda _: RatioTapChanger(mrid="rtc1"), lambda _: RatioTapChanger(mrid="rtc2"), ) - self.validator.validate_property(TransformerEnd.terminal, creator, lambda _: Terminal(mrid="t1", conducting_equipment=PowerTransformer(mrid="t1-pt1")), - lambda _: Terminal(mrid="t2", conducting_equipment=PowerTransformer(mrid="t2-pt2"))) + self.validator.validate_property( + TransformerEnd.terminal, + creator, + lambda _: Terminal(mrid="t1", conducting_equipment=PowerTransformer(mrid="t1-pt1")), + lambda _: Terminal(mrid="t2", conducting_equipment=PowerTransformer(mrid="t2-pt2")), + ) self.validator.validate_property( TransformerEnd.star_impedance, creator, @@ -1700,8 +1690,12 @@ def test_compare_transformer_star_impedance(self): self.validator.validate_property(TransformerStarImpedance.r0, TransformerStarImpedance, lambda _: 1.0, lambda _: 2.0) self.validator.validate_property(TransformerStarImpedance.x, TransformerStarImpedance, lambda _: 1.0, lambda _: 2.0) self.validator.validate_property(TransformerStarImpedance.x0, TransformerStarImpedance, lambda _: 1.0, lambda _: 2.0) - self.validator.validate_property(TransformerStarImpedance.transformer_end_info, TransformerStarImpedance, lambda _: TransformerEndInfo(mrid="tei1"), - lambda _: TransformerEndInfo(mrid="tei2")) + self.validator.validate_property( + TransformerStarImpedance.transformer_end_info, + TransformerStarImpedance, + lambda _: TransformerEndInfo(mrid="tei1"), + lambda _: TransformerEndInfo(mrid="tei2"), + ) ############################### # IEC61970 InfIEC61970 Feeder # From efc1cb83be18594498cc1f2038c34dd39d99f09e Mon Sep 17 00:00:00 2001 From: Anthony Charlton Date: Thu, 26 Mar 2026 21:42:49 +1100 Subject: [PATCH 15/26] You can now pass a list of `TransformerEndRatedS` to the `PowerTransformerEnd` constructor via the `ratings` argument. Signed-off-by: Anthony Charlton --- changelog.md | 1 + .../cim/iec61970/base/wires/power_transformer_end.py | 9 ++++++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/changelog.md b/changelog.md index ec977569b..0cf655c21 100644 --- a/changelog.md +++ b/changelog.md @@ -21,6 +21,7 @@ ### Enhancements * `SetDirection.run` now supports `ConductingEquipment`. * Fixed types on all overrides for `PowerSystemResource.asset_info`, removing the need to shadow them with type specific variants. +* You can now pass a list of `TransformerEndRatedS` to the `PowerTransformerEnd` constructor via the `ratings` argument. ### Fixes * None. diff --git a/src/zepben/ewb/model/cim/iec61970/base/wires/power_transformer_end.py b/src/zepben/ewb/model/cim/iec61970/base/wires/power_transformer_end.py index b3105e427..799867a4f 100644 --- a/src/zepben/ewb/model/cim/iec61970/base/wires/power_transformer_end.py +++ b/src/zepben/ewb/model/cim/iec61970/base/wires/power_transformer_end.py @@ -84,7 +84,7 @@ class PowerTransformerEnd(TransformerEnd): Should not be used directly, instead use add_rating and get_rating functions. """ - def __init__(self, power_transformer: PowerTransformer = None, rated_s: int = None, **kwargs): + def __init__(self, power_transformer: PowerTransformer = None, rated_s: int = None, ratings: list[TransformerEndRatedS] = None, **kwargs): super(PowerTransformerEnd, self).__init__(**kwargs) if power_transformer: self.power_transformer = power_transformer @@ -102,6 +102,9 @@ def __init__(self, power_transformer: PowerTransformer = None, rated_s: int = No if self._rated_s is not None: self.rated_s = self._rated_s self._rated_s = None + if ratings: + for rating in ratings: + self.add_rating(rating.rated_s, rating.cooling_type) @property def power_transformer(self): @@ -125,8 +128,8 @@ def rated_s(self) -> Optional[int]: Normal apparent power rating. The attribute shall be a positive value. For a two-winding transformer the values for the high and low voltage sides shall be identical. """ - if self._s_ratings: - return self._s_ratings[0].rated_s if len(self._s_ratings) > 0 else None + if self._s_ratings and len(self._s_ratings) > 0: + return self._s_ratings[0].rated_s return None @rated_s.setter From 3b82b23465ae3007b418d4884c0bfd928d6efeb5 Mon Sep 17 00:00:00 2001 From: Anthony Charlton Date: Thu, 26 Mar 2026 21:44:00 +1100 Subject: [PATCH 16/26] Coding style Signed-off-by: Anthony Charlton --- .idea/codeStyles/Project.xml | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml index feb22dcbc..8d529247b 100644 --- a/.idea/codeStyles/Project.xml +++ b/.idea/codeStyles/Project.xml @@ -16,6 +16,18 @@