Skip to content

Commit

Permalink
Beautify code with Ruff
Browse files Browse the repository at this point in the history
  • Loading branch information
Limych committed Oct 10, 2024
1 parent c81514d commit 16592b4
Show file tree
Hide file tree
Showing 6 changed files with 54 additions and 69 deletions.
3 changes: 2 additions & 1 deletion custom_components/car_wash/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"""The Car Wash binary sensor.
"""
The Car Wash binary sensor.
For more details about this platform, please refer to the documentation at
https://github.com/Limych/ha-car_wash/
Expand Down
52 changes: 27 additions & 25 deletions custom_components/car_wash/binary_sensor.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
# Copyright (c) 2019-2021, Andrey "Limych" Khrolenok <[email protected]>
# Creative Commons BY-NC-SA 4.0 International Public License
# (see LICENSE.md or https://creativecommons.org/licenses/by-nc-sa/4.0/)
"""The Car Wash binary sensor.
"""
The Car Wash binary sensor.
For more details about this platform, please refer to the documentation at
https://github.com/Limych/ha-car_wash/
"""

from collections.abc import Callable
from datetime import datetime
import logging
from datetime import datetime

import voluptuous as vol

from homeassistant.components.binary_sensor import BinarySensorEntity
from homeassistant.components.weather import (
ATTR_FORECAST_CONDITION,
Expand All @@ -21,10 +20,12 @@
ATTR_FORECAST_TEMP_LOW,
ATTR_FORECAST_TIME,
ATTR_WEATHER_TEMPERATURE,
DOMAIN as WEATHER_DOMAIN,
SERVICE_GET_FORECASTS,
WeatherEntityFeature,
)
from homeassistant.components.weather import (
DOMAIN as WEATHER_DOMAIN,
)
from homeassistant.const import (
ATTR_SUPPORTED_FEATURES,
CONF_ENTITY_ID,
Expand All @@ -34,11 +35,12 @@
EVENT_HOMEASSISTANT_START,
UnitOfTemperature,
)
from homeassistant.core import Event, EventStateChangedData, HomeAssistant, callback
from homeassistant.core import Event, HomeAssistant, callback
from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers import config_validation as cv
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.event import async_track_state_change_event
from homeassistant.helpers.typing import ConfigType
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
from homeassistant.util import dt as dt_util
from homeassistant.util.unit_conversion import TemperatureConverter

Expand Down Expand Up @@ -67,11 +69,11 @@

# pylint: disable=unused-argument
async def async_setup_platform(
hass: HomeAssistant,
hass: HomeAssistant, # noqa: ARG001
config: ConfigType,
async_add_entities: Callable,
discovery_info=None,
):
async_add_entities: AddEntitiesCallback,
discovery_info: DiscoveryInfoType = None, # noqa: ARG001
) -> None:
"""Set up the Car Wash sensor."""
# Print startup message
_LOGGER.info(STARTUP_MESSAGE)
Expand All @@ -97,7 +99,7 @@ def __init__(
friendly_name: str,
weather_entity: str,
days: int,
):
) -> None:
"""Initialize the sensor."""
self._weather_entity = weather_entity
self._days = days
Expand All @@ -124,19 +126,19 @@ async def async_added_to_hass(self) -> None:

# pylint: disable=unused-argument
@callback
def sensor_state_listener(event: Event[EventStateChangedData]) -> None:
def sensor_state_listener(event: Event) -> None: # noqa: ARG001
"""Handle device state changes."""
self.async_schedule_update_ha_state(True)
self.async_schedule_update_ha_state(force_refresh=True)

# pylint: disable=unused-argument
@callback
def sensor_startup(event) -> None:
def sensor_startup(event: Event) -> None: # noqa: ARG001
"""Update template on startup."""
async_track_state_change_event(
self.hass, [self._weather_entity], sensor_state_listener
)

self.async_schedule_update_ha_state(True)
self.async_schedule_update_ha_state(force_refresh=True)

self.hass.bus.async_listen_once(EVENT_HOMEASSISTANT_START, sensor_startup)

Expand All @@ -150,13 +152,12 @@ def _temp2c(temperature: float | None, temperature_unit: str) -> float | None:
return temperature

# pylint: disable=too-many-branches,too-many-statements
async def async_update(self):
async def async_update(self) -> None: # noqa: PLR0912, PLR0915
"""Update the sensor state."""
wstate = self.hass.states.get(self._weather_entity)
if wstate is None:
raise HomeAssistantError(
f"Unable to find an entity called {self._weather_entity}"
)
msg = f"Unable to find an entity called {self._weather_entity}"
raise HomeAssistantError(msg)

tmpu = self.hass.config.units.temperature_unit
temp = wstate.attributes.get(ATTR_WEATHER_TEMPERATURE)
Expand All @@ -170,7 +171,8 @@ async def async_update(self):
elif (wfeatures & WeatherEntityFeature.FORECAST_HOURLY) != 0:
forecast_type = "hourly"
else:
raise HomeAssistantError("Weather entity doesn't support any forecast")
msg = "Weather entity doesn't support any forecast"
raise HomeAssistantError(msg)

try:
forecast = await self.hass.services.async_call(
Expand All @@ -185,9 +187,8 @@ async def async_update(self):
)
except HomeAssistantError as ex:
self._attr_is_on = None
raise HomeAssistantError(
"Can't get forecast data! Are you sure it's the weather provider?"
) from ex
msg = "Can't get forecast data! Are you sure it's the weather provider?"
raise HomeAssistantError(msg) from ex

_LOGGER.debug("Current temperature %s, condition '%s'", temp, cond)

Expand All @@ -201,7 +202,8 @@ async def async_update(self):
today = dt_util.start_of_local_day()
cur_date = today.strftime("%F")
stop_date = datetime.fromtimestamp(
today.timestamp() + 86400 * (self._days + 1)
today.timestamp() + 86400 * (self._days + 1),
tz=dt_util.DEFAULT_TIME_ZONE,
).strftime("%F")

_LOGGER.debug("Inspect weather forecast from now till %s", stop_date)
Expand Down
4 changes: 3 additions & 1 deletion custom_components/car_wash/const.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
# Copyright (c) 2019-2021, Andrey "Limych" Khrolenok <[email protected]>
# Creative Commons BY-NC-SA 4.0 International Public License
# (see LICENSE.md or https://creativecommons.org/licenses/by-nc-sa/4.0/)
"""The Car Wash binary sensor.
"""
The Car Wash binary sensor.
For more details about this platform, please refer to the documentation at
https://github.com/Limych/ha-car_wash/
"""

