feat(easel): add api provider

This commit is contained in:
2026-06-17 21:15:01 +03:00
parent 657a62eab5
commit e37ca6eeac
12 changed files with 124 additions and 53 deletions

View File

@@ -2,8 +2,13 @@ from typing import TypeVar
class Api:
TYPE: str
PROVIDER: str
@property
def type(self) -> str:
return self.TYPE
@property
def provider(self) -> str:
return self.PROVIDER

View File

@@ -3,26 +3,27 @@ from .schedule.api import ScheduleApi
from .weather.api import WeatherApi
class ApiBundle(list[Api]):
def __init__(self, values: list[Api]) -> None:
super().__init__(values)
class ApiBundle:
def __init__(self, values: list[Api]):
self._values = values
self._by_provider = {value.provider: value for value in values}
def get_api_by_provider(self, provider: str) -> Api:
for value in self:
if value.PROVIDER == provider:
return value
raise ValueError(provider)
def get_api_providers(self, api_type: str) -> list[str]:
result = []
for value in self._values:
if value.type == api_type:
result.append(value.provider)
return result
def get_api_by_type(self, api_type: type[API]) -> API:
for value in self:
def get_api(self, api_type: type[API], provider: str | None = None) -> API:
for value in self._values:
if isinstance(value, api_type):
return value
if provider is None or provider == value.provider:
return value
raise ValueError(api_type)
@property
def weather(self) -> WeatherApi:
return self.get_api_by_type(WeatherApi)
def get_weather(self, provider: str | None = None) -> WeatherApi:
return self.get_api(WeatherApi, provider)
@property
def schedule(self) -> ScheduleApi:
return self.get_api_by_type(ScheduleApi)
def get_schedule(self, provider: str | None = None) -> ScheduleApi:
return self.get_api(ScheduleApi, provider)

View File

@@ -6,6 +6,7 @@ from .model import ChannelId, Schedule
class ScheduleApi(Api):
TYPE = "schedule"
INTERVAL: float = 0.5
async def get_channels(self) -> list[ChannelId]:

View File

@@ -12,7 +12,7 @@ CACHE_PRESET = CachePreset(ttl=TimeUnit.HOUR * 6)
class CachedScheduleApi(ScheduleApi, CachedApi[ScheduleApi]):
CACHE_KEY = "schedule"
CACHE_KEY = ScheduleApi.TYPE
@cached(
key_builder=lambda fun, self: f"api.{self.CACHE_KEY}.{self.provider}.channels",

View File

@@ -5,6 +5,7 @@ from .model import Location, WeatherResponse
class WeatherApi(Api):
TYPE = "weather"
async def find_locations(self, query: str) -> list[Location]:
raise NotImplementedError

View File

@@ -11,7 +11,7 @@ CACHE_PRESET = DEFAULT_CACHE_PRESET
class CachedWeatherApi(WeatherApi, CachedApi[WeatherApi]):
CACHE_KEY = "weather"
CACHE_KEY = WeatherApi.TYPE
@cached(
key_builder=lambda fun, self, query: f"api.{self.CACHE_KEY}.{self.provider}.locations.{query}",