Improve type hints in demo [1/3] (#77180)

This commit is contained in:
epenet 2022-08-29 00:51:10 +02:00 committed by GitHub
parent 575ac5ae0a
commit 7eb8e1f25d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 156 additions and 247 deletions

View File

@ -32,39 +32,27 @@ async def async_setup_entry(
class DemoAirQuality(AirQualityEntity): class DemoAirQuality(AirQualityEntity):
"""Representation of Air Quality data.""" """Representation of Air Quality data."""
def __init__(self, name, pm_2_5, pm_10, n2o): _attr_attribution = "Powered by Home Assistant"
_attr_should_poll = False
def __init__(self, name: str, pm_2_5: int, pm_10: int, n2o: int | None) -> None:
"""Initialize the Demo Air Quality.""" """Initialize the Demo Air Quality."""
self._name = name self._attr_name = f"Demo Air Quality {name}"
self._pm_2_5 = pm_2_5 self._pm_2_5 = pm_2_5
self._pm_10 = pm_10 self._pm_10 = pm_10
self._n2o = n2o self._n2o = n2o
@property @property
def name(self): def particulate_matter_2_5(self) -> int:
"""Return the name of the sensor."""
return f"Demo Air Quality {self._name}"
@property
def should_poll(self):
"""No polling needed for Demo Air Quality."""
return False
@property
def particulate_matter_2_5(self):
"""Return the particulate matter 2.5 level.""" """Return the particulate matter 2.5 level."""
return self._pm_2_5 return self._pm_2_5
@property @property
def particulate_matter_10(self): def particulate_matter_10(self) -> int:
"""Return the particulate matter 10 level.""" """Return the particulate matter 10 level."""
return self._pm_10 return self._pm_10
@property @property
def nitrogen_oxide(self): def nitrogen_oxide(self) -> int | None:
"""Return the nitrogen oxide (N2O) level.""" """Return the nitrogen oxide (N2O) level."""
return self._n2o return self._n2o
@property
def attribution(self):
"""Return the attribution."""
return "Powered by Home Assistant"

View File

@ -48,6 +48,8 @@ async def async_setup_entry(
class DemoBinarySensor(BinarySensorEntity): class DemoBinarySensor(BinarySensorEntity):
"""representation of a Demo binary sensor.""" """representation of a Demo binary sensor."""
_attr_should_poll = False
def __init__( def __init__(
self, self,
unique_id: str, unique_id: str,
@ -57,7 +59,7 @@ class DemoBinarySensor(BinarySensorEntity):
) -> None: ) -> None:
"""Initialize the demo sensor.""" """Initialize the demo sensor."""
self._unique_id = unique_id self._unique_id = unique_id
self._name = name self._attr_name = name
self._state = state self._state = state
self._sensor_type = device_class self._sensor_type = device_class
@ -82,16 +84,6 @@ class DemoBinarySensor(BinarySensorEntity):
"""Return the class of this sensor.""" """Return the class of this sensor."""
return self._sensor_type return self._sensor_type
@property
def should_poll(self) -> bool:
"""No polling needed for a demo binary sensor."""
return False
@property
def name(self) -> str:
"""Return the name of the binary sensor."""
return self._name
@property @property
def is_on(self) -> bool: def is_on(self) -> bool:
"""Return true if the binary sensor is on.""" """Return true if the binary sensor is on."""

View File

@ -3,6 +3,7 @@ from __future__ import annotations
import copy import copy
import datetime import datetime
from typing import Any
from homeassistant.components.calendar import ( from homeassistant.components.calendar import (
CalendarEntity, CalendarEntity,
@ -60,18 +61,13 @@ class DemoCalendar(CalendarEntity):
def __init__(self, event: CalendarEvent, name: str) -> None: def __init__(self, event: CalendarEvent, name: str) -> None:
"""Initialize demo calendar.""" """Initialize demo calendar."""
self._event = event self._event = event
self._name = name self._attr_name = name
@property @property
def event(self) -> CalendarEvent: def event(self) -> CalendarEvent:
"""Return the next upcoming event.""" """Return the next upcoming event."""
return self._event return self._event
@property
def name(self) -> str:
"""Return the name of the entity."""
return self._name
async def async_get_events( async def async_get_events(
self, self,
hass: HomeAssistant, hass: HomeAssistant,
@ -87,7 +83,7 @@ class LegacyDemoCalendar(CalendarEventDevice):
def __init__(self, name: str) -> None: def __init__(self, name: str) -> None:
"""Initialize demo calendar.""" """Initialize demo calendar."""
self._name = name self._attr_name = name
one_hour_from_now = dt_util.now() + datetime.timedelta(minutes=30) one_hour_from_now = dt_util.now() + datetime.timedelta(minutes=30)
self._event = { self._event = {
"start": {"dateTime": one_hour_from_now.isoformat()}, "start": {"dateTime": one_hour_from_now.isoformat()},
@ -102,16 +98,16 @@ class LegacyDemoCalendar(CalendarEventDevice):
} }
@property @property
def event(self): def event(self) -> dict[str, Any]:
"""Return the next upcoming event.""" """Return the next upcoming event."""
return self._event return self._event
@property async def async_get_events(
def name(self) -> str: self,
"""Return the name of the entity.""" hass: HomeAssistant,
return self._name start_date: datetime.datetime,
end_date: datetime.datetime,
async def async_get_events(self, hass, start_date, end_date): ) -> list[dict[str, Any]]:
"""Get all events in a specific time frame.""" """Get all events in a specific time frame."""
event = copy.copy(self.event) event = copy.copy(self.event)
event["title"] = event["summary"] event["title"] = event["summary"]

View File

@ -103,6 +103,8 @@ async def async_setup_entry(
class DemoClimate(ClimateEntity): class DemoClimate(ClimateEntity):
"""Representation of a demo climate device.""" """Representation of a demo climate device."""
_attr_should_poll = False
def __init__( def __init__(
self, self,
unique_id: str, unique_id: str,
@ -125,7 +127,7 @@ class DemoClimate(ClimateEntity):
) -> None: ) -> None:
"""Initialize the climate device.""" """Initialize the climate device."""
self._unique_id = unique_id self._unique_id = unique_id
self._name = name self._attr_name = name
self._support_flags = SUPPORT_FLAGS self._support_flags = SUPPORT_FLAGS
if target_temperature is not None: if target_temperature is not None:
self._support_flags = ( self._support_flags = (
@ -186,16 +188,6 @@ class DemoClimate(ClimateEntity):
"""Return the list of supported features.""" """Return the list of supported features."""
return self._support_flags return self._support_flags
@property
def should_poll(self) -> bool:
"""Return the polling state."""
return False
@property
def name(self) -> str:
"""Return the name of the climate device."""
return self._name
@property @property
def temperature_unit(self) -> str: def temperature_unit(self) -> str:
"""Return the unit of measurement.""" """Return the unit of measurement."""

View File

@ -1,6 +1,7 @@
"""Demo platform for the cover component.""" """Demo platform for the cover component."""
from __future__ import annotations from __future__ import annotations
from datetime import datetime
from typing import Any from typing import Any
from homeassistant.components.cover import ( from homeassistant.components.cover import (
@ -11,7 +12,7 @@ from homeassistant.components.cover import (
CoverEntityFeature, CoverEntityFeature,
) )
from homeassistant.config_entries import ConfigEntry from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant, callback from homeassistant.core import CALLBACK_TYPE, HomeAssistant, callback
from homeassistant.helpers.entity import DeviceInfo from homeassistant.helpers.entity import DeviceInfo
from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.event import async_track_utc_time_change from homeassistant.helpers.event import async_track_utc_time_change
@ -67,36 +68,38 @@ async def async_setup_entry(
class DemoCover(CoverEntity): class DemoCover(CoverEntity):
"""Representation of a demo cover.""" """Representation of a demo cover."""
_attr_should_poll = False
def __init__( def __init__(
self, self,
hass, hass: HomeAssistant,
unique_id, unique_id: str,
name, name: str,
position=None, position: int | None = None,
tilt_position=None, tilt_position: int | None = None,
device_class=None, device_class: CoverDeviceClass | None = None,
supported_features=None, supported_features: int | None = None,
): ) -> None:
"""Initialize the cover.""" """Initialize the cover."""
self.hass = hass self.hass = hass
self._unique_id = unique_id self._unique_id = unique_id
self._name = name self._attr_name = name
self._position = position self._position = position
self._device_class = device_class self._device_class = device_class
self._supported_features = supported_features self._supported_features = supported_features
self._set_position = None self._set_position: int | None = None
self._set_tilt_position = None self._set_tilt_position: int | None = None
self._tilt_position = tilt_position self._tilt_position = tilt_position
self._requested_closing = True self._requested_closing = True
self._requested_closing_tilt = True self._requested_closing_tilt = True
self._unsub_listener_cover = None self._unsub_listener_cover: CALLBACK_TYPE | None = None
self._unsub_listener_cover_tilt = None self._unsub_listener_cover_tilt: CALLBACK_TYPE | None = None
self._is_opening = False self._is_opening = False
self._is_closing = False self._is_closing = False
if position is None: if position is None:
self._closed = True self._closed = True
else: else:
self._closed = self.current_cover_position <= 0 self._closed = position <= 0
@property @property
def device_info(self) -> DeviceInfo: def device_info(self) -> DeviceInfo:
@ -114,16 +117,6 @@ class DemoCover(CoverEntity):
"""Return unique ID for cover.""" """Return unique ID for cover."""
return self._unique_id return self._unique_id
@property
def name(self) -> str:
"""Return the name of the cover."""
return self._name
@property
def should_poll(self) -> bool:
"""No polling needed for a demo cover."""
return False
@property @property
def current_cover_position(self) -> int | None: def current_cover_position(self) -> int | None:
"""Return the current position of the cover.""" """Return the current position of the cover."""
@ -213,7 +206,9 @@ class DemoCover(CoverEntity):
return return
self._listen_cover() self._listen_cover()
self._requested_closing = position < self._position self._requested_closing = (
self._position is not None and position < self._position
)
async def async_set_cover_tilt_position(self, **kwargs: Any) -> None: async def async_set_cover_tilt_position(self, **kwargs: Any) -> None:
"""Move the cover til to a specific position.""" """Move the cover til to a specific position."""
@ -223,7 +218,9 @@ class DemoCover(CoverEntity):
return return
self._listen_cover_tilt() self._listen_cover_tilt()
self._requested_closing_tilt = tilt_position < self._tilt_position self._requested_closing_tilt = (
self._tilt_position is not None and tilt_position < self._tilt_position
)
async def async_stop_cover(self, **kwargs: Any) -> None: async def async_stop_cover(self, **kwargs: Any) -> None:
"""Stop the cover.""" """Stop the cover."""
@ -247,15 +244,17 @@ class DemoCover(CoverEntity):
self._set_tilt_position = None self._set_tilt_position = None
@callback @callback
def _listen_cover(self): def _listen_cover(self) -> None:
"""Listen for changes in cover.""" """Listen for changes in cover."""
if self._unsub_listener_cover is None: if self._unsub_listener_cover is None:
self._unsub_listener_cover = async_track_utc_time_change( self._unsub_listener_cover = async_track_utc_time_change(
self.hass, self._time_changed_cover self.hass, self._time_changed_cover
) )
async def _time_changed_cover(self, now): async def _time_changed_cover(self, now: datetime) -> None:
"""Track time changes.""" """Track time changes."""
if self._position is None:
return
if self._requested_closing: if self._requested_closing:
self._position -= 10 self._position -= 10
else: else:
@ -264,19 +263,23 @@ class DemoCover(CoverEntity):
if self._position in (100, 0, self._set_position): if self._position in (100, 0, self._set_position):
await self.async_stop_cover() await self.async_stop_cover()
self._closed = self.current_cover_position <= 0 self._closed = (
self.current_cover_position is not None and self.current_cover_position <= 0
)
self.async_write_ha_state() self.async_write_ha_state()
@callback @callback
def _listen_cover_tilt(self): def _listen_cover_tilt(self) -> None:
"""Listen for changes in cover tilt.""" """Listen for changes in cover tilt."""
if self._unsub_listener_cover_tilt is None: if self._unsub_listener_cover_tilt is None:
self._unsub_listener_cover_tilt = async_track_utc_time_change( self._unsub_listener_cover_tilt = async_track_utc_time_change(
self.hass, self._time_changed_cover_tilt self.hass, self._time_changed_cover_tilt
) )
async def _time_changed_cover_tilt(self, now): async def _time_changed_cover_tilt(self, now: datetime) -> None:
"""Track time changes.""" """Track time changes."""
if self._tilt_position is None:
return
if self._requested_closing_tilt: if self._requested_closing_tilt:
self._tilt_position -= 10 self._tilt_position -= 10
else: else:

View File

@ -100,9 +100,11 @@ async def async_setup_entry(
class BaseDemoFan(FanEntity): class BaseDemoFan(FanEntity):
"""A demonstration fan component that uses legacy fan speeds.""" """A demonstration fan component that uses legacy fan speeds."""
_attr_should_poll = False
def __init__( def __init__(
self, self,
hass, hass: HomeAssistant,
unique_id: str, unique_id: str,
name: str, name: str,
supported_features: int, supported_features: int,
@ -117,7 +119,7 @@ class BaseDemoFan(FanEntity):
self._preset_mode: str | None = None self._preset_mode: str | None = None
self._oscillating: bool | None = None self._oscillating: bool | None = None
self._direction: str | None = None self._direction: str | None = None
self._name = name self._attr_name = name
if supported_features & FanEntityFeature.OSCILLATE: if supported_features & FanEntityFeature.OSCILLATE:
self._oscillating = False self._oscillating = False
if supported_features & FanEntityFeature.DIRECTION: if supported_features & FanEntityFeature.DIRECTION:
@ -128,16 +130,6 @@ class BaseDemoFan(FanEntity):
"""Return the unique id.""" """Return the unique id."""
return self._unique_id return self._unique_id
@property
def name(self) -> str:
"""Get entity name."""
return self._name
@property
def should_poll(self) -> bool:
"""No polling needed for a demo fan."""
return False
@property @property
def current_direction(self) -> str | None: def current_direction(self) -> str | None:
"""Fan direction.""" """Fan direction."""

View File

@ -112,6 +112,8 @@ class DemoManager:
class DemoGeolocationEvent(GeolocationEvent): class DemoGeolocationEvent(GeolocationEvent):
"""This represents a demo geolocation event.""" """This represents a demo geolocation event."""
_attr_should_poll = False
def __init__( def __init__(
self, self,
name: str, name: str,
@ -121,7 +123,7 @@ class DemoGeolocationEvent(GeolocationEvent):
unit_of_measurement: str, unit_of_measurement: str,
) -> None: ) -> None:
"""Initialize entity with data provided.""" """Initialize entity with data provided."""
self._name = name self._attr_name = name
self._distance = distance self._distance = distance
self._latitude = latitude self._latitude = latitude
self._longitude = longitude self._longitude = longitude
@ -132,16 +134,6 @@ class DemoGeolocationEvent(GeolocationEvent):
"""Return source value of this external event.""" """Return source value of this external event."""
return SOURCE return SOURCE
@property
def name(self) -> str | None:
"""Return the name of the event."""
return self._name
@property
def should_poll(self) -> bool:
"""No polling needed for a demo geolocation event."""
return False
@property @property
def distance(self) -> float | None: def distance(self) -> float | None:
"""Return distance value of this external event.""" """Return distance value of this external event."""

View File

@ -39,7 +39,7 @@ class DemoImageProcessingAlpr(ImageProcessingAlprEntity):
"""Initialize demo ALPR image processing entity.""" """Initialize demo ALPR image processing entity."""
super().__init__() super().__init__()
self._name = name self._attr_name = name
self._camera = camera_entity self._camera = camera_entity
@property @property
@ -52,11 +52,6 @@ class DemoImageProcessingAlpr(ImageProcessingAlprEntity):
"""Return minimum confidence for send events.""" """Return minimum confidence for send events."""
return 80 return 80
@property
def name(self) -> str:
"""Return the name of the entity."""
return self._name
def process_image(self, image: Image) -> None: def process_image(self, image: Image) -> None:
"""Process image.""" """Process image."""
demo_data = { demo_data = {
@ -76,7 +71,7 @@ class DemoImageProcessingFace(ImageProcessingFaceEntity):
"""Initialize demo face image processing entity.""" """Initialize demo face image processing entity."""
super().__init__() super().__init__()
self._name = name self._attr_name = name
self._camera = camera_entity self._camera = camera_entity
@property @property
@ -89,11 +84,6 @@ class DemoImageProcessingFace(ImageProcessingFaceEntity):
"""Return minimum confidence for send events.""" """Return minimum confidence for send events."""
return 80 return 80
@property
def name(self) -> str:
"""Return the name of the entity."""
return self._name
def process_image(self, image: Image) -> None: def process_image(self, image: Image) -> None:
"""Process image.""" """Process image."""
demo_data = [ demo_data = [

View File

@ -106,21 +106,23 @@ async def async_setup_entry(
class DemoLight(LightEntity): class DemoLight(LightEntity):
"""Representation of a demo light.""" """Representation of a demo light."""
_attr_should_poll = False
def __init__( def __init__(
self, self,
unique_id: str, unique_id: str,
name: str, name: str,
state, state: bool,
available=False, available: bool = False,
brightness=180, brightness: int = 180,
ct=None, # pylint: disable=invalid-name ct: int | None = None, # pylint: disable=invalid-name
effect_list: list[str] | None = None, effect_list: list[str] | None = None,
effect=None, effect: str | None = None,
hs_color=None, hs_color: tuple[int, int] | None = None,
rgbw_color=None, rgbw_color: tuple[int, int, int, int] | None = None,
rgbww_color=None, rgbww_color: tuple[int, int, int, int, int] | None = None,
supported_color_modes: set[ColorMode] | None = None, supported_color_modes: set[ColorMode] | None = None,
): ) -> None:
"""Initialize the light.""" """Initialize the light."""
self._available = True self._available = True
self._brightness = brightness self._brightness = brightness
@ -129,7 +131,7 @@ class DemoLight(LightEntity):
self._effect_list = effect_list self._effect_list = effect_list
self._features = 0 self._features = 0
self._hs_color = hs_color self._hs_color = hs_color
self._name = name self._attr_name = name
self._rgbw_color = rgbw_color self._rgbw_color = rgbw_color
self._rgbww_color = rgbww_color self._rgbww_color = rgbww_color
self._state = state self._state = state
@ -159,16 +161,6 @@ class DemoLight(LightEntity):
name=self.name, name=self.name,
) )
@property
def should_poll(self) -> bool:
"""No polling needed for a demo light."""
return False
@property
def name(self) -> str:
"""Return the name of the light if any."""
return self._name
@property @property
def unique_id(self) -> str: def unique_id(self) -> str:
"""Return unique ID for light.""" """Return unique ID for light."""
@ -192,17 +184,17 @@ class DemoLight(LightEntity):
return self._color_mode return self._color_mode
@property @property
def hs_color(self) -> tuple[float, float]: def hs_color(self) -> tuple[int, int] | None:
"""Return the hs color value.""" """Return the hs color value."""
return self._hs_color return self._hs_color
@property @property
def rgbw_color(self) -> tuple[int, int, int, int]: def rgbw_color(self) -> tuple[int, int, int, int] | None:
"""Return the rgbw color value.""" """Return the rgbw color value."""
return self._rgbw_color return self._rgbw_color
@property @property
def rgbww_color(self) -> tuple[int, int, int, int, int]: def rgbww_color(self) -> tuple[int, int, int, int, int] | None:
"""Return the rgbww color value.""" """Return the rgbww color value."""
return self._rgbww_color return self._rgbww_color
@ -217,7 +209,7 @@ class DemoLight(LightEntity):
return self._effect_list return self._effect_list
@property @property
def effect(self) -> str: def effect(self) -> str | None:
"""Return the current effect.""" """Return the current effect."""
return self._effect return self._effect

View File

@ -1,6 +1,7 @@
"""Demo implementation of the media player.""" """Demo implementation of the media player."""
from __future__ import annotations from __future__ import annotations
from datetime import datetime
from typing import Any from typing import Any
from homeassistant.components.media_player import ( from homeassistant.components.media_player import (
@ -108,11 +109,15 @@ NETFLIX_PLAYER_SUPPORT = (
class AbstractDemoPlayer(MediaPlayerEntity): class AbstractDemoPlayer(MediaPlayerEntity):
"""A demo media players.""" """A demo media players."""
_attr_should_poll = False
# We only implement the methods that we support # We only implement the methods that we support
def __init__(self, name, device_class=None): def __init__(
self, name: str, device_class: MediaPlayerDeviceClass | None = None
) -> None:
"""Initialize the demo device.""" """Initialize the demo device."""
self._name = name self._attr_name = name
self._player_state = STATE_PLAYING self._player_state = STATE_PLAYING
self._volume_level = 1.0 self._volume_level = 1.0
self._volume_muted = False self._volume_muted = False
@ -122,47 +127,37 @@ class AbstractDemoPlayer(MediaPlayerEntity):
self._device_class = device_class self._device_class = device_class
@property @property
def should_poll(self): def state(self) -> str:
"""Push an update after each command."""
return False
@property
def name(self):
"""Return the name of the media player."""
return self._name
@property
def state(self):
"""Return the state of the player.""" """Return the state of the player."""
return self._player_state return self._player_state
@property @property
def volume_level(self): def volume_level(self) -> float:
"""Return the volume level of the media player (0..1).""" """Return the volume level of the media player (0..1)."""
return self._volume_level return self._volume_level
@property @property
def is_volume_muted(self): def is_volume_muted(self) -> bool:
"""Return boolean if volume is currently muted.""" """Return boolean if volume is currently muted."""
return self._volume_muted return self._volume_muted
@property @property
def shuffle(self): def shuffle(self) -> bool:
"""Boolean if shuffling is enabled.""" """Boolean if shuffling is enabled."""
return self._shuffle return self._shuffle
@property @property
def sound_mode(self): def sound_mode(self) -> str:
"""Return the current sound mode.""" """Return the current sound mode."""
return self._sound_mode return self._sound_mode
@property @property
def sound_mode_list(self): def sound_mode_list(self) -> list[str]:
"""Return a list of available sound modes.""" """Return a list of available sound modes."""
return self._sound_mode_list return self._sound_mode_list
@property @property
def device_class(self): def device_class(self) -> MediaPlayerDeviceClass | None:
"""Return the device class of the media player.""" """Return the device class of the media player."""
return self._device_class return self._device_class
@ -227,52 +222,54 @@ class DemoYoutubePlayer(AbstractDemoPlayer):
# We only implement the methods that we support # We only implement the methods that we support
def __init__(self, name, youtube_id=None, media_title=None, duration=360): def __init__(
self, name: str, youtube_id: str, media_title: str, duration: int
) -> None:
"""Initialize the demo device.""" """Initialize the demo device."""
super().__init__(name) super().__init__(name)
self.youtube_id = youtube_id self.youtube_id = youtube_id
self._media_title = media_title self._media_title = media_title
self._duration = duration self._duration = duration
self._progress = int(duration * 0.15) self._progress: int | None = int(duration * 0.15)
self._progress_updated_at = dt_util.utcnow() self._progress_updated_at = dt_util.utcnow()
@property @property
def media_content_id(self): def media_content_id(self) -> str:
"""Return the content ID of current playing media.""" """Return the content ID of current playing media."""
return self.youtube_id return self.youtube_id
@property @property
def media_content_type(self): def media_content_type(self) -> str:
"""Return the content type of current playing media.""" """Return the content type of current playing media."""
return MEDIA_TYPE_MOVIE return MEDIA_TYPE_MOVIE
@property @property
def media_duration(self): def media_duration(self) -> int:
"""Return the duration of current playing media in seconds.""" """Return the duration of current playing media in seconds."""
return self._duration return self._duration
@property @property
def media_image_url(self): def media_image_url(self) -> str:
"""Return the image url of current playing media.""" """Return the image url of current playing media."""
return f"https://img.youtube.com/vi/{self.youtube_id}/hqdefault.jpg" return f"https://img.youtube.com/vi/{self.youtube_id}/hqdefault.jpg"
@property @property
def media_title(self): def media_title(self) -> str:
"""Return the title of current playing media.""" """Return the title of current playing media."""
return self._media_title return self._media_title
@property @property
def app_name(self): def app_name(self) -> str:
"""Return the current running application.""" """Return the current running application."""
return "YouTube" return "YouTube"
@property @property
def supported_features(self): def supported_features(self) -> int:
"""Flag media player features that are supported.""" """Flag media player features that are supported."""
return YOUTUBE_PLAYER_SUPPORT return YOUTUBE_PLAYER_SUPPORT
@property @property
def media_position(self): def media_position(self) -> int | None:
"""Position of current playing media in seconds.""" """Position of current playing media in seconds."""
if self._progress is None: if self._progress is None:
return None return None
@ -280,18 +277,21 @@ class DemoYoutubePlayer(AbstractDemoPlayer):
position = self._progress position = self._progress
if self._player_state == STATE_PLAYING: if self._player_state == STATE_PLAYING:
position += (dt_util.utcnow() - self._progress_updated_at).total_seconds() position += int(
(dt_util.utcnow() - self._progress_updated_at).total_seconds()
)
return position return position
@property @property
def media_position_updated_at(self): def media_position_updated_at(self) -> datetime | None:
"""When was the position of the current playing media valid. """When was the position of the current playing media valid.
Returns value from homeassistant.util.dt.utcnow(). Returns value from homeassistant.util.dt.utcnow().
""" """
if self._player_state == STATE_PLAYING: if self._player_state == STATE_PLAYING:
return self._progress_updated_at return self._progress_updated_at
return None
def play_media(self, media_type: str, media_id: str, **kwargs: Any) -> None: def play_media(self, media_type: str, media_id: str, **kwargs: Any) -> None:
"""Play a piece of media.""" """Play a piece of media."""
@ -333,65 +333,65 @@ class DemoMusicPlayer(AbstractDemoPlayer):
), ),
] ]
def __init__(self, name="Walkman"): def __init__(self, name: str = "Walkman") -> None:
"""Initialize the demo device.""" """Initialize the demo device."""
super().__init__(name) super().__init__(name)
self._cur_track = 0 self._cur_track = 0
self._group_members = [] self._group_members: list[str] = []
self._repeat = REPEAT_MODE_OFF self._repeat = REPEAT_MODE_OFF
@property @property
def group_members(self): def group_members(self) -> list[str]:
"""List of players which are currently grouped together.""" """List of players which are currently grouped together."""
return self._group_members return self._group_members
@property @property
def media_content_id(self): def media_content_id(self) -> str:
"""Return the content ID of current playing media.""" """Return the content ID of current playing media."""
return "bounzz-1" return "bounzz-1"
@property @property
def media_content_type(self): def media_content_type(self) -> str:
"""Return the content type of current playing media.""" """Return the content type of current playing media."""
return MEDIA_TYPE_MUSIC return MEDIA_TYPE_MUSIC
@property @property
def media_duration(self): def media_duration(self) -> int:
"""Return the duration of current playing media in seconds.""" """Return the duration of current playing media in seconds."""
return 213 return 213
@property @property
def media_image_url(self): def media_image_url(self) -> str:
"""Return the image url of current playing media.""" """Return the image url of current playing media."""
return "https://graph.facebook.com/v2.5/107771475912710/picture?type=large" return "https://graph.facebook.com/v2.5/107771475912710/picture?type=large"
@property @property
def media_title(self): def media_title(self) -> str:
"""Return the title of current playing media.""" """Return the title of current playing media."""
return self.tracks[self._cur_track][1] if self.tracks else "" return self.tracks[self._cur_track][1] if self.tracks else ""
@property @property
def media_artist(self): def media_artist(self) -> str:
"""Return the artist of current playing media (Music track only).""" """Return the artist of current playing media (Music track only)."""
return self.tracks[self._cur_track][0] if self.tracks else "" return self.tracks[self._cur_track][0] if self.tracks else ""
@property @property
def media_album_name(self): def media_album_name(self) -> str:
"""Return the album of current playing media (Music track only).""" """Return the album of current playing media (Music track only)."""
return "Bounzz" return "Bounzz"
@property @property
def media_track(self): def media_track(self) -> int:
"""Return the track number of current media (Music track only).""" """Return the track number of current media (Music track only)."""
return self._cur_track + 1 return self._cur_track + 1
@property @property
def repeat(self): def repeat(self) -> str:
"""Return current repeat mode.""" """Return current repeat mode."""
return self._repeat return self._repeat
@property @property
def supported_features(self): def supported_features(self) -> int:
"""Flag media player features that are supported.""" """Flag media player features that are supported."""
return MUSIC_PLAYER_SUPPORT return MUSIC_PLAYER_SUPPORT
@ -439,7 +439,7 @@ class DemoTVShowPlayer(AbstractDemoPlayer):
_attr_device_class = MediaPlayerDeviceClass.TV _attr_device_class = MediaPlayerDeviceClass.TV
def __init__(self): def __init__(self) -> None:
"""Initialize the demo device.""" """Initialize the demo device."""
super().__init__("Lounge room") super().__init__("Lounge room")
self._cur_episode = 1 self._cur_episode = 1
@ -448,62 +448,62 @@ class DemoTVShowPlayer(AbstractDemoPlayer):
self._source_list = ["dvd", "youtube"] self._source_list = ["dvd", "youtube"]
@property @property
def media_content_id(self): def media_content_id(self) -> str:
"""Return the content ID of current playing media.""" """Return the content ID of current playing media."""
return "house-of-cards-1" return "house-of-cards-1"
@property @property
def media_content_type(self): def media_content_type(self) -> str:
"""Return the content type of current playing media.""" """Return the content type of current playing media."""
return MEDIA_TYPE_TVSHOW return MEDIA_TYPE_TVSHOW
@property @property
def media_duration(self): def media_duration(self) -> int:
"""Return the duration of current playing media in seconds.""" """Return the duration of current playing media in seconds."""
return 3600 return 3600
@property @property
def media_image_url(self): def media_image_url(self) -> str:
"""Return the image url of current playing media.""" """Return the image url of current playing media."""
return "https://graph.facebook.com/v2.5/HouseofCards/picture?width=400" return "https://graph.facebook.com/v2.5/HouseofCards/picture?width=400"
@property @property
def media_title(self): def media_title(self) -> str:
"""Return the title of current playing media.""" """Return the title of current playing media."""
return f"Chapter {self._cur_episode}" return f"Chapter {self._cur_episode}"
@property @property
def media_series_title(self): def media_series_title(self) -> str:
"""Return the series title of current playing media (TV Show only).""" """Return the series title of current playing media (TV Show only)."""
return "House of Cards" return "House of Cards"
@property @property
def media_season(self): def media_season(self) -> str:
"""Return the season of current playing media (TV Show only).""" """Return the season of current playing media (TV Show only)."""
return 1 return "1"
@property @property
def media_episode(self): def media_episode(self) -> str:
"""Return the episode of current playing media (TV Show only).""" """Return the episode of current playing media (TV Show only)."""
return self._cur_episode return str(self._cur_episode)
@property @property
def app_name(self): def app_name(self) -> str:
"""Return the current running application.""" """Return the current running application."""
return "Netflix" return "Netflix"
@property @property
def source(self): def source(self) -> str:
"""Return the current input source.""" """Return the current input source."""
return self._source return self._source
@property @property
def source_list(self): def source_list(self) -> list[str]:
"""List of available sources.""" """List of available sources."""
return self._source_list return self._source_list
@property @property
def supported_features(self): def supported_features(self) -> int:
"""Flag media player features that are supported.""" """Flag media player features that are supported."""
return NETFLIX_PLAYER_SUPPORT return NETFLIX_PLAYER_SUPPORT

View File

@ -104,9 +104,11 @@ async def async_setup_platform(
class DemoVacuum(VacuumEntity): class DemoVacuum(VacuumEntity):
"""Representation of a demo vacuum.""" """Representation of a demo vacuum."""
_attr_should_poll = False
def __init__(self, name: str, supported_features: int) -> None: def __init__(self, name: str, supported_features: int) -> None:
"""Initialize the vacuum.""" """Initialize the vacuum."""
self._name = name self._attr_name = name
self._supported_features = supported_features self._supported_features = supported_features
self._state = False self._state = False
self._status = "Charging" self._status = "Charging"
@ -114,16 +116,6 @@ class DemoVacuum(VacuumEntity):
self._cleaned_area: float = 0 self._cleaned_area: float = 0
self._battery_level = 100 self._battery_level = 100
@property
def name(self) -> str:
"""Return the name of the vacuum."""
return self._name
@property
def should_poll(self) -> bool:
"""No polling needed for a demo vacuum."""
return False
@property @property
def is_on(self) -> bool: def is_on(self) -> bool:
"""Return true if vacuum is on.""" """Return true if vacuum is on."""
@ -258,25 +250,17 @@ class DemoVacuum(VacuumEntity):
class StateDemoVacuum(StateVacuumEntity): class StateDemoVacuum(StateVacuumEntity):
"""Representation of a demo vacuum supporting states.""" """Representation of a demo vacuum supporting states."""
_attr_should_poll = False
def __init__(self, name: str) -> None: def __init__(self, name: str) -> None:
"""Initialize the vacuum.""" """Initialize the vacuum."""
self._name = name self._attr_name = name
self._supported_features = SUPPORT_STATE_SERVICES self._supported_features = SUPPORT_STATE_SERVICES
self._state = STATE_DOCKED self._state = STATE_DOCKED
self._fan_speed = FAN_SPEEDS[1] self._fan_speed = FAN_SPEEDS[1]
self._cleaned_area: float = 0 self._cleaned_area: float = 0
self._battery_level = 100 self._battery_level = 100
@property
def name(self) -> str:
"""Return the name of the vacuum."""
return self._name
@property
def should_poll(self) -> bool:
"""No polling needed for a demo vacuum."""
return False
@property @property
def supported_features(self) -> int: def supported_features(self) -> int:
"""Flag supported features.""" """Flag supported features."""

View File

@ -118,6 +118,9 @@ def setup_platform(
class DemoWeather(WeatherEntity): class DemoWeather(WeatherEntity):
"""Representation of a weather condition.""" """Representation of a weather condition."""
_attr_attribution = "Powered by Home Assistant"
_attr_should_poll = False
def __init__( def __init__(
self, self,
name: str, name: str,
@ -132,7 +135,7 @@ class DemoWeather(WeatherEntity):
forecast: list[list], forecast: list[list],
) -> None: ) -> None:
"""Initialize the Demo weather.""" """Initialize the Demo weather."""
self._name = name self._attr_name = f"Demo Weather {name}"
self._condition = condition self._condition = condition
self._native_temperature = temperature self._native_temperature = temperature
self._native_temperature_unit = temperature_unit self._native_temperature_unit = temperature_unit
@ -143,16 +146,6 @@ class DemoWeather(WeatherEntity):
self._native_wind_speed_unit = wind_speed_unit self._native_wind_speed_unit = wind_speed_unit
self._forecast = forecast self._forecast = forecast
@property
def name(self) -> str:
"""Return the name of the sensor."""
return f"Demo Weather {self._name}"
@property
def should_poll(self) -> bool:
"""No polling needed for a demo weather condition."""
return False
@property @property
def native_temperature(self) -> float: def native_temperature(self) -> float:
"""Return the temperature.""" """Return the temperature."""
@ -195,11 +188,6 @@ class DemoWeather(WeatherEntity):
k for k, v in CONDITION_CLASSES.items() if self._condition.lower() in v k for k, v in CONDITION_CLASSES.items() if self._condition.lower() in v
][0] ][0]
@property
def attribution(self) -> str:
"""Return the attribution."""
return "Powered by Home Assistant"
@property @property
def forecast(self) -> list[Forecast]: def forecast(self) -> list[Forecast]:
"""Return the forecast.""" """Return the forecast."""

View File

@ -306,7 +306,7 @@ async def test_prev_next_track(hass):
ent_id = "media_player.lounge_room" ent_id = "media_player.lounge_room"
state = hass.states.get(ent_id) state = hass.states.get(ent_id)
assert state.attributes.get(mp.ATTR_MEDIA_EPISODE) == 1 assert state.attributes.get(mp.ATTR_MEDIA_EPISODE) == "1"
await hass.services.async_call( await hass.services.async_call(
mp.DOMAIN, mp.DOMAIN,
@ -315,7 +315,7 @@ async def test_prev_next_track(hass):
blocking=True, blocking=True,
) )
state = hass.states.get(ent_id) state = hass.states.get(ent_id)
assert state.attributes.get(mp.ATTR_MEDIA_EPISODE) == 2 assert state.attributes.get(mp.ATTR_MEDIA_EPISODE) == "2"
await hass.services.async_call( await hass.services.async_call(
mp.DOMAIN, mp.DOMAIN,
@ -324,7 +324,7 @@ async def test_prev_next_track(hass):
blocking=True, blocking=True,
) )
state = hass.states.get(ent_id) state = hass.states.get(ent_id)
assert state.attributes.get(mp.ATTR_MEDIA_EPISODE) == 1 assert state.attributes.get(mp.ATTR_MEDIA_EPISODE) == "1"
async def test_play_media(hass): async def test_play_media(hass):