Skip to content

Commit 0f4fe4c

Browse files
authored
Updated float("NaN") to math.nan (#484)
Fixes #460
2 parents 0adc6df + 56db8b4 commit 0f4fe4c

File tree

6 files changed

+53
-47
lines changed

6 files changed

+53
-47
lines changed

src/frequenz/sdk/timeseries/_formula_engine/_formula_steps.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
from __future__ import annotations
77

8+
import math
89
from abc import ABC, abstractmethod
910
from typing import Generic, List, Optional
1011

@@ -326,6 +327,6 @@ def apply(self, eval_stack: List[float]) -> None:
326327
if self._nones_are_zeros:
327328
eval_stack.append(0.0)
328329
else:
329-
eval_stack.append(float("NaN"))
330+
eval_stack.append(math.nan)
330331
else:
331332
eval_stack.append(next_value.base_value)

tests/actor/test_battery_status.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
"""Tests for BatteryStatusTracker."""
44

55
import asyncio
6+
import math
67
from dataclasses import dataclass
78
from datetime import datetime, timedelta, timezone
89
from typing import Generic, Iterable, List, Optional, Set, Tuple, TypeVar
@@ -358,7 +359,7 @@ async def test_sync_update_status_with_messages(
358359
assert tracker._update_status(select) is Status.WORKING # type: ignore[arg-type]
359360

360361
select = FakeSelect(
361-
battery=battery_data(component_id=BATTERY_ID, capacity=float("NaN"))
362+
battery=battery_data(component_id=BATTERY_ID, capacity=math.nan)
362363
)
363364
assert tracker._update_status(select) is Status.NOT_WORKING # type: ignore[arg-type]
364365

tests/actor/test_power_distributing.py

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
from __future__ import annotations
77

88
import asyncio
9+
import math
910
import re
1011
from typing import TypeVar
1112
from unittest.mock import AsyncMock, MagicMock
@@ -190,7 +191,7 @@ async def test_battery_soc_nan(self, mocker: MockerFixture) -> None:
190191
await mock_microgrid.send(
191192
battery_msg(
192193
106,
193-
soc=Metric(float("NaN"), Bound(20, 80)),
194+
soc=Metric(math.nan, Bound(20, 80)),
194195
capacity=Metric(98000),
195196
power=Bound(-1000, 1000),
196197
)
@@ -254,7 +255,7 @@ async def test_battery_capacity_nan(self, mocker: MockerFixture) -> None:
254255
battery_msg(
255256
106,
256257
soc=Metric(40, Bound(20, 80)),
257-
capacity=Metric(float("NaN")),
258+
capacity=Metric(math.nan),
258259
power=Bound(-1000, 1000),
259260
)
260261
)
@@ -310,15 +311,15 @@ async def test_battery_power_bounds_nan(self, mocker: MockerFixture) -> None:
310311
await mock_microgrid.send(
311312
inverter_msg(
312313
205,
313-
power=Bound(float("NaN"), float("NaN")),
314+
power=Bound(math.nan, math.nan),
314315
)
315316
)
316317

317318
# Battery 106 should not work because both battery and inverter sends NaN
318319
await mock_microgrid.send(
319320
inverter_msg(
320321
105,
321-
power=Bound(-1000, float("NaN")),
322+
power=Bound(-1000, math.nan),
322323
)
323324
)
324325

@@ -327,7 +328,7 @@ async def test_battery_power_bounds_nan(self, mocker: MockerFixture) -> None:
327328
106,
328329
soc=Metric(40, Bound(20, 80)),
329330
capacity=Metric(float(98000)),
330-
power=Bound(float("NaN"), float("NaN")),
331+
power=Bound(math.nan, math.nan),
331332
)
332333
)
333334