from typing import Final

from homeassistant.components.weather import (
Expand Down
4 changes: 3 additions & 1 deletion custom_components/car_wash/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
"documentation": "https://github.com/Limych/ha-car_wash",
"iot_class": "calculated",
"issue_tracker": "https://github.com/Limych/ha-car_wash/issues",
"requirements": [],
"requirements": [
"pip>=21.3.1"
],
"version": "1.5.8-alpha"
}
23 changes: 0 additions & 23 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,26 +42,3 @@ def _skip_notifications_fixture() -> None:
patch("homeassistant.components.persistent_notification.async_dismiss"),
):
yield


# This fixture, when used, will result in calls to async_get_data to return None. To
# have the call return a value, we would add the `return_value=<VALUE_TO_RETURN>`
# parameter to the patch call.
@pytest.fixture(name="bypass_get_data")
def _bypass_get_data_fixture() -> None:
"""Skip calls to get data from API."""
with patch.object(
IntegrationBlueprintApiClient, "async_get_data", side_effect=Mock()
):
yield


# In this fixture, we are forcing calls to async_get_data to raise an Exception. This
# is useful for exception handling.
@pytest.fixture(name="error_on_get_data")
def _error_get_data_fixture() -> None:
"""Simulate error when retrieving data from API."""
with patch.object(
IntegrationBlueprintApiClient, "async_get_data", side_effect=Exception
):
yield
37 changes: 19 additions & 18 deletions tests/test_binary_sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,6 @@
from unittest.mock import MagicMock, patch

import pytest
from pytest import raises
from pytest_homeassistant_custom_component.common import async_mock_service

