|
|
@@ -2,9 +2,9 @@ import asyncio
|
|
|
import logging
|
|
|
from datetime import date
|
|
|
|
|
|
-from ._airbnb import _AirbnbClient
|
|
|
-from ._booking import _BookingClient
|
|
|
+from . import _airbnb, _booking # noqa: F401 — import registers each client via @register_service
|
|
|
from ._protocols import ChatClient, ServiceClient
|
|
|
+from ._registry import client_classes
|
|
|
from .types import DayInfo, ServiceAuthError
|
|
|
|
|
|
_log = logging.getLogger(__name__)
|
|
|
@@ -21,11 +21,6 @@ class ServiceAPI:
|
|
|
Pass a custom `clients` dict to substitute stubs for testing.
|
|
|
"""
|
|
|
|
|
|
- _CLIENT_CLASSES: dict[str, type] = {
|
|
|
- 'airbnb': _AirbnbClient,
|
|
|
- 'booking': _BookingClient,
|
|
|
- }
|
|
|
-
|
|
|
@classmethod
|
|
|
def get(cls) -> 'ServiceAPI':
|
|
|
"""Return the process-wide singleton, creating it on first call."""
|
|
|
@@ -47,7 +42,7 @@ class ServiceAPI:
|
|
|
return
|
|
|
self._clients = {}
|
|
|
self._disabled: dict[str, str] = {}
|
|
|
- for key, cls in self._CLIENT_CLASSES.items():
|
|
|
+ for key, cls in client_classes().items():
|
|
|
try:
|
|
|
self._clients[key] = cls.from_env()
|
|
|
except Exception as e:
|
|
|
@@ -60,13 +55,13 @@ class ServiceAPI:
|
|
|
|
|
|
def service_name(self, key: str) -> str:
|
|
|
"""Return the human-readable display name for a service key."""
|
|
|
- cls = self._CLIENT_CLASSES.get(key)
|
|
|
+ cls = client_classes().get(key)
|
|
|
return getattr(cls, 'service_name', key.capitalize()) if cls else key.capitalize()
|
|
|
|
|
|
|
|
|
async def refresh_credentials(self, key: str) -> None:
|
|
|
"""Trigger credential refresh for the named service. Raises ServiceAuthError on failure."""
|
|
|
- cls = self._CLIENT_CLASSES.get(key)
|
|
|
+ cls = client_classes().get(key)
|
|
|
if cls is None or not hasattr(cls, 'refresh_credentials'):
|
|
|
from .types import ServiceAuthError
|
|
|
raise ServiceAuthError(f'No automatic refresh handler for service: {key}')
|
|
|
@@ -84,7 +79,7 @@ class ServiceAPI:
|
|
|
if client is not None and hasattr(client, '_reload_from_env'):
|
|
|
client._reload_from_env()
|
|
|
return
|
|
|
- cls = self._CLIENT_CLASSES.get(key)
|
|
|
+ cls = client_classes().get(key)
|
|
|
if cls is None:
|
|
|
return
|
|
|
try:
|