Skip to content

Commit de05503

Browse files
committed
Move SetPowerResult class to _component_status.py
So that it can be reused by other component status tracker specializations. Also make it `frozen` and `kw_only`, and update some docs and field names in the class. Signed-off-by: Sahas Subramanian <[email protected]>
1 parent fe57721 commit de05503

File tree

4 files changed

+36
-31
lines changed

4 files changed

+36
-31
lines changed

src/frequenz/sdk/actor/power_distributing/_battery_status_tracker.py

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
import asyncio
77
import logging
88
import math
9-
from collections.abc import Iterable
109
from dataclasses import dataclass
1110
from datetime import datetime, timedelta, timezone
1211

@@ -28,22 +27,11 @@
2827
ComponentData,
2928
InverterData,
3029
)
31-
from ._component_status import ComponentStatus, ComponentStatusEnum
30+
from ._component_status import ComponentStatus, ComponentStatusEnum, SetPowerResult
3231

3332
_logger = logging.getLogger(__name__)
3433

3534

36-
@dataclass
37-
class SetPowerResult:
38-
"""Information what batteries succeed or failed the last request."""
39-
40-
succeed: Iterable[int]
41-
"""Set of the batteries that succeed."""
42-
43-
failed: Iterable[int]
44-
"""Set of the batteries that failed."""
45-
46-
4735
@dataclass
4836
class _ComponentStreamStatus:
4937
component_id: int
@@ -255,7 +243,7 @@ def _handle_status_inverter(self, inv_data: InverterData) -> None:
255243
self._inverter.data_recv_timer.reset()
256244

257245
def _handle_status_set_power_result(self, result: SetPowerResult) -> None:
258-
if self.battery_id in result.succeed:
246+
if self.battery_id in result.succeeded:
259247
self._blocking_status.unblock()
260248

