From 6beb56cd9101761c41615d6c8c3c64ef0327d52e Mon Sep 17 00:00:00 2001 From: glrs <5999366+glrs@users.noreply.github.com> Date: Thu, 5 Dec 2024 13:58:45 +0100 Subject: [PATCH] Introduce `SingletonMeta` metaclass and refactor singleton decorator to a metaclass instead of a function decorator --- lib/core_utils/singleton_decorator.py | 41 ++++++++++++++++++--------- 1 file changed, 27 insertions(+), 14 deletions(-) diff --git a/lib/core_utils/singleton_decorator.py b/lib/core_utils/singleton_decorator.py index 7b89733..475e8f2 100644 --- a/lib/core_utils/singleton_decorator.py +++ b/lib/core_utils/singleton_decorator.py @@ -1,25 +1,38 @@ -from typing import Any, Callable, Dict, Type, TypeVar +from typing import Any, Dict, Type -T = TypeVar("T") +class SingletonMeta(type): + """ + A metaclass that creates a singleton instance of a class. + """ + + _instances: Dict[type, Any] = {} -def singleton(cls: Type[T]) -> Callable[..., T]: - """Decorator to make a class a singleton. + def __call__(cls, *args: Any, **kwargs: Any) -> Any: + if cls not in cls._instances: + cls._instances[cls] = super().__call__(*args, **kwargs) + return cls._instances[cls] - Ensures that only one instance of the class is created. Subsequent - calls to the class will return the same instance. + +def singleton(cls: Type[Any]) -> Type[Any]: + """ + Decorator to make a class a singleton by setting its metaclass to SingletonMeta. Args: - cls (Type[T]): The class to be decorated. + cls (Type[Any]): The class to be decorated. Returns: - Callable[..., T]: A function that returns the singleton instance of the class. + Type[Any]: The singleton class with SingletonMeta as its metaclass. """ - instances: Dict[Type[T], T] = {} - def get_instance(*args: Any, **kwargs: Any) -> T: - if cls not in instances: - instances[cls] = cls(*args, **kwargs) - return instances[cls] + # Create a new class with SingletonMeta as its metaclass + class SingletonClass(cls, metaclass=SingletonMeta): + pass + + # Preserve class metadata + SingletonClass.__name__ = cls.__name__ + SingletonClass.__doc__ = cls.__doc__ + SingletonClass.__module__ = cls.__module__ + SingletonClass.__annotations__ = getattr(cls, "__annotations__", {}) - return get_instance + return SingletonClass