diff --git a/homeassistant/components/habitica/todo.py b/homeassistant/components/habitica/todo.py index 71ba8e60e06..b8641deb9c2 100644 --- a/homeassistant/components/habitica/todo.py +++ b/homeassistant/components/habitica/todo.py @@ -4,6 +4,7 @@ from __future__ import annotations from enum import StrEnum import logging +import math from typing import TYPE_CHECKING from uuid import UUID @@ -281,7 +282,7 @@ class HabiticaTodosListEntity(BaseHabiticaListEntity): return sorted( tasks, key=lambda task: ( - float("inf") + math.inf if (uid := UUID(task.uid)) not in (tasks_order := self.coordinator.data.user.tasksOrder.todos) else tasks_order.index(uid) @@ -367,7 +368,7 @@ class HabiticaDailiesListEntity(BaseHabiticaListEntity): return sorted( tasks, key=lambda task: ( - float("inf") + math.inf if (uid := UUID(task.uid)) not in (tasks_order := self.coordinator.data.user.tasksOrder.dailys) else tasks_order.index(uid) diff --git a/homeassistant/components/knx/schema.py b/homeassistant/components/knx/schema.py index e6dc0c1bb3e..794d8751327 100644 --- a/homeassistant/components/knx/schema.py +++ b/homeassistant/components/knx/schema.py @@ -4,6 +4,7 @@ from __future__ import annotations from abc import ABC from collections import OrderedDict +import math from typing import ClassVar, Final import voluptuous as vol @@ -86,7 +87,7 @@ def number_limit_sub_validator(entity_config: OrderedDict) -> OrderedDict: raise vol.Invalid(f"'type: {value_type}' is not a valid numeric sensor type.") # Infinity is not supported by Home Assistant frontend so user defined # config is required if if xknx DPTNumeric subclass defines it as limit. - if min_config is None and dpt_class.value_min == float("-inf"): + if min_config is None and dpt_class.value_min == -math.inf: raise vol.Invalid(f"'min' key required for value type '{value_type}'") if min_config is not None and min_config < dpt_class.value_min: raise vol.Invalid( @@ -94,7 +95,7 @@ def number_limit_sub_validator(entity_config: OrderedDict) -> OrderedDict: f" of value type '{value_type}': {dpt_class.value_min}" ) - if max_config is None and dpt_class.value_max == float("inf"): + if max_config is None and dpt_class.value_max == math.inf: raise vol.Invalid(f"'max' key required for value type '{value_type}'") if max_config is not None and max_config > dpt_class.value_max: raise vol.Invalid( diff --git a/homeassistant/components/stream/recorder.py b/homeassistant/components/stream/recorder.py index a24440e6d19..1a7cc199a3c 100644 --- a/homeassistant/components/stream/recorder.py +++ b/homeassistant/components/stream/recorder.py @@ -5,6 +5,7 @@ from __future__ import annotations from collections import deque from io import DEFAULT_BUFFER_SIZE, BytesIO import logging +import math import os from typing import TYPE_CHECKING @@ -76,7 +77,7 @@ class RecorderOutput(StreamOutput): # units which seem to be defined inversely to how stream time_bases are defined running_duration = 0 - last_sequence = float("-inf") + last_sequence = -math.inf def write_segment(segment: Segment) -> None: """Write a segment to output.""" diff --git a/homeassistant/components/stream/worker.py b/homeassistant/components/stream/worker.py index c196e57baa4..521457f428c 100644 --- a/homeassistant/components/stream/worker.py +++ b/homeassistant/components/stream/worker.py @@ -9,6 +9,7 @@ from dataclasses import fields import datetime from io import SEEK_END, BytesIO import logging +import math from threading import Event from typing import Any, Self, cast @@ -46,7 +47,7 @@ from .fmp4utils import read_init from .hls import HlsStreamOutput _LOGGER = logging.getLogger(__name__) -NEGATIVE_INF = float("-inf") +NEGATIVE_INF = -math.inf def redact_av_error_string(err: av.FFmpegError) -> str: diff --git a/homeassistant/helpers/significant_change.py b/homeassistant/helpers/significant_change.py index 893ca7a3586..632b42c735b 100644 --- a/homeassistant/helpers/significant_change.py +++ b/homeassistant/helpers/significant_change.py @@ -30,6 +30,7 @@ The following cases will never be passed to your function: from __future__ import annotations from collections.abc import Callable, Mapping +import math from types import MappingProxyType from typing import Any, Protocol @@ -161,7 +162,7 @@ def check_percentage_change( try: return (abs(new_state - old_state) / old_state) * 100.0 except ZeroDivisionError: - return float("inf") + return math.inf return _check_numeric_change(old_state, new_state, change, percentage_change) diff --git a/pyproject.toml b/pyproject.toml index 15d82c13861..99c4f3a7a53 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -161,7 +161,6 @@ class-const-naming-style = "any" # possibly-used-before-assignment - too many errors / not necessarily issues # --- # Pylint CodeStyle plugin -# consider-math-not-float # consider-using-namedtuple-or-dataclass - too opinionated # consider-using-assignment-expr - decision to use := better left to devs disable = [ @@ -182,7 +181,6 @@ disable = [ "too-many-boolean-expressions", "too-many-positional-arguments", "wrong-import-order", - "consider-math-not-float", "consider-using-namedtuple-or-dataclass", "consider-using-assignment-expr", "possibly-used-before-assignment", diff --git a/tests/components/http/test_view.py b/tests/components/http/test_view.py index e3bb3ac303b..062d3c768a3 100644 --- a/tests/components/http/test_view.py +++ b/tests/components/http/test_view.py @@ -3,6 +3,7 @@ from decimal import Decimal from http import HTTPStatus import json +import math from unittest.mock import AsyncMock, Mock from aiohttp.web_exceptions import ( @@ -46,7 +47,7 @@ async def test_invalid_json(caplog: pytest.LogCaptureFixture) -> None: async def test_nan_serialized_to_null() -> None: """Test nan serialized to null JSON.""" - response = HomeAssistantView.json(float("NaN")) + response = HomeAssistantView.json(math.nan) assert json.loads(response.body.decode("utf-8")) is None diff --git a/tests/components/modbus/test_sensor.py b/tests/components/modbus/test_sensor.py index ef9c6b5b8cd..e9e56ff6974 100644 --- a/tests/components/modbus/test_sensor.py +++ b/tests/components/modbus/test_sensor.py @@ -1,5 +1,6 @@ """The tests for the Modbus sensor component.""" +import math import struct import pytest @@ -738,8 +739,8 @@ async def test_all_sensor(hass: HomeAssistant, mock_do_cycle, expected) -> None: [ 0x5102, 0x0304, - int.from_bytes(struct.pack(">f", float("nan"))[0:2]), - int.from_bytes(struct.pack(">f", float("nan"))[2:4]), + int.from_bytes(struct.pack(">f", math.nan)[0:2]), + int.from_bytes(struct.pack(">f", math.nan)[2:4]), ], False, ["34899771392.0", STATE_UNKNOWN], @@ -753,8 +754,8 @@ async def test_all_sensor(hass: HomeAssistant, mock_do_cycle, expected) -> None: [ 0x5102, 0x0304, - int.from_bytes(struct.pack(">f", float("nan"))[0:2]), - int.from_bytes(struct.pack(">f", float("nan"))[2:4]), + int.from_bytes(struct.pack(">f", math.nan)[0:2]), + int.from_bytes(struct.pack(">f", math.nan)[2:4]), ], False, ["34899771392.0", STATE_UNKNOWN], @@ -1160,8 +1161,8 @@ async def test_wrong_unpack(hass: HomeAssistant, mock_do_cycle) -> None: CONF_DATA_TYPE: DataType.FLOAT32, }, [ - int.from_bytes(struct.pack(">f", float("nan"))[0:2]), - int.from_bytes(struct.pack(">f", float("nan"))[2:4]), + int.from_bytes(struct.pack(">f", math.nan)[0:2]), + int.from_bytes(struct.pack(">f", math.nan)[2:4]), ], STATE_UNKNOWN, ), @@ -1224,8 +1225,8 @@ async def test_unpack_ok(hass: HomeAssistant, mock_do_cycle, expected) -> None: # floats: nan, 10.600000381469727, # 1.000879611487865e-28, 10.566553115844727 [ - int.from_bytes(struct.pack(">f", float("nan"))[0:2]), - int.from_bytes(struct.pack(">f", float("nan"))[2:4]), + int.from_bytes(struct.pack(">f", math.nan)[0:2]), + int.from_bytes(struct.pack(">f", math.nan)[2:4]), 0x4129, 0x999A, 0x10FD, diff --git a/tests/components/sensor/test_init.py b/tests/components/sensor/test_init.py index 05e24d1f9b2..4b0ac44c14f 100644 --- a/tests/components/sensor/test_init.py +++ b/tests/components/sensor/test_init.py @@ -5,6 +5,7 @@ from __future__ import annotations from collections.abc import Generator from datetime import UTC, date, datetime from decimal import Decimal +import math from typing import Any from unittest.mock import patch @@ -2313,9 +2314,11 @@ async def test_state_classes_with_invalid_unit_of_measurement( (datetime(2012, 11, 10, 7, 35, 1), "non-numeric"), (date(2012, 11, 10), "non-numeric"), ("inf", "non-finite"), - (float("inf"), "non-finite"), + (math.inf, "non-finite"), + (float("inf"), "non-finite"), # pylint: disable=consider-math-not-float ("nan", "non-finite"), - (float("nan"), "non-finite"), + (math.nan, "non-finite"), + (float("nan"), "non-finite"), # pylint: disable=consider-math-not-float ], ) async def test_non_numeric_validation_error( diff --git a/tests/components/websocket_api/test_commands.py b/tests/components/websocket_api/test_commands.py index 43a4fb0e539..4a62ae99817 100644 --- a/tests/components/websocket_api/test_commands.py +++ b/tests/components/websocket_api/test_commands.py @@ -4,6 +4,7 @@ import asyncio from copy import deepcopy import io import logging +import math from typing import Any from unittest.mock import ANY, AsyncMock, Mock, patch @@ -1061,7 +1062,7 @@ async def test_get_states_not_allows_nan( ) -> None: """Test get_states command converts NaN to None.""" hass.states.async_set("greeting.hello", "world") - hass.states.async_set("greeting.bad", "data", {"hello": float("NaN")}) + hass.states.async_set("greeting.bad", "data", {"hello": math.nan}) hass.states.async_set("greeting.bye", "universe") await websocket_client.send_json_auto_id({"type": "get_states"}) diff --git a/tests/helpers/test_json.py b/tests/helpers/test_json.py index 26ee4c675bb..6326f81d651 100644 --- a/tests/helpers/test_json.py +++ b/tests/helpers/test_json.py @@ -306,7 +306,7 @@ def test_find_unserializable_data() -> None: assert find_paths_unserializable_data({("A",): 1}) == {"$": ("A",)} assert math.isnan( find_paths_unserializable_data( - float("nan"), dump=partial(json.dumps, allow_nan=False) + math.nan, dump=partial(json.dumps, allow_nan=False) )["$"] )