From 90c1263501de63098ba989d19301e1d745cbcbaa Mon Sep 17 00:00:00 2001 From: Erik Montnemery Date: Tue, 27 Jun 2023 11:59:24 +0200 Subject: [PATCH] Adjust image entity URL support (#95330) --- homeassistant/components/image/__init__.py | 27 +++++++++++----------- tests/components/image/conftest.py | 5 +--- 2 files changed, 14 insertions(+), 18 deletions(-) diff --git a/homeassistant/components/image/__init__.py b/homeassistant/components/image/__init__.py index 72636e3bf4a..b54ce2dc1e5 100644 --- a/homeassistant/components/image/__init__.py +++ b/homeassistant/components/image/__init__.py @@ -27,7 +27,7 @@ from homeassistant.helpers.entity import Entity, EntityDescription from homeassistant.helpers.entity_component import EntityComponent from homeassistant.helpers.event import async_track_time_interval from homeassistant.helpers.httpx_client import get_async_client -from homeassistant.helpers.typing import ConfigType +from homeassistant.helpers.typing import UNDEFINED, ConfigType, UndefinedType from .const import DOMAIN, IMAGE_TIMEOUT # noqa: F401 @@ -130,8 +130,10 @@ class ImageEntity(Entity): # Entity Properties _attr_content_type: str = DEFAULT_CONTENT_TYPE _attr_image_last_updated: datetime | None = None + _attr_image_url: str | None | UndefinedType = UNDEFINED _attr_should_poll: bool = False # No need to poll image entities _attr_state: None = None # State is determined by last_updated + _cached_image: Image | None = None def __init__(self, hass: HomeAssistant, verify_ssl: bool = False) -> None: """Initialize an image entity.""" @@ -156,6 +158,11 @@ class ImageEntity(Entity): """The time when the image was last updated.""" return self._attr_image_last_updated + @property + def image_url(self) -> str | None | UndefinedType: + """Return URL of image.""" + return self._attr_image_url + def image(self) -> bytes | None: """Return bytes of image.""" raise NotImplementedError() @@ -186,24 +193,16 @@ class ImageEntity(Entity): ) return None - if (url := await self.async_image_url()) is not None: - # Ignore an empty url - if url == "": - return None - if (image := await _async_load_image_from_url(url)) is None: + if self._cached_image: + return self._cached_image.content + if (url := self.image_url) is not UNDEFINED: + if not url or (image := await _async_load_image_from_url(url)) is None: return None + self._cached_image = image self._attr_content_type = image.content_type return image.content return await self.hass.async_add_executor_job(self.image) - def image_url(self) -> str | None: - """Return URL of image.""" - return None - - async def async_image_url(self) -> str | None: - """Return URL of image.""" - return self.image_url() - @property @final def state(self) -> str | None: diff --git a/tests/components/image/conftest.py b/tests/components/image/conftest.py index 03ef6d03f59..6c9deea852f 100644 --- a/tests/components/image/conftest.py +++ b/tests/components/image/conftest.py @@ -54,16 +54,13 @@ class MockImageEntityInvalidContentType(image.ImageEntity): class MockURLImageEntity(image.ImageEntity): """Mock image entity.""" + _attr_image_url = "https://example.com/myimage.jpg" _attr_name = "Test" async def async_added_to_hass(self): """Set the update time.""" self._attr_image_last_updated = dt_util.utcnow() - async def async_image_url(self) -> str: - """Return URL of image.""" - return "https://example.com/myimage.jpg" - class MockImageNoStateEntity(image.ImageEntity): """Mock image entity."""