def _check_open(current_state: int, phase: SinglePhaseKind = None) -> bool: require(phase != SinglePhaseKind.NONE and phase != SinglePhaseKind.INVALID, lambda: f"Invalid phase {phase} specified") if phase is None: return current_state != 0 else: return (current_state & phase.bit_mask) != 0
def _calculate_open_state(current_state: int, is_open: bool, phase: SinglePhaseKind = None) -> int: require(phase != SinglePhaseKind.NONE and phase != SinglePhaseKind.INVALID, lambda: f"Invalid phase {phase} specified") if phase is None: return 0b1111 if is_open else 0 else: return current_state | phase.bit_mask if is_open else current_state & ~phase.bit_mask
def __init__(self): require( -90.0 <= self.y_position <= 90.0, lambda: f"Latitude is out of range. Expected -90 to 90, got {self.y_position}." ) require( -180.0 <= self.x_position <= 180.0, lambda: f"Longitude is out of range. Expected -180 to 180, got {self.x_position}." )
def add_point(self, point: PositionPoint, sequence_number: int = None) -> Location: """ Associate a `PositionPoint` with this `Location` `point` The `PositionPoint` to associate with this `Location`. `sequence_number` The sequence number of the `PositionPoint`. Returns A reference to this `Location` to allow fluent use. Raises `ValueError` if `sequence_number` is set and not between 0 and `num_points()` """ if sequence_number is None: sequence_number = self.num_points() require( 0 <= sequence_number <= self.num_points(), lambda: f"Unable to add PositionPoint to Location {str(self)}. Sequence number {sequence_number} is invalid. " f"Expected a value between 0 and {self.num_points()}. Make sure you are adding the points in order and there are no gaps in the numbering." ) self._position_points = [] if self._position_points is None else self._position_points self._position_points.insert(sequence_number, point) return self
def _validate_reference(self, other: IdentifiedObject, getter: Callable[[str], IdentifiedObject], type_descr: str) -> bool: """ Validate whether a given reference exists to `other` using the provided getter function. `other` The object to look up with the getter using its mRID. `getter` A function that takes an mRID and returns an object if it exists, and throws a ``KeyError`` if it couldn't be found. `type_descr` The type description to use for the lazily generated error message. Should be of the form "A[n] type(other)" Returns True if `other` was retrieved with `getter` and was equivalent, False otherwise. Raises `ValueError` if the object retrieved from `getter` is not `other`. """ try: get_result = getter(other.mrid) require( get_result is other, lambda: f"{type_descr} with mRID {other.mrid} already exists in {str(self)}" ) return True except (KeyError, AttributeError): return False
def add_object(self, diagram_object: DiagramObject) -> DiagramObject: """ Associate a `DiagramObject` with this `Diagram`. `diagram_object` the `DiagramObject` to associate with this `Diagram`. Returns The previous `DiagramObject` stored by `diagram_object`s mrid, otherwise `diagram_object` is returned if there was no previous value. Raises `ValueError` if another `DiagramObject` with the same `mrid` already exists for this `Diagram`, or if `diagram_object.diagram` is not this `Diagram`. """ require( diagram_object.diagram is self, lambda: f"{str(diagram_object)} references another Diagram " f"{str(diagram_object.diagram)}, expected {str(self)}.") require( not contains_mrid(self._diagram_objects, diagram_object.mrid), lambda: f"A DiagramObject with mRID ${diagram_object.mrid} already exists in {str(self)}." ) self._diagram_objects = dict( ) if self._diagram_objects is None else self._diagram_objects return self._diagram_objects.setdefault(diagram_object.mrid, diagram_object)
def insert_point(self, point: DiagramObjectPoint, sequence_number: int = None) -> DiagramObject: """ Associate a `DiagramObjectPoint` with this `DiagramObject` `point` The `DiagramObjectPoint` to associate with this `DiagramObject`. `sequence_number` The sequence number of the `DiagramObjectPoint`. Returns A reference to this `DiagramObject` to allow fluent use. Raises `ValueError` if `sequence_number` < 0 or > `num_points()`. """ if sequence_number is None: sequence_number = self.num_points() require( 0 <= sequence_number <= self.num_points(), lambda: f"Unable to add DiagramObjectPoint to {str(self)}. Sequence number {sequence_number}" f" is invalid. Expected a value between 0 and {self.num_points}. Make sure you are " f"adding the points in the correct order and there are no missing sequence numbers." ) self._diagram_object_points = list( ) if self._diagram_object_points is None else self._diagram_object_points self._diagram_object_points.insert(sequence_number, point) return self
def _validate_terminal(self, terminal: Terminal) -> bool: """ Validate a terminal against this `ConductingEquipment`'s `zepben.evolve.iec61970.base.core.terminal.Terminal`s. `terminal` The `zepben.evolve.iec61970.base.core.terminal.Terminal` to validate. Returns True if `zepben.evolve.iec61970.base.core.terminal.Terminal`` is already associated with this `ConductingEquipment`, otherwise False. Raises `ValueError` if `zepben.evolve.iec61970.base.core.terminal.Terminal`s `conducting_equipment` is not this `ConductingEquipment`, or if this `ConductingEquipment` has a different `zepben.evolve.iec61970.base.core.terminal.Terminal` with the same mRID. """ if self._validate_reference(terminal, self.get_terminal_by_mrid, "A Terminal"): return True if self._validate_reference_by_sn(terminal.sequence_number, terminal, self.get_terminal_by_sn, "A Terminal"): return True require( terminal.conducting_equipment is self, lambda: f"Terminal {terminal} references another piece of conducting equipment {terminal.conducting_equipment}, expected {str(self)}." ) return False
def _validate_end(self, end: PowerTransformerEnd) -> bool: """ Validate an end against this `PowerTransformer`'s `PowerTransformerEnd`s. `end` The `PowerTransformerEnd` to validate. Returns True if `end` is already associated with this `PowerTransformer`, otherwise False. Raises `ValueError` if `end.power_transformer` is not this `PowerTransformer`, or if this `PowerTransformer` has a different `PowerTransformerEnd` with the same mRID. """ if self._validate_reference(end, self.get_end_by_mrid, "A PowerTransformerEnd"): return True if self._validate_reference_by_sn(end.end_number, end, self.get_end_by_num, "A PowerTransformerEnd", "end_number"): return True require( end.power_transformer is self, lambda: f"PowerTransformerEnd {end} references another PowerTransformer {end.power_transformer}, expected {str(self)}." ) return False
def _validate_steps(self): require( self.high_step > self.low_step, lambda: f"High step [{self.high_step}] must be greater than low step [{self.low_step}]" ) require( self.low_step <= self.neutral_step <= self.high_step, lambda: f"Neutral step [{self.neutral_step}] must be between high step [{self._high_step}] and low step [{self._low_step}]" ) require( self._low_step <= self.normal_step <= self._high_step, lambda: f"Normal step [{self.normal_step}] must be between high step [{self._high_step}] and low step [{self._low_step}]" ) require( self._low_step <= self.step <= self._high_step, lambda: f"Step [{self.step}] must be between high step [{self._high_step}] and low step [{self._low_step}]" )
def _validate_reference_by_sn(self, field: Any, other: IdentifiedObject, getter: Callable[[Any], IdentifiedObject], type_descr: str, field_name: str = "sequence_number") -> bool: """ Validate whether a given reference exists to `other` using the provided getter function called with `field`. `other` The object to compare against. `getter` A function that takes `field` and returns an `IdentifiedObject` if it exists, and throws an `IndexError` if it couldn't be found. `type_descr` The type description to use for the lazily generated error message. Should be of the form "A[n] type(other)" Returns True if `other` was retrieved with a call to `getter(field)` and was equivalent, False otherwise. Raises `ValueError` if an object is retrieved from `getter` and it is not `other`. """ try: get_result = getter(field) require( get_result is other, lambda: f"{type_descr} with {field_name} {field} already exists in {str(self)}" ) return True except IndexError: return False
def _check_steps(self, low, high): require( low <= self.step <= high, lambda: f"New value would invalidate current step of {self.step}") require( low <= self.normal_step <= high, lambda: f"New value would invalidate current normal_step of {self.normal_step}" ) require( low <= self.neutral_step <= high, lambda: f"New value would invalidate current neutral_step of {self.neutral_step}" )
def neutral_step(self, val): require( self._low_step <= val <= self._high_step, lambda: f"Neutral step {val} must be between high step {self._high_step} and low step {self._low_step}" ) self._neutral_step = val
def low_step(self, val): require( val < self._high_step, lambda: f"Low step {val} must be less than high step {self._high_step}") self._check_steps(val, self.high_step) self._low_step = val
def high_step(self, val): require( val > self._low_step, lambda: f"High step {val} must be greater than low step {self._low_step}") self._check_steps(self.low_step, val) self._high_step = val