From 84e4e94d8e5dba9562bf806bac674fcc1e52f2fd Mon Sep 17 00:00:00 2001 From: phispi Date: Fri, 1 Nov 2019 21:23:23 +0100 Subject: [PATCH 01/11] Prevent TypeError when KNX RGB(W) light value contains None (#28358) * Prevent TypeError when KNX RGB(W) light value contains None. * Pylint doesn't like 'w' as variable name, therefore using 'white' instead. * Simplified code as suggested by pvizeli. --- homeassistant/components/knx/light.py | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/homeassistant/components/knx/light.py b/homeassistant/components/knx/light.py index 81bf4ad3c83..c7292309461 100644 --- a/homeassistant/components/knx/light.py +++ b/homeassistant/components/knx/light.py @@ -180,13 +180,9 @@ class KNXLight(Light): @property def brightness(self): """Return the brightness of this light between 0..255.""" - if self.device.supports_brightness: - return self.device.current_brightness - if ( - self.device.supports_color or self.device.supports_rgbw - ) and self.device.current_color: - return max(self.device.current_color) - return None + if not self.device.supports_brightness: + return None + return self.device.current_brightness @property def hs_color(self): From 9e9537a3d07721781b0bcc84a4f29752337db911 Mon Sep 17 00:00:00 2001 From: Mister Wil <1091741+MisterWil@users.noreply.github.com> Date: Fri, 1 Nov 2019 17:28:50 -0700 Subject: [PATCH 02/11] Change Abode cache file path, add cache path to config flow (#28389) * Changed cache file path * Cache file naming scheme matches original * Restart tests * Adding cache path to config_flow.py * Moved DEFAULT_CACHEDB to consts file * Use correct cache path * Linting issues --- homeassistant/components/abode/__init__.py | 4 +--- homeassistant/components/abode/config_flow.py | 7 +++++-- homeassistant/components/abode/const.py | 2 ++ 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/homeassistant/components/abode/__init__.py b/homeassistant/components/abode/__init__.py index 6a72ac64145..76c14d7917f 100644 --- a/homeassistant/components/abode/__init__.py +++ b/homeassistant/components/abode/__init__.py @@ -23,14 +23,12 @@ from homeassistant.const import ( from homeassistant.helpers import config_validation as cv from homeassistant.helpers.entity import Entity -from .const import ATTRIBUTION, DOMAIN +from .const import ATTRIBUTION, DOMAIN, DEFAULT_CACHEDB _LOGGER = logging.getLogger(__name__) CONF_POLLING = "polling" -DEFAULT_CACHEDB = "./abodepy_cache.pickle" - SERVICE_SETTINGS = "change_setting" SERVICE_CAPTURE_IMAGE = "capture_image" SERVICE_TRIGGER = "trigger_quick_action" diff --git a/homeassistant/components/abode/config_flow.py b/homeassistant/components/abode/config_flow.py index d8d914f7998..bf48e4546b3 100644 --- a/homeassistant/components/abode/config_flow.py +++ b/homeassistant/components/abode/config_flow.py @@ -10,7 +10,7 @@ from homeassistant import config_entries from homeassistant.const import CONF_PASSWORD, CONF_USERNAME from homeassistant.core import callback -from .const import DOMAIN # pylint: disable=W0611 +from .const import DOMAIN, DEFAULT_CACHEDB # pylint: disable=W0611 CONF_POLLING = "polling" @@ -42,9 +42,12 @@ class AbodeFlowHandler(config_entries.ConfigFlow, domain=DOMAIN): username = user_input[CONF_USERNAME] password = user_input[CONF_PASSWORD] polling = user_input.get(CONF_POLLING, False) + cache = self.hass.config.path(DEFAULT_CACHEDB) try: - await self.hass.async_add_executor_job(Abode, username, password, True) + await self.hass.async_add_executor_job( + Abode, username, password, True, True, True, cache + ) except (AbodeException, ConnectTimeout, HTTPError) as ex: _LOGGER.error("Unable to connect to Abode: %s", str(ex)) diff --git a/homeassistant/components/abode/const.py b/homeassistant/components/abode/const.py index 35e74e154cf..092843ba212 100644 --- a/homeassistant/components/abode/const.py +++ b/homeassistant/components/abode/const.py @@ -1,3 +1,5 @@ """Constants for the Abode Security System component.""" DOMAIN = "abode" ATTRIBUTION = "Data provided by goabode.com" + +DEFAULT_CACHEDB = "abodepy_cache.pickle" From b88c0cf3148ffa66fa5a37ebd5e493fcfdc224fa Mon Sep 17 00:00:00 2001 From: Robin Pronk Date: Fri, 1 Nov 2019 15:38:14 +0100 Subject: [PATCH 03/11] SNMP switch fix integer support (#28425) --- homeassistant/components/snmp/switch.py | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/snmp/switch.py b/homeassistant/components/snmp/switch.py index aac43208a1f..8d5be1221c4 100644 --- a/homeassistant/components/snmp/switch.py +++ b/homeassistant/components/snmp/switch.py @@ -1,6 +1,8 @@ """Support for SNMP enabled switch.""" import logging +from pyasn1.type.univ import Integer + import pysnmp.hlapi.asyncio as hlapi from pysnmp.hlapi.asyncio import ( CommunityData, @@ -190,15 +192,20 @@ class SnmpSwitch(SwitchDevice): async def async_turn_on(self, **kwargs): """Turn on the switch.""" - await self._set(self._command_payload_on) + if self._command_payload_on.isdigit(): + await self._set(Integer(self._command_payload_on)) + else: + await self._set(self._command_payload_on) async def async_turn_off(self, **kwargs): """Turn off the switch.""" - await self._set(self._command_payload_off) + if self._command_payload_on.isdigit(): + await self._set(Integer(self._command_payload_off)) + else: + await self._set(self._command_payload_off) async def async_update(self): """Update the state.""" - errindication, errstatus, errindex, restable = await getCmd( *self._request_args, ObjectType(ObjectIdentity(self._baseoid)) ) @@ -215,8 +222,12 @@ class SnmpSwitch(SwitchDevice): for resrow in restable: if resrow[-1] == self._payload_on: self._state = True + elif resrow[-1] == Integer(self._payload_on): + self._state = True elif resrow[-1] == self._payload_off: self._state = False + elif resrow[-1] == Integer(self._payload_off): + self._state = False else: self._state = None From fc7d43269c588aca9ea0fa36aa8d192f7e5225c7 Mon Sep 17 00:00:00 2001 From: jjlawren Date: Fri, 1 Nov 2019 16:41:26 -0500 Subject: [PATCH 04/11] Use server-specific unique_ids for Plex media_players (#28447) --- homeassistant/components/plex/media_player.py | 27 ++++++++++++++++--- homeassistant/components/plex/server.py | 3 ++- 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/homeassistant/components/plex/media_player.py b/homeassistant/components/plex/media_player.py index 32bf7b65fff..4c32c1e6376 100644 --- a/homeassistant/components/plex/media_player.py +++ b/homeassistant/components/plex/media_player.py @@ -6,7 +6,7 @@ from xml.etree.ElementTree import ParseError import plexapi.exceptions import requests.exceptions -from homeassistant.components.media_player import MediaPlayerDevice +from homeassistant.components.media_player import DOMAIN as MP_DOMAIN, MediaPlayerDevice from homeassistant.components.media_player.const import ( MEDIA_TYPE_MOVIE, MEDIA_TYPE_MUSIC, @@ -30,6 +30,7 @@ from homeassistant.const import ( ) from homeassistant.core import callback from homeassistant.helpers.dispatcher import async_dispatcher_connect +from homeassistant.helpers.entity_registry import async_get_registry from homeassistant.util import dt as dt_util from .const import ( @@ -56,10 +57,11 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info= async def async_setup_entry(hass, config_entry, async_add_entities): """Set up Plex media_player from a config entry.""" server_id = config_entry.data[CONF_SERVER_IDENTIFIER] + registry = await async_get_registry(hass) def async_new_media_players(new_entities): _async_add_entities( - hass, config_entry, async_add_entities, server_id, new_entities + hass, registry, config_entry, async_add_entities, server_id, new_entities ) unsub = async_dispatcher_connect( @@ -70,7 +72,7 @@ async def async_setup_entry(hass, config_entry, async_add_entities): @callback def _async_add_entities( - hass, config_entry, async_add_entities, server_id, new_entities + hass, registry, config_entry, async_add_entities, server_id, new_entities ): """Set up Plex media_player entities.""" entities = [] @@ -79,6 +81,19 @@ def _async_add_entities( plex_mp = PlexMediaPlayer(plexserver, **entity_params) entities.append(plex_mp) + # Migration to per-server unique_ids + old_entity_id = registry.async_get_entity_id( + MP_DOMAIN, PLEX_DOMAIN, plex_mp.machine_identifier + ) + if old_entity_id is not None: + new_unique_id = f"{server_id}:{plex_mp.machine_identifier}" + _LOGGER.debug( + "Migrating unique_id from [%s] to [%s]", + plex_mp.machine_identifier, + new_unique_id, + ) + registry.async_update_entity(old_entity_id, new_unique_id=new_unique_id) + async_add_entities(entities, True) @@ -126,6 +141,7 @@ class PlexMediaPlayer(MediaPlayerDevice): async def async_added_to_hass(self): """Run when about to be added to hass.""" server_id = self.plex_server.machine_identifier + unsub = async_dispatcher_connect( self.hass, PLEX_UPDATE_MEDIA_PLAYER_SIGNAL.format(self.unique_id), @@ -315,6 +331,11 @@ class PlexMediaPlayer(MediaPlayerDevice): @property def unique_id(self): """Return the id of this plex client.""" + return f"{self.plex_server.machine_identifier}:{self._machine_identifier}" + + @property + def machine_identifier(self): + """Return the Plex-provided identifier of this plex client.""" return self._machine_identifier @property diff --git a/homeassistant/components/plex/server.py b/homeassistant/components/plex/server.py index e6f77a310f1..28380e714ac 100644 --- a/homeassistant/components/plex/server.py +++ b/homeassistant/components/plex/server.py @@ -94,9 +94,10 @@ class PlexServer: def refresh_entity(self, machine_identifier, device, session): """Forward refresh dispatch to media_player.""" + unique_id = f"{self.machine_identifier}:{machine_identifier}" dispatcher_send( self._hass, - PLEX_UPDATE_MEDIA_PLAYER_SIGNAL.format(machine_identifier), + PLEX_UPDATE_MEDIA_PLAYER_SIGNAL.format(unique_id), device, session, ) From 3f8dc5ed75c493acd56f587ce00fd3334277070a Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Fri, 1 Nov 2019 17:21:50 -0700 Subject: [PATCH 05/11] Also install after_deps (#28453) --- homeassistant/requirements.py | 8 ++++++-- tests/test_requirements.py | 13 +++++++++++-- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/homeassistant/requirements.py b/homeassistant/requirements.py index 74469ef2fcd..a0eec0f442b 100644 --- a/homeassistant/requirements.py +++ b/homeassistant/requirements.py @@ -48,8 +48,12 @@ async def async_get_integration_with_requirements( hass, integration.domain, integration.requirements ) - for dependency in integration.dependencies: - await async_get_integration_with_requirements(hass, dependency) + deps = integration.dependencies + (integration.after_dependencies or []) + + if deps: + await asyncio.gather( + *[async_get_integration_with_requirements(hass, dep) for dep in deps] + ) return integration diff --git a/tests/test_requirements.py b/tests/test_requirements.py index 548ea645360..782b4386552 100644 --- a/tests/test_requirements.py +++ b/tests/test_requirements.py @@ -115,12 +115,19 @@ async def test_get_integration_with_requirements(hass): mock_integration( hass, MockModule("test_component_dep", requirements=["test-comp-dep==1.0.0"]) ) + mock_integration( + hass, + MockModule( + "test_component_after_dep", requirements=["test-comp-after-dep==1.0.0"] + ), + ) mock_integration( hass, MockModule( "test_component", requirements=["test-comp==1.0.0"], dependencies=["test_component_dep"], + partial_manifest={"after_dependencies": ["test_component_after_dep"]}, ), ) @@ -136,13 +143,15 @@ async def test_get_integration_with_requirements(hass): assert integration assert integration.domain == "test_component" - assert len(mock_is_installed.mock_calls) == 2 + assert len(mock_is_installed.mock_calls) == 3 assert mock_is_installed.mock_calls[0][1][0] == "test-comp==1.0.0" assert mock_is_installed.mock_calls[1][1][0] == "test-comp-dep==1.0.0" + assert mock_is_installed.mock_calls[2][1][0] == "test-comp-after-dep==1.0.0" - assert len(mock_inst.mock_calls) == 2 + assert len(mock_inst.mock_calls) == 3 assert mock_inst.mock_calls[0][1][0] == "test-comp==1.0.0" assert mock_inst.mock_calls[1][1][0] == "test-comp-dep==1.0.0" + assert mock_inst.mock_calls[2][1][0] == "test-comp-after-dep==1.0.0" async def test_install_with_wheels_index(hass): From 969b36a44764afb84c1eb41bc675550b39222128 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Fri, 1 Nov 2019 17:32:57 -0700 Subject: [PATCH 06/11] Bumped version to 0.101.2 --- homeassistant/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homeassistant/const.py b/homeassistant/const.py index 4e25e8c7dc3..575a7d5740f 100644 --- a/homeassistant/const.py +++ b/homeassistant/const.py @@ -1,7 +1,7 @@ """Constants used by Home Assistant components.""" MAJOR_VERSION = 0 MINOR_VERSION = 101 -PATCH_VERSION = "1" +PATCH_VERSION = "2" __short_version__ = "{}.{}".format(MAJOR_VERSION, MINOR_VERSION) __version__ = "{}.{}".format(__short_version__, PATCH_VERSION) REQUIRED_PYTHON_VER = (3, 6, 1) From 1618c5c040989a7f99b44c8bb49b5722963b7438 Mon Sep 17 00:00:00 2001 From: Tim McCormick Date: Sun, 3 Nov 2019 04:25:24 +0000 Subject: [PATCH 07/11] Fix missing import (#28460) --- homeassistant/components/sonos/media_player.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/sonos/media_player.py b/homeassistant/components/sonos/media_player.py index 94d252e9fee..2baa02d0a5d 100644 --- a/homeassistant/components/sonos/media_player.py +++ b/homeassistant/components/sonos/media_player.py @@ -8,6 +8,7 @@ import urllib import async_timeout import pysonos +from pysonos import alarms from pysonos.exceptions import SoCoException, SoCoUPnPException import pysonos.snapshot @@ -1163,7 +1164,7 @@ class SonosEntity(MediaPlayerDevice): """Set the alarm clock on the player.""" alarm = None - for one_alarm in pysonos.alarms.get_alarms(self.soco): + for one_alarm in alarms.get_alarms(self.soco): # pylint: disable=protected-access if one_alarm._alarm_id == str(data[ATTR_ALARM_ID]): alarm = one_alarm From f5306f769cda3d3f1b814189db069931383cf499 Mon Sep 17 00:00:00 2001 From: Maciej Bieniek Date: Mon, 4 Nov 2019 00:58:35 +0100 Subject: [PATCH 08/11] Fix Airly if more than one config entry (#28498) --- homeassistant/components/airly/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/airly/__init__.py b/homeassistant/components/airly/__init__.py index 80f3518c652..ce165918ac2 100644 --- a/homeassistant/components/airly/__init__.py +++ b/homeassistant/components/airly/__init__.py @@ -31,6 +31,8 @@ DEFAULT_SCAN_INTERVAL = timedelta(minutes=10) async def async_setup(hass: HomeAssistant, config: Config) -> bool: """Set up configured Airly.""" + hass.data[DOMAIN] = {} + hass.data[DOMAIN][DATA_CLIENT] = {} return True @@ -49,8 +51,6 @@ async def async_setup_entry(hass, config_entry): if not airly.data: raise ConfigEntryNotReady() - hass.data[DOMAIN] = {} - hass.data[DOMAIN][DATA_CLIENT] = {} hass.data[DOMAIN][DATA_CLIENT][config_entry.entry_id] = airly hass.async_create_task( From 2814a24f9e12b9bb69ad0bb7e87a9c1fc605df4e Mon Sep 17 00:00:00 2001 From: Santobert Date: Tue, 5 Nov 2019 15:43:50 +0100 Subject: [PATCH 09/11] Add deprecated attributes to light.reproduce_state (#28557) * Add deprecated attributes to light.reproduce_state * Add blank line * fix minor bug * Typo --- .../components/light/reproduce_state.py | 42 +++++++++++- .../components/light/test_reproduce_state.py | 66 +++++++++++++++++-- 2 files changed, 99 insertions(+), 9 deletions(-) diff --git a/homeassistant/components/light/reproduce_state.py b/homeassistant/components/light/reproduce_state.py index ae618f7a8ef..c84b3627bed 100644 --- a/homeassistant/components/light/reproduce_state.py +++ b/homeassistant/components/light/reproduce_state.py @@ -17,10 +17,16 @@ from homeassistant.helpers.typing import HomeAssistantType from . import ( DOMAIN, ATTR_BRIGHTNESS, + ATTR_BRIGHTNESS_PCT, + ATTR_COLOR_NAME, ATTR_COLOR_TEMP, ATTR_EFFECT, + ATTR_FLASH, ATTR_HS_COLOR, + ATTR_KELVIN, + ATTR_PROFILE, ATTR_RGB_COLOR, + ATTR_TRANSITION, ATTR_WHITE_VALUE, ATTR_XY_COLOR, ) @@ -28,8 +34,36 @@ from . import ( _LOGGER = logging.getLogger(__name__) VALID_STATES = {STATE_ON, STATE_OFF} -ATTR_GROUP = [ATTR_BRIGHTNESS, ATTR_EFFECT, ATTR_WHITE_VALUE] -COLOR_GROUP = [ATTR_COLOR_TEMP, ATTR_HS_COLOR, ATTR_RGB_COLOR, ATTR_XY_COLOR] + +ATTR_GROUP = [ + ATTR_BRIGHTNESS, + ATTR_BRIGHTNESS_PCT, + ATTR_EFFECT, + ATTR_FLASH, + ATTR_WHITE_VALUE, + ATTR_TRANSITION, +] + +COLOR_GROUP = [ + ATTR_COLOR_NAME, + ATTR_COLOR_TEMP, + ATTR_HS_COLOR, + ATTR_KELVIN, + ATTR_PROFILE, + ATTR_RGB_COLOR, + ATTR_XY_COLOR, +] + +DEPRECATED_GROUP = [ + ATTR_BRIGHTNESS_PCT, + ATTR_COLOR_NAME, + ATTR_FLASH, + ATTR_KELVIN, + ATTR_PROFILE, + ATTR_TRANSITION, +] + +DEPRECATION_WARNING = "The use of other attributes than device state attributes is deprecated and will be removed in a future release. Read the logs for further details: https://www.home-assistant.io/integrations/scene/" async def _async_reproduce_state( @@ -48,6 +82,10 @@ async def _async_reproduce_state( ) return + # Warn if deprecated attributes are used + if any(attr in DEPRECATED_GROUP for attr in state.attributes): + _LOGGER.warning(DEPRECATION_WARNING) + # Return if we are already at the right state. if cur_state.state == state.state and all( check_attr_equal(cur_state.attributes, state.attributes, attr) diff --git a/tests/components/light/test_reproduce_state.py b/tests/components/light/test_reproduce_state.py index 92790890a4c..250a0fe26a8 100644 --- a/tests/components/light/test_reproduce_state.py +++ b/tests/components/light/test_reproduce_state.py @@ -1,13 +1,19 @@ """Test reproduce state for Light.""" +from homeassistant.components.light.reproduce_state import DEPRECATION_WARNING from homeassistant.core import State from tests.common import async_mock_service VALID_BRIGHTNESS = {"brightness": 180} VALID_WHITE_VALUE = {"white_value": 200} +VALID_FLASH = {"flash": "short"} VALID_EFFECT = {"effect": "random"} +VALID_TRANSITION = {"transition": 15} +VALID_COLOR_NAME = {"color_name": "red"} VALID_COLOR_TEMP = {"color_temp": 240} VALID_HS_COLOR = {"hs_color": (345, 75)} +VALID_KELVIN = {"kelvin": 4000} +VALID_PROFILE = {"profile": "relax"} VALID_RGB_COLOR = {"rgb_color": (255, 63, 111)} VALID_XY_COLOR = {"xy_color": (0.59, 0.274)} @@ -17,9 +23,14 @@ async def test_reproducing_states(hass, caplog): hass.states.async_set("light.entity_off", "off", {}) hass.states.async_set("light.entity_bright", "on", VALID_BRIGHTNESS) hass.states.async_set("light.entity_white", "on", VALID_WHITE_VALUE) + hass.states.async_set("light.entity_flash", "on", VALID_FLASH) hass.states.async_set("light.entity_effect", "on", VALID_EFFECT) + hass.states.async_set("light.entity_trans", "on", VALID_TRANSITION) + hass.states.async_set("light.entity_name", "on", VALID_COLOR_NAME) hass.states.async_set("light.entity_temp", "on", VALID_COLOR_TEMP) hass.states.async_set("light.entity_hs", "on", VALID_HS_COLOR) + hass.states.async_set("light.entity_kelvin", "on", VALID_KELVIN) + hass.states.async_set("light.entity_profile", "on", VALID_PROFILE) hass.states.async_set("light.entity_rgb", "on", VALID_RGB_COLOR) hass.states.async_set("light.entity_xy", "on", VALID_XY_COLOR) @@ -32,9 +43,14 @@ async def test_reproducing_states(hass, caplog): State("light.entity_off", "off"), State("light.entity_bright", "on", VALID_BRIGHTNESS), State("light.entity_white", "on", VALID_WHITE_VALUE), + State("light.entity_flash", "on", VALID_FLASH), State("light.entity_effect", "on", VALID_EFFECT), + State("light.entity_trans", "on", VALID_TRANSITION), + State("light.entity_name", "on", VALID_COLOR_NAME), State("light.entity_temp", "on", VALID_COLOR_TEMP), State("light.entity_hs", "on", VALID_HS_COLOR), + State("light.entity_kelvin", "on", VALID_KELVIN), + State("light.entity_profile", "on", VALID_PROFILE), State("light.entity_rgb", "on", VALID_RGB_COLOR), State("light.entity_xy", "on", VALID_XY_COLOR), ], @@ -59,16 +75,21 @@ async def test_reproducing_states(hass, caplog): State("light.entity_xy", "off"), State("light.entity_off", "on", VALID_BRIGHTNESS), State("light.entity_bright", "on", VALID_WHITE_VALUE), - State("light.entity_white", "on", VALID_EFFECT), - State("light.entity_effect", "on", VALID_COLOR_TEMP), + State("light.entity_white", "on", VALID_FLASH), + State("light.entity_flash", "on", VALID_EFFECT), + State("light.entity_effect", "on", VALID_TRANSITION), + State("light.entity_trans", "on", VALID_COLOR_NAME), + State("light.entity_name", "on", VALID_COLOR_TEMP), State("light.entity_temp", "on", VALID_HS_COLOR), - State("light.entity_hs", "on", VALID_RGB_COLOR), + State("light.entity_hs", "on", VALID_KELVIN), + State("light.entity_kelvin", "on", VALID_PROFILE), + State("light.entity_profile", "on", VALID_RGB_COLOR), State("light.entity_rgb", "on", VALID_XY_COLOR), ], blocking=True, ) - assert len(turn_on_calls) == 7 + assert len(turn_on_calls) == 12 expected_calls = [] @@ -80,22 +101,42 @@ async def test_reproducing_states(hass, caplog): expected_bright["entity_id"] = "light.entity_bright" expected_calls.append(expected_bright) - expected_white = VALID_EFFECT + expected_white = VALID_FLASH expected_white["entity_id"] = "light.entity_white" expected_calls.append(expected_white) - expected_effect = VALID_COLOR_TEMP + expected_flash = VALID_EFFECT + expected_flash["entity_id"] = "light.entity_flash" + expected_calls.append(expected_flash) + + expected_effect = VALID_TRANSITION expected_effect["entity_id"] = "light.entity_effect" expected_calls.append(expected_effect) + expected_trans = VALID_COLOR_NAME + expected_trans["entity_id"] = "light.entity_trans" + expected_calls.append(expected_trans) + + expected_name = VALID_COLOR_TEMP + expected_name["entity_id"] = "light.entity_name" + expected_calls.append(expected_name) + expected_temp = VALID_HS_COLOR expected_temp["entity_id"] = "light.entity_temp" expected_calls.append(expected_temp) - expected_hs = VALID_RGB_COLOR + expected_hs = VALID_KELVIN expected_hs["entity_id"] = "light.entity_hs" expected_calls.append(expected_hs) + expected_kelvin = VALID_PROFILE + expected_kelvin["entity_id"] = "light.entity_kelvin" + expected_calls.append(expected_kelvin) + + expected_profile = VALID_RGB_COLOR + expected_profile["entity_id"] = "light.entity_profile" + expected_calls.append(expected_profile) + expected_rgb = VALID_XY_COLOR expected_rgb["entity_id"] = "light.entity_rgb" expected_calls.append(expected_rgb) @@ -115,3 +156,14 @@ async def test_reproducing_states(hass, caplog): assert len(turn_off_calls) == 1 assert turn_off_calls[0].domain == "light" assert turn_off_calls[0].data == {"entity_id": "light.entity_xy"} + + +async def test_deprecation_warning(hass, caplog): + """Test deprecation warning.""" + hass.states.async_set("light.entity_off", "off", {}) + turn_on_calls = async_mock_service(hass, "light", "turn_on") + await hass.helpers.state.async_reproduce_state( + [State("light.entity_off", "on", {"brightness_pct": 80})], blocking=True + ) + assert len(turn_on_calls) == 1 + assert DEPRECATION_WARNING in caplog.text From b2a5c75fbda410c02fab8a2d003d7506f1abb0b7 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Tue, 5 Nov 2019 09:09:00 -0800 Subject: [PATCH 10/11] Bumped version to 0.101.3 --- homeassistant/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homeassistant/const.py b/homeassistant/const.py index 575a7d5740f..424944f244c 100644 --- a/homeassistant/const.py +++ b/homeassistant/const.py @@ -1,7 +1,7 @@ """Constants used by Home Assistant components.""" MAJOR_VERSION = 0 MINOR_VERSION = 101 -PATCH_VERSION = "2" +PATCH_VERSION = "3" __short_version__ = "{}.{}".format(MAJOR_VERSION, MINOR_VERSION) __version__ = "{}.{}".format(__short_version__, PATCH_VERSION) REQUIRED_PYTHON_VER = (3, 6, 1) From a0443b0238afed2075154ec238b56b7efa448106 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Sat, 2 Nov 2019 21:21:13 -0700 Subject: [PATCH 11/11] Fix flaky test --- tests/test_requirements.py | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/tests/test_requirements.py b/tests/test_requirements.py index 782b4386552..2627a077a87 100644 --- a/tests/test_requirements.py +++ b/tests/test_requirements.py @@ -144,14 +144,18 @@ async def test_get_integration_with_requirements(hass): assert integration.domain == "test_component" assert len(mock_is_installed.mock_calls) == 3 - assert mock_is_installed.mock_calls[0][1][0] == "test-comp==1.0.0" - assert mock_is_installed.mock_calls[1][1][0] == "test-comp-dep==1.0.0" - assert mock_is_installed.mock_calls[2][1][0] == "test-comp-after-dep==1.0.0" + assert sorted(mock_call[1][0] for mock_call in mock_is_installed.mock_calls) == [ + "test-comp-after-dep==1.0.0", + "test-comp-dep==1.0.0", + "test-comp==1.0.0", + ] assert len(mock_inst.mock_calls) == 3 - assert mock_inst.mock_calls[0][1][0] == "test-comp==1.0.0" - assert mock_inst.mock_calls[1][1][0] == "test-comp-dep==1.0.0" - assert mock_inst.mock_calls[2][1][0] == "test-comp-after-dep==1.0.0" + assert sorted(mock_call[1][0] for mock_call in mock_inst.mock_calls) == [ + "test-comp-after-dep==1.0.0", + "test-comp-dep==1.0.0", + "test-comp==1.0.0", + ] async def test_install_with_wheels_index(hass):