Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions RELEASE_NOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@
* `frequenz.client.common.grid.EnergyMarketCodeType`
* `frequenz.client.common.metrics.Metric`
* `frequenz.client.common.metrics.MetricConnectionCategory`
* `frequenz.client.common.microgrid.electrical_components.ElectricalComponentDiagnosticCode`
* `frequenz.client.common.microgrid.electrical_components.ElectricalComponentStateCode`
* `frequenz.client.common.streaming.Event`

When loading these types from protobuf using dataclass-level converters (e.g., `delivery_area_from_proto`, `metric_sample_from_proto`), the low-level fields (`code_type`, `category`, `metric`) now store the raw integer `0` for unspecified values instead of the deprecated member. Unspecified values should be rare errors, so it is better to expose them only via the low-level interface.

Expand Down
8 changes: 4 additions & 4 deletions src/frequenz/client/common/metrics/_metric.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@

"""Supported metrics for microgrid components."""

from frequenz.core import enum as core_enum
from frequenz.core.enum import Enum, deprecated_member, unique


@core_enum.unique
class Metric(core_enum.Enum):
@unique
class Metric(Enum):
"""List of supported metrics.

Metric units are as follows:
Expand Down Expand Up @@ -39,7 +39,7 @@ class Metric(core_enum.Enum):
period, and therefore can be inconsistent.
"""

