"""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)