Source code for ska_ser_skallop.utils.singleton

"""This module provides a Singleton metaclass."""
from typing import Any, Union


[docs]class Singleton(type): """ A metaclass that ensures that only one instance exists. If you try to create an instance of a class based on this metaclass, and an instance has been created already, then the existing instance is returned. Usage: .. code-block:: python class TangoBridge(metaclass=Singleton) .... """ _instances = {} def __call__(cls: type["Singleton"], *args: Any, **kwargs: Any) -> "Singleton": """ Handle a call to this metaclass. Whereas a call would normally result in creation of a new instance (via calls to ``__new__`` and ``__init__``), here we first check if we have already previously created an instance, and return that instance if it exists. :param args: positional arguments to the call :param kwargs: keyword arguments to the call """ if cls not in cls._instances: cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs) return cls._instances[cls]
[docs]class Memo: """Singleton class that will store any given variables across multiple class instances. To store a value you can either provide it as an argument upon instantiation or with the set method. To retrieve a value you use a get method (returns None if value doesn't exist) e.g.: .. code-block:: python memo = Memo(foo='bar') assert memo.get('foo') == 'bar' # or alternatively memo.reset() # equal to creating a new instance with all values resetted. memo.set(foo='bar') assert memo.get('foo') == 'bar' """ _instance: Union["Memo", None] = None _skip_init = False def __new__(cls: type["Memo"], **kwargs) -> "Memo": if cls._instance: cls._instance.set(**kwargs) else: cls._instance = super(Memo, cls).__new__(cls) return cls._instance def __init__(self, **kwargs) -> None: if not self._skip_init: self._data = {**kwargs} self._skip_init = True
[docs] def reset(self) -> None: """Clears all stored values to None""" self._skip_init = False self.__init__()
[docs] def set(self, **kwargs) -> None: """Store a (or update) a set of given key/value pairs as given by the kwargs.""" self._data = {**self._data, **kwargs}
[docs] def get(self, key: Any) -> Union[None, Any]: """Return a stored value (if exists) for a given key. :param key: The key or id of the expected variable :return: The value of the key if exists, otherwise None """ return self._data.get(key)