UNSPECIFIED = core_enum.deprecated_member(
UNSPECIFIED = deprecated_member(
0,
"Metric.UNSPECIFIED is deprecated; use the `int` value `0` "
"instead if you really need to check for this low-level value.",
Expand Down
13 changes: 6 additions & 7 deletions src/frequenz/client/common/metrics/_sample.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,21 @@

"""Definition to work with metric sample values."""

import enum
import warnings
from collections.abc import Sequence
from dataclasses import dataclass
from datetime import datetime
from typing import assert_never

from frequenz.core import enum as core_enum
from frequenz.core.enum import Enum, deprecated_member, unique

from .._exception import UnrecognizedValueError, UnspecifiedValueError
from ._bounds import Bounds
from ._metric import Metric


@enum.unique
class AggregationMethod(enum.Enum):
@unique
class AggregationMethod(Enum):
"""The type of the aggregated value."""

AVG = "avg"
Expand Down Expand Up @@ -70,11 +69,11 @@ def __str__(self) -> str:
return f"avg:{self.avg}{extra_str}"


@core_enum.unique
class MetricConnectionCategory(core_enum.Enum):
@unique
class MetricConnectionCategory(Enum):
"""The categories of connections from which metrics can be obtained."""

UNSPECIFIED = core_enum.deprecated_member(
UNSPECIFIED = deprecated_member(
0,
"MetricConnectionCategory.UNSPECIFIED is deprecated; use the `int` value `0` "
"instead if you really need to check for this low-level value.",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from typing import Any, Self, TypeAlias

import typing_extensions
from frequenz.core import enum as core_enum
from frequenz.core.enum import Enum, deprecated_member, unique

from ._electrical_component import ElectricalComponent

Expand Down Expand Up @@ -36,19 +36,17 @@ def _battery_type_member_message(name: str) -> str:


@typing_extensions.deprecated(_BATTERY_TYPE_DEPRECATION_MESSAGE)
@core_enum.unique
class BatteryType(core_enum.Enum):
@unique
class BatteryType(Enum):
"""The known types of batteries."""

UNSPECIFIED = core_enum.deprecated_member(
0, _battery_type_member_message("UNSPECIFIED")
)
UNSPECIFIED = deprecated_member(0, _battery_type_member_message("UNSPECIFIED"))
"""The battery type is unspecified."""

LI_ION = core_enum.deprecated_member(1, _battery_type_member_message("LI_ION"))
LI_ION = deprecated_member(1, _battery_type_member_message("LI_ION"))
"""Lithium-ion (Li-ion) battery."""

NA_ION = core_enum.deprecated_member(2, _battery_type_member_message("NA_ION"))
NA_ION = deprecated_member(2, _battery_type_member_message("NA_ION"))
"""Sodium-ion (Na-ion) battery."""


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"""Electrical component categories."""

import typing_extensions
from frequenz.core import enum as core_enum
from frequenz.core.enum import Enum, deprecated_member, unique

_DEPRECATION_MESSAGE = (
"ElectricalComponentCategory is deprecated; use the ElectricalComponent class "
Expand All @@ -30,77 +30,75 @@ def _member_message(name: str) -> str:


@typing_extensions.deprecated(_DEPRECATION_MESSAGE)
@core_enum.unique
class ElectricalComponentCategory(core_enum.Enum):
@unique
class ElectricalComponentCategory(Enum):
"""Possible types of microgrid electrical component."""

UNSPECIFIED = core_enum.deprecated_member(0, _member_message("UNSPECIFIED"))
UNSPECIFIED = deprecated_member(0, _member_message("UNSPECIFIED"))
"""The component category is unspecified. This should not be used."""

GRID_CONNECTION_POINT = core_enum.deprecated_member(
GRID_CONNECTION_POINT = deprecated_member(
1, _member_message("GRID_CONNECTION_POINT")
)
"""The point where the local microgrid is connected to the grid."""

METER = core_enum.deprecated_member(2, _member_message("METER"))
METER = deprecated_member(2, _member_message("METER"))
"""A meter, for measuring electrical metrics, e.g., current, voltage, etc."""

INVERTER = core_enum.deprecated_member(3, _member_message("INVERTER"))
INVERTER = deprecated_member(3, _member_message("INVERTER"))
"""An inverter that converts DC to AC power and vice versa."""

CONVERTER = core_enum.deprecated_member(4, _member_message("CONVERTER"))
CONVERTER = deprecated_member(4, _member_message("CONVERTER"))
"""An electricity converter, e.g., a DC-DC converter."""

BATTERY = core_enum.deprecated_member(5, _member_message("BATTERY"))
BATTERY = deprecated_member(5, _member_message("BATTERY"))
"""A battery energy storage system."""

EV_CHARGER = core_enum.deprecated_member(6, _member_message("EV_CHARGER"))
EV_CHARGER = deprecated_member(6, _member_message("EV_CHARGER"))
"""A station for charging electrical vehicles."""

BREAKER = core_enum.deprecated_member(7, _member_message("BREAKER"))
BREAKER = deprecated_member(7, _member_message("BREAKER"))
"""A circuit breaker, providing protection and switching by disconnecting circuits."""

PRECHARGER = core_enum.deprecated_member(8, _member_message("PRECHARGER"))
PRECHARGER = deprecated_member(8, _member_message("PRECHARGER"))
"""A precharger, used for preparing electrical circuits for switching on."""

CHP = core_enum.deprecated_member(9, _member_message("CHP"))
CHP = deprecated_member(9, _member_message("CHP"))
"""A combined heat and power (CHP) plant.

It generates electricity and useful heat from a single energy source.
"""

ELECTROLYZER = core_enum.deprecated_member(10, _member_message("ELECTROLYZER"))
ELECTROLYZER = deprecated_member(10, _member_message("ELECTROLYZER"))
"""A device for splitting water into hydrogen and oxygen using electricity."""

POWER_TRANSFORMER = core_enum.deprecated_member(
11, _member_message("POWER_TRANSFORMER")
)
POWER_TRANSFORMER = deprecated_member(11, _member_message("POWER_TRANSFORMER"))
"""A transformer, used for changing the voltage of electrical circuits."""

HVAC = core_enum.deprecated_member(12, _member_message("HVAC"))
HVAC = deprecated_member(12, _member_message("HVAC"))
"""A heating, ventilation, and air conditioning (HVAC) system."""

PLC = core_enum.deprecated_member(13, _member_message("PLC"))
PLC = deprecated_member(13, _member_message("PLC"))
"""A programmable logic controller (PLC)."""

CRYPTO_MINER = core_enum.deprecated_member(14, _member_message("CRYPTO_MINER"))
CRYPTO_MINER = deprecated_member(14, _member_message("CRYPTO_MINER"))
"""A device for mining cryptocurrencies."""

STATIC_TRANSFER_SWITCH = core_enum.deprecated_member(
STATIC_TRANSFER_SWITCH = deprecated_member(
15, _member_message("STATIC_TRANSFER_SWITCH")
)
"""A static transfer switch, used for switching between power sources."""

UNINTERRUPTIBLE_POWER_SUPPLY = core_enum.deprecated_member(
UNINTERRUPTIBLE_POWER_SUPPLY = deprecated_member(
16, _member_message("UNINTERRUPTIBLE_POWER_SUPPLY")
)
"""An uninterruptible power supply (UPS), used to provide backup power."""

CAPACITOR_BANK = core_enum.deprecated_member(17, _member_message("CAPACITOR_BANK"))
CAPACITOR_BANK = deprecated_member(17, _member_message("CAPACITOR_BANK"))
"""A capacitor bank, used for power factor correction and reactive power compensation."""

WIND_TURBINE = core_enum.deprecated_member(18, _member_message("WIND_TURBINE"))
WIND_TURBINE = deprecated_member(18, _member_message("WIND_TURBINE"))
"""A wind turbine, used to generate electricity from wind energy."""

STEAM_BOILER = core_enum.deprecated_member(19, _member_message("STEAM_BOILER"))
STEAM_BOILER = deprecated_member(19, _member_message("STEAM_BOILER"))
"""A steam boiler, used to generate steam for heating or industrial processes."""
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,18 @@

"""Electrical component diagnostic codes."""

import enum
from frequenz.core.enum import Enum, deprecated_member, unique


@enum.unique
class ElectricalComponentDiagnosticCode(enum.Enum):
@unique
class ElectricalComponentDiagnosticCode(Enum):
"""All diagnostics that can occur across electrical component categories."""

UNSPECIFIED = 0
UNSPECIFIED = deprecated_member(
0,
"ElectricalComponentDiagnosticCode.UNSPECIFIED is deprecated; use the `int` value `0` "
"instead if you really need to check for this low-level value.",
)
"""Default value. No specific error is specified."""

UNKNOWN = 1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from typing import Any, Self, TypeAlias

import typing_extensions
from frequenz.core import enum as core_enum
from frequenz.core.enum import Enum, deprecated_member, unique

from ._electrical_component import ElectricalComponent

Expand Down Expand Up @@ -36,22 +36,20 @@ def _ev_charger_type_member_message(name: str) -> str:


@typing_extensions.deprecated(_EV_CHARGER_TYPE_DEPRECATION_MESSAGE)
@core_enum.unique
class EvChargerType(core_enum.Enum):
@unique
class EvChargerType(Enum):
"""The known types of electric vehicle (EV) chargers."""

UNSPECIFIED = core_enum.deprecated_member(
0, _ev_charger_type_member_message("UNSPECIFIED")
)
UNSPECIFIED = deprecated_member(0, _ev_charger_type_member_message("UNSPECIFIED"))
"""The type of the EV charger is unspecified."""

AC = core_enum.deprecated_member(1, _ev_charger_type_member_message("AC"))
AC = deprecated_member(1, _ev_charger_type_member_message("AC"))
"""The EV charging station supports AC charging only."""

DC = core_enum.deprecated_member(2, _ev_charger_type_member_message("DC"))
DC = deprecated_member(2, _ev_charger_type_member_message("DC"))
"""The EV charging station supports DC charging only."""

HYBRID = core_enum.deprecated_member(3, _ev_charger_type_member_message("HYBRID"))
HYBRID = deprecated_member(3, _ev_charger_type_member_message("HYBRID"))
"""The EV charging station supports both AC and DC."""


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from typing import Any, Self, TypeAlias

import typing_extensions
from frequenz.core import enum as core_enum
from frequenz.core.enum import Enum, deprecated_member, unique

from ._electrical_component import ElectricalComponent

Expand Down Expand Up @@ -36,22 +36,20 @@ def _inverter_type_member_message(name: str) -> str:


@typing_extensions.deprecated(_INVERTER_TYPE_DEPRECATION_MESSAGE)
@core_enum.unique
class InverterType(core_enum.Enum):
@unique
class InverterType(Enum):
"""The known types of inverters."""

UNSPECIFIED = core_enum.deprecated_member(
0, _inverter_type_member_message("UNSPECIFIED")
)
UNSPECIFIED = deprecated_member(0, _inverter_type_member_message("UNSPECIFIED"))
"""The type of the inverter is unspecified."""

BATTERY = core_enum.deprecated_member(1, _inverter_type_member_message("BATTERY"))
BATTERY = deprecated_member(1, _inverter_type_member_message("BATTERY"))
"""The inverter is a battery inverter."""

PV = core_enum.deprecated_member(2, _inverter_type_member_message("PV"))
PV = deprecated_member(2, _inverter_type_member_message("PV"))
"""The inverter is a PV inverter."""

HYBRID = core_enum.deprecated_member(3, _inverter_type_member_message("HYBRID"))
HYBRID = deprecated_member(3, _inverter_type_member_message("HYBRID"))
"""The inverter is a hybrid inverter."""


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,18 @@

"""Electrical component state codes."""

import enum
from frequenz.core.enum import Enum, deprecated_member, unique


@enum.unique
class ElectricalComponentStateCode(enum.Enum):
@unique
class ElectricalComponentStateCode(Enum):
"""All possible states of a microgrid electrical component."""

UNSPECIFIED = 0
UNSPECIFIED = deprecated_member(
0,
"ElectricalComponentStateCode.UNSPECIFIED is deprecated; use the `int` value `0` "
"instead if you really need to check for this low-level value.",
)
"""Default value when the component state is not explicitly set."""

UNKNOWN = 1
Expand Down
12 changes: 8 additions & 4 deletions src/frequenz/client/common/streaming/_event.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,18 @@

"""Streaming event type enum."""

import enum
from frequenz.core.enum import Enum, deprecated_member, unique


@enum.unique
class Event(enum.Enum):
@unique
class Event(Enum):
"""A type of streaming event."""

UNSPECIFIED = 0
UNSPECIFIED = deprecated_member(
0,
"Event.UNSPECIFIED is deprecated; use the `int` value `0` "
"instead if you really need to check for this low-level value.",
)
"""Unspecified event type."""

CREATED = 1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,4 @@ class TestElectricalComponentDiagnosticCodeParity(EnumParityTest):
name_prefix = "ELECTRICAL_COMPONENT_DIAGNOSTIC_CODE_"
from_proto = staticmethod(electrical_component_diagnostic_code_from_proto)
to_proto = staticmethod(electrical_component_diagnostic_code_to_proto)
deprecated_members = frozenset({"UNSPECIFIED"})
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,4 @@ class TestElectricalComponentStateCodeParity(EnumParityTest):
name_prefix = "ELECTRICAL_COMPONENT_STATE_CODE_"
from_proto = staticmethod(electrical_component_state_code_from_proto)
to_proto = staticmethod(electrical_component_state_code_to_proto)
deprecated_members = frozenset({"UNSPECIFIED"})
1 change: 1 addition & 0 deletions tests/streaming/proto/v1alpha8/test_event.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,4 @@ class TestEventParity(EnumParityTest):
name_prefix = "EVENT_"
from_proto = staticmethod(event_from_proto)
to_proto = staticmethod(event_to_proto)
deprecated_members = frozenset({"UNSPECIFIED"})
5 changes: 4 additions & 1 deletion tests/streaming/test_event.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,16 @@

"""Tests for the `Event` enum domain model."""

import pytest

from frequenz.client.common.streaming import Event


def test_event_members() -> None:
"""Test that Event has the expected members with correct values."""
assert [m.name for m in Event] == ["UNSPECIFIED", "CREATED", "UPDATED", "DELETED"]
assert Event.UNSPECIFIED.value == 0
with pytest.warns(DeprecationWarning):
assert Event.UNSPECIFIED.value == 0
assert Event.CREATED.value == 1
assert Event.UPDATED.value == 2
assert Event.DELETED.value == 3
Loading