261249
elif (

src/frequenz/sdk/actor/power_distributing/_component_pool_status_tracker.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,13 @@
1212
from frequenz.channels.util import Merge
1313

1414
from ..._internal._asyncio import cancel_and_await
15-
from ._battery_status_tracker import BatteryStatusTracker, SetPowerResult
16-
from ._component_status import ComponentPoolStatus, ComponentStatus, ComponentStatusEnum
15+
from ._battery_status_tracker import BatteryStatusTracker
16+
from ._component_status import (
17+
ComponentPoolStatus,
18+
ComponentStatus,
19+
ComponentStatusEnum,
20+
SetPowerResult,
21+
)
1722

1823
_logger = logging.getLogger(__name__)
1924

@@ -143,7 +148,7 @@ async def update_status(
143148
failed_components: Components that failed request
144149
"""
145150
await self._set_power_result_sender.send(
146-
SetPowerResult(succeed_components, failed_components)
151+
SetPowerResult(succeeded=succeed_components, failed=failed_components)
147152
)
148153

149154
def get_working_components(self, components: abc.Set[int]) -> abc.Set[int]:

src/frequenz/sdk/actor/power_distributing/_component_status.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66

77
import enum
8+
import typing
89
from collections import abc
910
from dataclasses import dataclass
1011

@@ -60,3 +61,14 @@ class ComponentStatus:
6061

6162
value: ComponentStatusEnum
6263
"""Component status."""
64+
65+
66+
@dataclass(frozen=True, kw_only=True)
67+
class SetPowerResult:
68+
"""Lists of components for which the last set power command succeeded or failed."""
69+
70+
succeeded: typing.Iterable[int]
71+
"""Component IDs for which the last set power command succeeded."""
72+
73+
failed: typing.Iterable[int]
74+
"""Component IDs for which the last set power command failed."""

tests/actor/test_battery_status.py

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,11 @@
3030

3131
from frequenz.sdk.actor.power_distributing._battery_status_tracker import (
3232
BatteryStatusTracker,
33-
SetPowerResult,
3433
)
3534
from frequenz.sdk.actor.power_distributing._component_status import (
3635
ComponentStatus,
3736
ComponentStatusEnum,
37+
SetPowerResult,
3838
)
3939
from frequenz.sdk.microgrid.component import BatteryData, InverterData
4040
from tests.timeseries.mock_microgrid import MockMicrogrid
@@ -356,7 +356,7 @@ async def test_sync_blocking_feature(self, mocker: MockerFixture) -> None:
356356

357357
# message is not correct, component should not block.
358358
tracker._handle_status_set_power_result(
359-
SetPowerResult(succeed={1}, failed={BATTERY_ID})
359+
SetPowerResult(succeeded={1}, failed={BATTERY_ID})
360360
)
361361

362362
assert tracker._get_new_status_if_changed() is None
@@ -370,7 +370,7 @@ async def test_sync_blocking_feature(self, mocker: MockerFixture) -> None:
370370
for timeout in expected_blocking_timeout:
371371
# message is not correct, component should not block.
372372
tracker._handle_status_set_power_result(
373-
SetPowerResult(succeed={1}, failed={BATTERY_ID})
373+
SetPowerResult(succeeded={1}, failed={BATTERY_ID})
374374
)
375375

376376
assert (
@@ -381,7 +381,7 @@ async def test_sync_blocking_feature(self, mocker: MockerFixture) -> None:
381381
# Battery should be still blocked, nothing should happen
382382
time.shift(timeout - 1)
383383
tracker._handle_status_set_power_result(
384-
SetPowerResult(succeed={1}, failed={BATTERY_ID})
384+
SetPowerResult(succeeded={1}, failed={BATTERY_ID})
385385
)
386386

387387
assert tracker._get_new_status_if_changed() is None
@@ -399,7 +399,7 @@ async def test_sync_blocking_feature(self, mocker: MockerFixture) -> None:
399399

400400
# should block for 30 sec
401401
tracker._handle_status_set_power_result(
402-
SetPowerResult(succeed={1}, failed={BATTERY_ID})
402+
SetPowerResult(succeeded={1}, failed={BATTERY_ID})
403403
)
404404

405405
assert tracker._get_new_status_if_changed() is ComponentStatusEnum.UNCERTAIN
@@ -422,14 +422,14 @@ async def test_sync_blocking_feature(self, mocker: MockerFixture) -> None:
422422

423423
# should block for 30 sec
424424
tracker._handle_status_set_power_result(
425-
SetPowerResult(succeed={1}, failed={BATTERY_ID})
425+
SetPowerResult(succeeded={1}, failed={BATTERY_ID})
426426
)
427427
assert tracker._get_new_status_if_changed() is ComponentStatusEnum.UNCERTAIN
428428
time.shift(28)
429429

430430
# If battery succeed, then it should unblock.
431431
tracker._handle_status_set_power_result(
432-
SetPowerResult(succeed={BATTERY_ID}, failed={19})
432+
SetPowerResult(succeeded={BATTERY_ID}, failed={19})
433433
)
434434
assert tracker._get_new_status_if_changed() is ComponentStatusEnum.WORKING
435435

@@ -470,15 +470,15 @@ async def test_sync_blocking_interrupted_with_with_max_data(
470470
assert tracker._get_new_status_if_changed() is ComponentStatusEnum.WORKING
471471

472472
tracker._handle_status_set_power_result(
473-
SetPowerResult(succeed={1}, failed={BATTERY_ID})
473+
SetPowerResult(succeeded={1}, failed={BATTERY_ID})
474474
)
475475
assert tracker._get_new_status_if_changed() is ComponentStatusEnum.UNCERTAIN
476476

477477
expected_blocking_timeout = [1, 2, 4]
478478
for timeout in expected_blocking_timeout:
479479
# message is not correct, component should not block.
480480
tracker._handle_status_set_power_result(
481-
SetPowerResult(succeed={1}, failed={BATTERY_ID})
481+
SetPowerResult(succeeded={1}, failed={BATTERY_ID})
482482
)
483483
assert tracker._get_new_status_if_changed() is None
484484
time.shift(timeout)
@@ -520,7 +520,7 @@ async def test_sync_blocking_interrupted_with_invalid_message(
520520
assert tracker._get_new_status_if_changed() is ComponentStatusEnum.WORKING
521521

522522
tracker._handle_status_set_power_result(
523-
SetPowerResult(succeed={1}, failed={BATTERY_ID})
523+
SetPowerResult(succeeded={1}, failed={BATTERY_ID})
524524
)
525525
assert tracker._get_new_status_if_changed() is ComponentStatusEnum.UNCERTAIN
526526

@@ -533,12 +533,12 @@ async def test_sync_blocking_interrupted_with_invalid_message(
533533
assert tracker._get_new_status_if_changed() is ComponentStatusEnum.NOT_WORKING
534534

535535
tracker._handle_status_set_power_result(
536-
SetPowerResult(succeed={1}, failed={BATTERY_ID})
536+
SetPowerResult(succeeded={1}, failed={BATTERY_ID})
537537
)
538538
assert tracker._get_new_status_if_changed() is None
539539

540540
tracker._handle_status_set_power_result(
541-
SetPowerResult(succeed={BATTERY_ID}, failed={})
541+
SetPowerResult(succeeded={BATTERY_ID}, failed={})
542542
)
543543
assert tracker._get_new_status_if_changed() is None
544544

@@ -648,7 +648,7 @@ async def test_async_battery_status(self, mocker: MockerFixture) -> None:
648648
assert status.value is ComponentStatusEnum.WORKING
649649

650650
await set_power_result_sender.send(
651-
SetPowerResult(succeed={}, failed={BATTERY_ID})
651+
SetPowerResult(succeeded={}, failed={BATTERY_ID})
652652
)
653653
status = await asyncio.wait_for(status_receiver.receive(), timeout=0.1)
654654
assert status.value is ComponentStatusEnum.UNCERTAIN
@@ -669,7 +669,7 @@ async def test_async_battery_status(self, mocker: MockerFixture) -> None:
669669
assert status.value is ComponentStatusEnum.NOT_WORKING
670670

671671
await set_power_result_sender.send(
672-
SetPowerResult(succeed={}, failed={BATTERY_ID})
672+
SetPowerResult(succeeded={}, failed={BATTERY_ID})
673673
)
674674
await asyncio.sleep(0.3)
675675
assert len(status_receiver) == 0

0 commit comments

Comments
 (0)