@@ -760,14 +761,14 @@ async def test_force_request_battery_nan_value_non_cached(
760761
batteries_data = (
761762
battery_msg(
762763
106,
763-
soc=Metric(float("NaN"), Bound(20, 80)),
764-
capacity=Metric(float("NaN")),
764+
soc=Metric(math.nan, Bound(20, 80)),
765+
capacity=Metric(math.nan),
765766
power=Bound(-1000, 1000),
766767
),
767768
battery_msg(
768769
206,
769770
soc=Metric(40, Bound(20, 80)),
770-
capacity=Metric(float("NaN")),
771+
capacity=Metric(math.nan),
771772
power=Bound(-1000, 1000),
772773
),
773774
)
@@ -846,21 +847,21 @@ async def test_result() -> None:
846847
batteries_data = (
847848
battery_msg(
848849
106,
849-
soc=Metric(float("NaN"), Bound(20, 80)),
850+
soc=Metric(math.nan, Bound(20, 80)),
850851
capacity=Metric(98000),
851852
power=Bound(-1000, 1000),
852853
),
853854
battery_msg(
854855
206,
855856
soc=Metric(40, Bound(20, 80)),
856-
capacity=Metric(float("NaN")),
857+
capacity=Metric(math.nan),
857858
power=Bound(-1000, 1000),
858859
),
859860
battery_msg(
860861
306,
861862
soc=Metric(40, Bound(20, 80)),
862863
capacity=Metric(float(98000)),
863-
power=Bound(float("NaN"), float("NaN")),
864+
power=Bound(math.nan, math.nan),
864865
),
865866
)
866867

tests/power/test_distribution_algorithm.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
# pylint: disable=too-many-lines
55
"""Tests for distribution algorithm."""
6+
import math
67
from dataclasses import dataclass
78
from datetime import datetime, timezone
89
from typing import Dict, List, Optional
@@ -62,10 +63,10 @@ def battery_msg( # pylint: disable=too-many-arguments
6263
"""
6364
return BatteryDataWrapper(
6465
component_id=component_id,
65-
capacity=capacity.now if capacity.now is not None else float("NaN"),
66-
soc=soc.now if soc.now is not None else float("NaN"),
67-
soc_lower_bound=soc.bound.lower if soc.bound is not None else float("NaN"),
68-
soc_upper_bound=soc.bound.upper if soc.bound is not None else float("NaN"),
66+
capacity=capacity.now if capacity.now is not None else math.nan,
67+
soc=soc.now if soc.now is not None else math.nan,
68+
soc_lower_bound=soc.bound.lower if soc.bound is not None else math.nan,
69+
soc_upper_bound=soc.bound.upper if soc.bound is not None else math.nan,
6970
power_lower_bound=power.lower,
7071
power_upper_bound=power.upper,
7172
timestamp=timestamp,

tests/timeseries/_battery_pool/test_battery_pool.py

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import asyncio
88
import dataclasses
99
import logging
10+
import math
1011
from dataclasses import dataclass, is_dataclass, replace
1112
from datetime import datetime, timedelta, timezone
1213
from typing import Any, AsyncIterator, Generic, Iterator, TypeVar
@@ -565,7 +566,7 @@ async def run_capacity_test(setup_args: SetupArgs) -> None:
565566
),
566567
Scenario(
567568
batteries_in_pool[1],
568-
{"soc_upper_bound": float("NaN")},
569+
{"soc_upper_bound": math.nan},
569570
Sample(
570571
now,
571572
Energy.from_watt_hours(
@@ -595,7 +596,7 @@ async def run_capacity_test(setup_args: SetupArgs) -> None:
595596
),
596597
Scenario(
597598
batteries_in_pool[1],
598-
{"capacity": float("NaN")},
599+
{"capacity": math.nan},
599600
Sample(
600601
now,
601602
Energy.from_watt_hours(
@@ -709,13 +710,13 @@ async def run_soc_test(setup_args: SetupArgs) -> None:
709710
# If NaN, then not include that battery in the metric.
710711
Scenario(
711712
batteries_in_pool[0],
712-
{"soc_upper_bound": float("NaN")},
713+
{"soc_upper_bound": math.nan},
713714
Sample(now, Percentage.from_percent(10.0)),
714715
),
715716
# All batteries are sending NaN, can't calculate SoC so we should send None
716717
Scenario(
717718
batteries_in_pool[1],
718-
{"soc": float("NaN")},
719+
{"soc": math.nan},
719720
None,
720721
),
721722
Scenario(
@@ -866,44 +867,44 @@ async def run_power_bounds_test( # pylint: disable=too-many-locals
866867
# Setting upper bound to NaN should not influence lower bound
867868
Scenario(
868869
batteries_in_pool[0],
869-
{"power_lower_bound": -50, "power_upper_bound": float("NaN")},
870+
{"power_lower_bound": -50, "power_upper_bound": math.nan},
870871
PowerMetrics(now, Bound(-60, 0), Bound(0, 9200)),
871872
),
872873
Scenario(
873874
bat_inv_map[batteries_in_pool[0]],
874875
{
875-
"active_power_lower_bound": float("NaN"),
876-
"active_power_upper_bound": float("NaN"),
876+
"active_power_lower_bound": math.nan,
877+
"active_power_upper_bound": math.nan,
877878
},
878879
PowerMetrics(now, Bound(-60, 0), Bound(0, 200)),
879880
),
880881
Scenario(
881882
batteries_in_pool[0],
882-
{"power_lower_bound": float("NaN")},
883+
{"power_lower_bound": math.nan},
883884
PowerMetrics(now, Bound(-10, 0), Bound(0, 200)),
884885
),
885886
Scenario(
886887
batteries_in_pool[1],
887888
{
888889
"power_lower_bound": -100,
889-
"power_upper_bound": float("NaN"),
890+
"power_upper_bound": math.nan,
890891
},
891892
PowerMetrics(now, Bound(-100, 0), Bound(0, 6000)),
892893
),
893894
Scenario(
894895
bat_inv_map[batteries_in_pool[1]],
895896
{
896-
"active_power_lower_bound": float("NaN"),
897-
"active_power_upper_bound": float("NaN"),
897+
"active_power_lower_bound": math.nan,
898+
"active_power_upper_bound": math.nan,
898899
},
899900
PowerMetrics(now, Bound(-100, 0), Bound(0, 0)),
900901
),
901902
# All components are sending NaN, can't calculate bounds
902903
Scenario(
903904
batteries_in_pool[1],
904905
{
905-
"power_lower_bound": float("NaN"),
906-
"power_upper_bound": float("NaN"),
906+
"power_lower_bound": math.nan,
907+
"power_upper_bound": math.nan,
907908
},
908909
None,
909910
),

tests/utils/component_data_wrapper.py

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
"""
1313
from __future__ import annotations
1414

15+
import math
1516
from dataclasses import dataclass, field, replace
1617
from datetime import datetime
1718
from typing import Tuple
@@ -33,13 +34,13 @@
3334
class BatteryDataWrapper(BatteryData):
3435
"""Wrapper for the BatteryData with default arguments."""
3536

36-
soc: float = float("NaN")
37-
soc_lower_bound: float = float("NaN")
38-
soc_upper_bound: float = float("NaN")
39-
capacity: float = float("NaN")
40-
power_lower_bound: float = float("NaN")
41-
power_upper_bound: float = float("NaN")
42-
temperature_max: float = float("NaN")
37+
soc: float = math.nan
38+
soc_lower_bound: float = math.nan
39+
soc_upper_bound: float = math.nan
40+
capacity: float = math.nan
41+
power_lower_bound: float = math.nan
42+
power_upper_bound: float = math.nan
43+
temperature_max: float = math.nan
4344
_relay_state: battery_pb.RelayState.ValueType = (
4445
battery_pb.RelayState.RELAY_STATE_UNSPECIFIED
4546
)
@@ -67,9 +68,9 @@ def copy_with_new_timestamp(self, new_timestamp: datetime) -> BatteryDataWrapper
6768
class InverterDataWrapper(InverterData):
6869
"""Wrapper for the InverterData with default arguments."""
6970

70-
active_power: float = float("NaN")
71-
active_power_lower_bound: float = float("NaN")
72-
active_power_upper_bound: float = float("NaN")
71+
active_power: float = math.nan
72+
active_power_lower_bound: float = math.nan
73+
active_power_upper_bound: float = math.nan
7374
_component_state: inverter_pb.ComponentState.ValueType = (
7475
inverter_pb.ComponentState.COMPONENT_STATE_UNSPECIFIED
7576
)
@@ -94,12 +95,12 @@ def copy_with_new_timestamp(self, new_timestamp: datetime) -> InverterDataWrappe
9495
class EvChargerDataWrapper(EVChargerData):
9596
"""Wrapper for the EvChargerData with default arguments."""
9697

97-
active_power: float = float("NaN")
98+
active_power: float = math.nan
9899
current_per_phase: Tuple[float, float, float] = field(
99-
default_factory=lambda: (float("NaN"), float("NaN"), float("NaN"))
100+
default_factory=lambda: (math.nan, math.nan, math.nan)
100101
)
101102
voltage_per_phase: Tuple[float, float, float] = field(
102-
default_factory=lambda: (float("NaN"), float("NaN"), float("NaN"))
103+
default_factory=lambda: (math.nan, math.nan, math.nan)
103104
)
104105
cable_state: EVChargerCableState = EVChargerCableState.UNSPECIFIED
105106
component_state: EVChargerComponentState = EVChargerComponentState.UNSPECIFIED
@@ -123,14 +124,14 @@ def copy_with_new_timestamp(self, new_timestamp: datetime) -> EvChargerDataWrapp
123124
class MeterDataWrapper(MeterData):
124125
"""Wrapper for the MeterData with default arguments."""
125126

126-
active_power: float = float("NaN")
127+
active_power: float = math.nan
127128
current_per_phase: Tuple[float, float, float] = field(
128-
default_factory=lambda: (float("NaN"), float("NaN"), float("NaN"))
129+
default_factory=lambda: (math.nan, math.nan, math.nan)
129130
)
130131
voltage_per_phase: Tuple[float, float, float] = field(
131-
default_factory=lambda: (float("NaN"), float("NaN"), float("NaN"))
132+
default_factory=lambda: (math.nan, math.nan, math.nan)
132133
)
133-
frequency: float = float("NaN")
134+
frequency: float = math.nan
134135

135136
def copy_with_new_timestamp(self, new_timestamp: datetime) -> MeterDataWrapper:
136137
"""Copy the component data but insert new timestamp.

0 commit comments

Comments
 (0)