diff --git a/custom_components/gismeteo/api.py b/custom_components/gismeteo/api.py index 213d1cb..8472655 100644 --- a/custom_components/gismeteo/api.py +++ b/custom_components/gismeteo/api.py @@ -205,9 +205,9 @@ async def _async_get_data( if self._cache and cache_fname is not None: cache_fname += ".xml" - if self._cache.is_cached(cache_fname): + if await self._cache.is_cached(cache_fname): _LOGGER.debug("Cached response used") - return self._cache.read_cache(cache_fname) + return await self._cache.read_cache(cache_fname) headers = {} if as_browser: @@ -220,7 +220,7 @@ async def _async_get_data( data = await resp.text() if self._cache and cache_fname is not None and data: - self._cache.save_cache(cache_fname, data) + await self._cache.save_cache(cache_fname, data) return data @@ -234,9 +234,13 @@ async def async_update_location(self) -> None: url = ( ENDPOINT_URL - + f"/cities/?lat={self._attributes[ATTR_LATITUDE]}&lng={self._attributes[ATTR_LONGITUDE]}&count=1&lang=en" + + f"/cities/?lat={self._attributes[ATTR_LATITUDE]}" + + f"&lng={self._attributes[ATTR_LONGITUDE]}&count=1&lang=en" + ) + cache_fname = ( + f"location_{self._attributes[ATTR_LATITUDE]}" + + f"_{self._attributes[ATTR_LONGITUDE]}" ) - cache_fname = f"location_{self._attributes[ATTR_LATITUDE]}_{self._attributes[ATTR_LONGITUDE]}" response = await self._async_get_data(url, cache_fname) try: diff --git a/custom_components/gismeteo/cache.py b/custom_components/gismeteo/cache.py index d8fbb8a..98acd53 100644 --- a/custom_components/gismeteo/cache.py +++ b/custom_components/gismeteo/cache.py @@ -7,7 +7,10 @@ import logging import os import time -from typing import Any, Dict, Optional +from typing import Any + +import aiofiles +from aiofiles import os as aio_os _LOGGER = logging.getLogger(__name__) @@ -15,7 +18,7 @@ class Cache: """Data caching class.""" - def __init__(self, params: Optional[Dict[str, Any]] = None): + def __init__(self, params: dict[str, Any] | None = None): """Initialize cache.""" _LOGGER.debug("Initializing cache") params = params or {} @@ -54,43 +57,47 @@ def _get_file_path(self, file_name: str) -> str: file_name = ".".join((self._domain, file_name)) return os.path.join(self._cache_dir, file_name) - def cached_for(self, file_name: str) -> Optional[float]: + async def cached_for(self, file_name: str) -> float | None: """Return caching time of file if exists. Otherwise None.""" file_path = self._get_file_path(file_name) - if not os.path.exists(file_path) or not os.path.isfile(file_path): + if not await aio_os.path.exists(file_path) or not await aio_os.path.isfile( + file_path + ): return None - file_time = os.path.getmtime(file_path) + file_time = await aio_os.path.getmtime(file_path) return time.time() - file_time - def is_cached(self, file_name: str, cache_time: int = 0) -> bool: + async def is_cached(self, file_name: str, cache_time: int = 0) -> bool: """Return True if cache file is exists.""" file_path = self._get_file_path(file_name) - if not os.path.exists(file_path) or not os.path.isfile(file_path): + if not await aio_os.path.exists(file_path) or not await aio_os.path.isfile( + file_path + ): return False - file_time = os.path.getmtime(file_path) + file_time = await aio_os.path.getmtime(file_path) cache_time = max(cache_time, self._cache_time) return (file_time + cache_time) > time.time() - def read_cache(self, file_name: str, cache_time: int = 0) -> Optional[Any]: + async def read_cache(self, file_name: str, cache_time: int = 0) -> Any | None: """Read cached data.""" file_path = self._get_file_path(file_name) _LOGGER.debug("Read cache file %s", file_path) - if not self.is_cached(file_name, cache_time): + if not await self.is_cached(file_name, cache_time): return None - with open(file_path, encoding="utf-8") as fp: - return fp.read() + async with aiofiles.open(file_path, encoding="utf-8") as fp: + return await fp.read() - def save_cache(self, file_name: str, content: Any) -> None: + async def save_cache(self, file_name: str, content: Any) -> None: """Save data to cache.""" if self._cache_dir: - if not os.path.exists(self._cache_dir): - os.makedirs(self._cache_dir) + if not await aio_os.path.exists(self._cache_dir): + await aio_os.makedirs(self._cache_dir) file_path = self._get_file_path(file_name) _LOGGER.debug("Store cache file %s", file_path) - with open(file_path, "w", encoding="utf-8") as fp: - fp.write(content) + async with aiofiles.open(file_path, "w", encoding="utf-8") as fp: + await fp.write(content) diff --git a/custom_components/gismeteo/manifest.json b/custom_components/gismeteo/manifest.json index 8681d68..ddb1fd5 100644 --- a/custom_components/gismeteo/manifest.json +++ b/custom_components/gismeteo/manifest.json @@ -12,7 +12,8 @@ "iot_class": "cloud_polling", "issue_tracker": "https://github.com/Limych/ha-gismeteo/issues", "requirements": [ - "beautifulsoup4~=4.12" + "beautifulsoup4~=4.12", + "aiofiles>=24.0.0" ], "version": "3.0.0" } \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index d709277..2dbc756 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,4 @@ homeassistant>=2024.4.0 pip>=24.0 beautifulsoup4~=4.12 +aiofiles>=24.0.0 diff --git a/tests/test_cache.py b/tests/test_cache.py index 2ae4dea..1ad9bb4 100644 --- a/tests/test_cache.py +++ b/tests/test_cache.py @@ -100,34 +100,34 @@ def test__get_file_path(): assert cache._get_file_path("file_name.ext") == "/some/dir/dmn.file_name.ext" -def test_is_cached(config, cache_dir): +async def test_is_cached(config, cache_dir): """Cache controller tests.""" config["clean_dir"] = False cache = Cache(config) for i in cache_dir["old"]: - assert cache.is_cached(i) is False + assert await cache.is_cached(i) is False for i in cache_dir["new"]: - assert cache.is_cached(i) is True + assert await cache.is_cached(i) is True for _ in range(8): file_name = os.urandom(3).hex() - assert cache.is_cached(file_name) is False + assert await cache.is_cached(file_name) is False -def test_read_cache(config, cache_dir): +async def test_read_cache(config, cache_dir): """Cache controller tests.""" cache = Cache(config) for i in cache_dir["old"]: - assert cache.read_cache(i) is None + assert await cache.read_cache(i) is None for i, con in cache_dir["new"].items(): - assert cache.read_cache(i) == con + assert await cache.read_cache(i) == con -def test_save_cache(config): +async def test_save_cache(config): """Cache controller tests.""" config["cache_dir"] = os.path.join(config["cache_dir"], os.urandom(3).hex()) cache = Cache(config) @@ -135,6 +135,6 @@ def test_save_cache(config): for _ in range(8): file_name = os.urandom(5).hex() content = os.urandom(7).hex() - cache.save_cache(file_name, content) + await cache.save_cache(file_name, content) - assert cache.read_cache(file_name) == content + assert await cache.read_cache(file_name) == content