from custom_components.car_wash.binary_sensor import (
CarWashBinarySensor,
async_setup_platform,
)
from custom_components.car_wash.const import CONF_WEATHER, DOMAIN, ICON
from homeassistant.components.weather import (
ATTR_CONDITION_RAINY,
ATTR_CONDITION_SUNNY,
Expand All @@ -22,10 +14,12 @@
ATTR_FORECAST_TEMP_LOW,
ATTR_FORECAST_TIME,
ATTR_WEATHER_TEMPERATURE,
DOMAIN as WEATHER_DOMAIN,
SERVICE_GET_FORECASTS,
WeatherEntityFeature,
)
from homeassistant.components.weather import (
DOMAIN as WEATHER_DOMAIN,
)
from homeassistant.const import (
ATTR_SUPPORTED_FEATURES,
CONF_PLATFORM,
Expand All @@ -35,6 +29,13 @@
from homeassistant.core import HomeAssistant, ServiceRegistry, SupportsResponse
from homeassistant.exceptions import HomeAssistantError
from homeassistant.util import dt as dt_util
from pytest_homeassistant_custom_component.common import async_mock_service

from custom_components.car_wash.binary_sensor import (
CarWashBinarySensor,
async_setup_platform,
)
from custom_components.car_wash.const import CONF_WEATHER, DOMAIN, ICON

MOCK_ENTITY: Final = DOMAIN + ".test"
MOCK_UNIQUE_ID: Final = "test_id"
Expand All @@ -49,7 +50,7 @@
}


@pytest.fixture()
@pytest.fixture
def default_sensor(hass: HomeAssistant):
"""Create an AverageSensor with default values."""
entity = CarWashBinarySensor(
Expand All @@ -60,7 +61,7 @@ def default_sensor(hass: HomeAssistant):


@pytest.mark.parametrize(
"uid, expected_uid",
("uid", "expected_uid"),
[
(None, None),
("__legacy__", DOMAIN + "-" + MOCK_WEATHER_ENTITY_NAME),
Expand Down Expand Up @@ -90,7 +91,7 @@ async def test_async_setup_platform(hass: HomeAssistant):

# pylint: disable=protected-access
@pytest.mark.parametrize(
"temp1, temp2",
("temp1", "temp2"),
[(0, -17.78), (10, -12.22), (20, -6.67), (30, -1.11), (40, 4.44), (50, 10)],
)
async def test__temp2c(temp1, temp2):
Expand All @@ -109,7 +110,7 @@ async def test_async_update_fail(hass: HomeAssistant):
MOCK_UNIQUE_ID, MOCK_NAME, WEATHER_DOMAIN + ".nonexistent", MOCK_DAYS
)
entity.hass = hass
with raises(HomeAssistantError):
with pytest.raises(HomeAssistantError):
await entity.async_update()


Expand All @@ -122,7 +123,7 @@ async def test_async_update_forecast_fail(hass: HomeAssistant, default_sensor):
supports_response=SupportsResponse.OPTIONAL,
)

with raises(HomeAssistantError, match="Unable to find an entity"):
with pytest.raises(HomeAssistantError, match="Unable to find an entity"):
await default_sensor.async_update()

hass.states.async_set(
Expand All @@ -133,7 +134,7 @@ async def test_async_update_forecast_fail(hass: HomeAssistant, default_sensor):
},
)

with raises(HomeAssistantError, match="doesn't support any forecast"):
with pytest.raises(HomeAssistantError, match="doesn't support any forecast"):
await default_sensor.async_update()

hass.states.async_set(
Expand All @@ -145,7 +146,7 @@ async def test_async_update_forecast_fail(hass: HomeAssistant, default_sensor):
},
)

with raises(TypeError):
with pytest.raises(TypeError):
await default_sensor.async_update()


Expand All @@ -155,12 +156,12 @@ async def test_async_update(hass: HomeAssistant, default_sensor):

hass.states.async_set(MOCK_WEATHER_ENTITY, None)

with raises(HomeAssistantError):
with pytest.raises(HomeAssistantError):
await default_sensor.async_update()

hass.states.async_set(MOCK_WEATHER_ENTITY, "State")

with raises(HomeAssistantError):
with pytest.raises(HomeAssistantError):
await default_sensor.async_update()

hass.states.async_set(
Expand Down

0 comments on commit 16592b4

Please sign in to comment.