Enforce MediaPlayerState in group (#78465)

* Enforce MediaPlayerState in group

* Adjust

* Use self._attr_state

* Add warning

* Add group name to logger warning

* Remove logger warning

* Remove duplicate code

* Add type hints to tests

* Improve coverage

* Improve coverage

* suppress ValueError
pull/78467/head
epenet 2022-11-30 10:13:14 +01:00 committed by GitHub
parent b5aac9a1c7
commit 200f29563a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 21 additions and 17 deletions

View File

@ -1,6 +1,7 @@
"""This platform allows several media players to be grouped into one media player."""
from __future__ import annotations
from contextlib import suppress
from typing import Any
import voluptuous as vol
@ -108,7 +109,6 @@ class MediaPlayerGroup(MediaPlayerEntity):
def __init__(self, unique_id: str | None, name: str, entities: list[str]) -> None:
"""Initialize a Media Group entity."""
self._name = name
self._state: str | None = None
self._attr_unique_id = unique_id
self._entities = entities
@ -206,11 +206,6 @@ class MediaPlayerGroup(MediaPlayerEntity):
"""Return the name of the entity."""
return self._name
@property
def state(self) -> str | None:
"""Return the state of the media group."""
return self._state
@property
def extra_state_attributes(self) -> dict:
"""Return the state attributes for the media group."""
@ -395,15 +390,17 @@ class MediaPlayerGroup(MediaPlayerEntity):
)
if not valid_state:
# Set as unknown if all members are unknown or unavailable
self._state = None
self._attr_state = None
else:
off_values = {MediaPlayerState.OFF, STATE_UNAVAILABLE, STATE_UNKNOWN}
if states.count(states[0]) == len(states):
self._state = states[0]
if states.count(single_state := states[0]) == len(states):
self._attr_state = None
with suppress(ValueError):
self._attr_state = MediaPlayerState(single_state)
elif any(state for state in states if state not in off_values):
self._state = MediaPlayerState.ON
self._attr_state = MediaPlayerState.ON
else:
self._state = MediaPlayerState.OFF
self._attr_state = MediaPlayerState.OFF
supported_features = MediaPlayerEntityFeature(0)
if self._features[KEY_CLEAR_PLAYLIST]:

View File

@ -1,5 +1,5 @@
"""The tests for the Media group platform."""
from unittest.mock import patch
from unittest.mock import Mock, patch
import async_timeout
import pytest
@ -43,6 +43,7 @@ from homeassistant.const import (
STATE_UNAVAILABLE,
STATE_UNKNOWN,
)
from homeassistant.core import HomeAssistant
from homeassistant.helpers import entity_registry as er
from homeassistant.setup import async_setup_component
@ -57,7 +58,7 @@ def media_player_media_seek_fixture():
yield seek
async def test_default_state(hass):
async def test_default_state(hass: HomeAssistant) -> None:
"""Test media group default state."""
hass.states.async_set("media_player.player_1", "on")
await async_setup_component(
@ -91,7 +92,7 @@ async def test_default_state(hass):
assert entry.unique_id == "unique_identifier"
async def test_state_reporting(hass):
async def test_state_reporting(hass: HomeAssistant) -> None:
"""Test the state reporting.
The group state is unavailable if all group members are unavailable.
@ -170,6 +171,12 @@ async def test_state_reporting(hass):
await hass.async_block_till_done()
assert hass.states.get("media_player.media_group").state == STATE_OFF
# All group members in same invalid state -> unknown
hass.states.async_set("media_player.player_1", "invalid_state")
hass.states.async_set("media_player.player_2", "invalid_state")
await hass.async_block_till_done()
assert hass.states.get("media_player.media_group").state == STATE_UNKNOWN
# All group members removed from the state machine -> unavailable
hass.states.async_remove("media_player.player_1")
hass.states.async_remove("media_player.player_2")
@ -177,7 +184,7 @@ async def test_state_reporting(hass):
assert hass.states.get("media_player.media_group").state == STATE_UNAVAILABLE
async def test_supported_features(hass):
async def test_supported_features(hass: HomeAssistant) -> None:
"""Test supported features reporting."""
pause_play_stop = (
MediaPlayerEntityFeature.PAUSE
@ -241,7 +248,7 @@ async def test_supported_features(hass):
assert state.attributes[ATTR_SUPPORTED_FEATURES] == pause_play_stop | play_media
async def test_service_calls(hass, mock_media_seek):
async def test_service_calls(hass: HomeAssistant, mock_media_seek: Mock) -> None:
"""Test service calls."""
await async_setup_component(
hass,
@ -533,7 +540,7 @@ async def test_service_calls(hass, mock_media_seek):
assert hass.states.get("media_player.living_room").state == STATE_OFF
async def test_nested_group(hass):
async def test_nested_group(hass: HomeAssistant) -> None:
"""Test nested media group."""
await async_setup_component(
hass,