import inspect import logging from typing import Any, TypeVar from app.library.Singleton import Singleton T = TypeVar("T") LOG: logging.Logger = logging.getLogger(__name__) class Services(metaclass=Singleton): _dct: dict[str, T] = {} _instance = None """The instance of the class.""" @staticmethod def get_instance() -> "Services": if Services._instance is None: Services._instance = Services() return Services._instance def add(self, name: str, service: T): self._dct[name] = service def add_all(self, services: dict[str, T]): for name, service in services.items(): self.add(name, service) def get(self, name: str) -> T | None: return self._dct.get(name) def has(self, name: str) -> bool: return name in self._dct def remove(self, name: str): if name not in self._dct: return self._dct.pop(name, None) def clear(self): self._dct.clear() def get_all(self) -> dict[str, T]: return self._dct.copy() async def handle_async(self, handler: callable, **kwargs) -> Any: context = {**self.get_all(), **kwargs} sig = inspect.signature(handler) expected_args = sig.parameters.keys() filtered = {k: v for k, v in context.items() if k in expected_args} if missing_args := expected_args - filtered.keys(): LOG.error(f"Missing arguments for handler '{handler.__name__}': {missing_args}") return await handler(**filtered) def handle_sync(self, handler: callable, **kwargs) -> Any: context = {**self.get_all(), **kwargs} sig = inspect.signature(handler) expected_args = sig.parameters.keys() filtered = {k: v for k, v in context.items() if k in expected_args} if missing_args := expected_args - filtered.keys(): LOG.error(f"Missing arguments for handler '{handler.__name__}': {missing_args}") return handler(**filtered)