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): def __init__(self): self._services: dict[str, T] = {} @staticmethod def get_instance() -> "Services": return Services() def add(self, name: str, service: T): self._services[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._services.get(name) def has(self, name: str) -> bool: return name in self._services def remove(self, name: str): if name not in self._services: return self._services.pop(name, None) def clear(self): self._services.clear() def get_all(self) -> dict[str, T]: return self._services.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)