From 6dc078871df5fcf53ddbf2ca09dec45b498cebb0 Mon Sep 17 00:00:00 2001 From: Jean-Marc Collin Date: Sat, 21 Oct 2023 10:31:56 +0000 Subject: [PATCH] FIX merge from #108 have lost some changes --- .../versatile_thermostat/climate.py | 61 ++++++++------ tests/test_multiple_switch.py | 82 +++++++++++++------ 2 files changed, 93 insertions(+), 50 deletions(-) diff --git a/custom_components/versatile_thermostat/climate.py b/custom_components/versatile_thermostat/climate.py index 7e2eb39..5c22fae 100644 --- a/custom_components/versatile_thermostat/climate.py +++ b/custom_components/versatile_thermostat/climate.py @@ -1,3 +1,6 @@ +# pylint: disable=line-too-long +# pylint: disable=too-many-lines +# pylint: disable=invalid-name """ Implements the VersatileThermostat climate component """ import math import logging @@ -1312,7 +1315,9 @@ class VersatileThermostat(ClimateEntity, RestoreEntity): self.recalculate() self.send_event(EventType.PRESET_EVENT, {"preset": self._attr_preset_mode}) - def reset_last_change_time(self, old_preset_mode=None): + def reset_last_change_time( + self, old_preset_mode=None + ): # pylint: disable=unused-argument """Reset to now the last change time""" self._last_change_time = datetime.now(tz=self._current_tz) _LOGGER.debug("%s - last_change_time is now %s", self, self._last_change_time) @@ -1546,7 +1551,11 @@ class VersatileThermostat(ClimateEntity, RestoreEntity): # Check delay condition async def try_motion_condition(_): try: - delay = self._motion_delay_sec if new_state.state == STATE_ON else self._motion_off_delay_sec + delay = ( + self._motion_delay_sec + if new_state.state == STATE_ON + else self._motion_off_delay_sec + ) long_enough = condition.state( self.hass, self._motion_sensor_entity_id, @@ -1583,13 +1592,17 @@ class VersatileThermostat(ClimateEntity, RestoreEntity): await self._async_control_heating(force=True) self._motion_call_cancel = None - im_on = (self._motion_state == STATE_ON) - delay_running = (self._motion_call_cancel is not None) - event_on = (new_state.state == STATE_ON) + im_on = self._motion_state == STATE_ON + delay_running = self._motion_call_cancel is not None + event_on = new_state.state == STATE_ON def arm(): - """ Arm the timer""" - delay = self._motion_delay_sec if new_state.state == STATE_ON else self._motion_off_delay_sec + """Arm the timer""" + delay = ( + self._motion_delay_sec + if new_state.state == STATE_ON + else self._motion_off_delay_sec + ) self._motion_call_cancel = async_call_later( self.hass, timedelta(seconds=delay), try_motion_condition ) @@ -1602,7 +1615,10 @@ class VersatileThermostat(ClimateEntity, RestoreEntity): # if I'm off if not im_on: if event_on and not delay_running: - _LOGGER.debug("%s - Arm delay cause i'm off and event is on and no delay is running", self) + _LOGGER.debug( + "%s - Arm delay cause i'm off and event is on and no delay is running", + self, + ) arm() return try_motion_condition # Ignore the event @@ -1614,7 +1630,10 @@ class VersatileThermostat(ClimateEntity, RestoreEntity): arm() return try_motion_condition if event_on and delay_running: - _LOGGER.debug("%s - Desarm off delay cause i'm on and event is on and a delay is running", self) + _LOGGER.debug( + "%s - Desarm off delay cause i'm on and event is on and a delay is running", + self, + ) desarm() return None # Ignore the event @@ -1696,9 +1715,7 @@ class VersatileThermostat(ClimateEntity, RestoreEntity): # Issue 99 - some AC turn hvac_mode=cool and hvac_action=idle when sending a HVACMode_OFF command # Issue 114 - Remove this because hvac_mode is now managed by local _hvac_mode and use idle action as is # if self._hvac_mode == HVACMode.OFF and new_hvac_action == HVACAction.IDLE: - # _LOGGER.debug( - # "The underlying switch to idle instead of OFF. We will consider it as OFF" - # ) + # _LOGGER.debug("The underlying switch to idle instead of OFF. We will consider it as OFF") # new_hvac_mode = HVACMode.OFF _LOGGER.info( @@ -1710,17 +1727,15 @@ class VersatileThermostat(ClimateEntity, RestoreEntity): old_hvac_action, ) - if new_hvac_mode in [ - HVACMode.OFF, - HVACMode.HEAT, - HVACMode.COOL, - HVACMode.HEAT_COOL, - HVACMode.DRY, - HVACMode.AUTO, - HVACMode.FAN_ONLY, - None, - ]: - self._hvac_mode = new_hvac_mode + _LOGGER.debug( + "%s - last_change_time=%s old_state_date_changed=%s old_state_date_updated=%s new_state_date_changed=%s new_state_date_updated=%s", + self, + self._last_change_time, + old_state_date_changed, + old_state_date_updated, + new_state_date_changed, + new_state_date_updated, + ) # Interpretation of hvac action HVAC_ACTION_ON = [ # pylint: disable=invalid-name diff --git a/tests/test_multiple_switch.py b/tests/test_multiple_switch.py index 28a2351..09408d2 100644 --- a/tests/test_multiple_switch.py +++ b/tests/test_multiple_switch.py @@ -1,11 +1,11 @@ """ Test the Multiple switch management """ import asyncio from unittest.mock import patch, call, ANY -from .commons import * # pylint: disable=wildcard-import, unused-wildcard-import from datetime import datetime, timedelta - import logging +from .commons import * # pylint: disable=wildcard-import, unused-wildcard-import + logging.getLogger().setLevel(logging.DEBUG) @@ -15,7 +15,7 @@ async def test_one_switch_cycle( hass: HomeAssistant, skip_hass_states_is_state, skip_send_event, -): +): # pylint: disable=unused-argument """Test that when multiple switch are configured the activation is distributed""" tz = get_tz(hass) # pylint: disable=invalid-name @@ -75,7 +75,7 @@ async def test_one_switch_cycle( with patch( "homeassistant.core.StateMachine.is_state", return_value=False ) as mock_is_state: - assert entity._is_device_active is False + assert entity._is_device_active is False # pylint: disable=protected-access # Should be call for the Switch assert mock_is_state.call_count == 1 @@ -132,7 +132,8 @@ async def test_one_switch_cycle( assert mock_send_event.call_count == 0 assert mock_heater_off.call_count == 0 - # The first heater should be turned on but is already on but because above we mock call_later the heater is not on. But this time it will be really on + # The first heater should be turned on but is already on but because above we mock + # call_later the heater is not on. But this time it will be really on assert mock_heater_on.call_count == 1 # Set another temperature at middle level @@ -153,12 +154,15 @@ async def test_one_switch_cycle( assert mock_send_event.call_count == 0 assert mock_heater_off.call_count == 0 - # The heater is already on cycle. So we wait that the cycle ends and no heater action is done + # The heater is already on cycle. So we wait that the cycle ends and no heater action + # is done assert mock_heater_on.call_count == 0 # assert entity.underlying_entity(0)._should_relaunch_control_heating is True # Simulate the relaunch - await entity.underlying_entity(0)._turn_on_later(None) + await entity.underlying_entity(0)._turn_on_later( # pylint: disable=protected-access + None + ) # wait restart await asyncio.sleep(0.1) @@ -177,7 +181,9 @@ async def test_one_switch_cycle( "custom_components.versatile_thermostat.underlyings.UnderlyingSwitch.is_device_active", return_value=True, ) as mock_device_active: - await entity.underlying_entity(0)._turn_off_later(None) + await entity.underlying_entity(0)._turn_off_later( # pylint: disable=protected-access + None + ) # No special event assert mock_send_event.call_count == 0 @@ -198,7 +204,9 @@ async def test_one_switch_cycle( "custom_components.versatile_thermostat.underlyings.UnderlyingSwitch.is_device_active", return_value=True, ) as mock_device_active: - await entity.underlying_entity(0)._turn_on_later(None) + await entity.underlying_entity(0)._turn_on_later( # pylint: disable=protected-access + None + ) # No special event assert mock_send_event.call_count == 0 @@ -214,7 +222,7 @@ async def test_multiple_switchs( hass: HomeAssistant, skip_hass_states_is_state, skip_send_event, -): +): # pylint: disable=unused-argument """Test that when multiple switch are configured the activation is distributed""" tz = get_tz(hass) # pylint: disable=invalid-name @@ -277,7 +285,7 @@ async def test_multiple_switchs( await send_temperature_change_event(entity, 15, event_timestamp) # Checks that all climates are off - assert entity._is_device_active is False + assert entity._is_device_active is False # pylint: disable=protected-access # Should be call for all Switch assert mock_underlying_set_hvac_mode.call_count == 4 @@ -342,17 +350,20 @@ async def test_multiple_switchs( assert mock_send_event.call_count == 0 assert mock_heater_off.call_count == 0 - # The first heater should be turned on but is already on but because call_later is mocked, it is only turned on here + # The first heater should be turned on but is already on but because call_later + # is mocked, it is only turned on here assert mock_heater_on.call_count == 1 + @pytest.mark.parametrize("expected_lingering_tasks", [True]) @pytest.mark.parametrize("expected_lingering_timers", [True]) async def test_multiple_climates( hass: HomeAssistant, skip_hass_states_is_state, skip_send_event, -): - """Test that when multiple climates are configured the activation and deactivation is propagated to all climates""" +): # pylint: disable=unused-argument + """Test that when multiple climates are configured the activation and deactivation + is propagated to all climates""" tz = get_tz(hass) # pylint: disable=invalid-name now: datetime = datetime.now(tz=tz) @@ -416,7 +427,7 @@ async def test_multiple_climates( call.set_hvac_mode(HVACMode.HEAT), ] ) - assert entity._is_device_active is False + assert entity._is_device_active is False # pylint: disable=protected-access # Stop heating, in boost mode. We block the control_heating to avoid running a cycle with patch( @@ -441,7 +452,8 @@ async def test_multiple_climates( call.set_hvac_mode(HVACMode.OFF), ] ) - assert entity._is_device_active is False + assert entity._is_device_active is False # pylint: disable=protected-access + @pytest.mark.parametrize("expected_lingering_tasks", [True]) @pytest.mark.parametrize("expected_lingering_timers", [True]) @@ -449,8 +461,9 @@ async def test_multiple_climates_underlying_changes( hass: HomeAssistant, skip_hass_states_is_state, skip_send_event, -): - """Test that when multiple switch are configured the activation of one underlying climate activate the others""" +): # pylint: disable=unused-argument + """Test that when multiple switch are configured the activation of one underlying + climate activate the others""" tz = get_tz(hass) # pylint: disable=invalid-name now: datetime = datetime.now(tz=tz) @@ -514,7 +527,7 @@ async def test_multiple_climates_underlying_changes( call.set_hvac_mode(HVACMode.HEAT), ] ) - assert entity._is_device_active is False + assert entity._is_device_active is False # pylint: disable=protected-access # Stop heating on one underlying climate with patch( @@ -524,7 +537,14 @@ async def test_multiple_climates_underlying_changes( ) as mock_underlying_set_hvac_mode: # Wait 11 sec so that the event will not be discarded event_timestamp = now + timedelta(seconds=11) - await send_climate_change_event(entity, HVACMode.OFF, HVACMode.HEAT, HVACAction.OFF, HVACAction.HEATING, event_timestamp) + await send_climate_change_event( + entity, + HVACMode.OFF, + HVACMode.HEAT, + HVACAction.OFF, + HVACAction.HEATING, + event_timestamp, + ) # Should be call for all Switch assert mock_underlying_set_hvac_mode.call_count == 4 @@ -534,7 +554,7 @@ async def test_multiple_climates_underlying_changes( ] ) assert entity.hvac_mode == HVACMode.OFF - assert entity._is_device_active is False + assert entity._is_device_active is False # pylint: disable=protected-access # Start heating on one underlying climate with patch( @@ -542,12 +562,21 @@ async def test_multiple_climates_underlying_changes( ), patch( "custom_components.versatile_thermostat.underlyings.UnderlyingClimate.set_hvac_mode" ) as mock_underlying_set_hvac_mode, patch( - # notice that there is no need of return_value=HVACAction.IDLE because this is not a function but a property - "custom_components.versatile_thermostat.underlyings.UnderlyingClimate.hvac_action", HVACAction.IDLE - ) as mock_underlying_get_hvac_action: + # notice that there is no need of return_value=HVACAction.IDLE because this is not + # a function but a property + "custom_components.versatile_thermostat.underlyings.UnderlyingClimate.hvac_action", + HVACAction.IDLE, + ): # Wait 11 sec so that the event will not be discarded event_timestamp = now + timedelta(seconds=11) - await send_climate_change_event(entity, HVACMode.HEAT, HVACMode.OFF, HVACAction.IDLE, HVACAction.OFF, event_timestamp) + await send_climate_change_event( + entity, + HVACMode.HEAT, + HVACMode.OFF, + HVACAction.IDLE, + HVACAction.OFF, + event_timestamp, + ) # Should be call for all Switch assert mock_underlying_set_hvac_mode.call_count == 4 @@ -558,5 +587,4 @@ async def test_multiple_climates_underlying_changes( ) assert entity.hvac_mode == HVACMode.HEAT assert entity.hvac_action == HVACAction.IDLE - assert entity._is_device_active is False - + assert entity._is_device_active is False # pylint: disable=protected-access