Source code for sdt.helper.singleton

# SPDX-FileCopyrightText: 2013 Yu Yang <reyoung@126.com>
# SPDX-FileCopyrightText: 2020 Lukas Schrangl <lukas.schrangl@tuwien.ac.at>
#
# SPDX-License-Identifier: BSD-3-Clause
# SPDX-License-Identifier: MIT
#
# Based on https://github.com/reyoung/singleton (MIT licensed), adapted under
# BSD-3-Clause as part of the sdt-python package

"""Create singleton classes"""
from threading import RLock


[docs]class Singleton: """Class decorator to create singleton objects Based on https://github.com/reyoung/singleton (released under MIT license). Examples -------- >>> @Singleton ... class Example: ... def __init__(self): ... self.x = 1 >>> Example.instance <__main__.Example object at 0x7fe65a904a20> """ def __init__(self, cls): """Parameters ---------- cls : class Decorator class type """ self.__cls = cls self.__instance = None
[docs] def initialize(self, *args, **kwargs): """Initialize singleton object if it has not been initialized Parameters ---------- *args, **kwargs Passed to the singleton object's ``__init__()`` """ if not self.is_initialized: self.__instance = self.__cls(*args, **kwargs)
@property def is_initialized(self): """True if :py:attr:`instance` is initialized""" return self.__instance is not None @property def instance(self): """Singleton instance""" if not self.is_initialized: self.initialize() return self.__instance def __call__(self, *args, **kwargs): """Disable new instance of original class Raises ====== TypeError There can only be one instance. """ raise TypeError("Singletons must be accessed by instance") def __instancecheck__(self, inst): return isinstance(inst, self.__cls)
[docs]class ThreadSafeSingleton(object): """Thread-safe version of the :py:class:`Singleton` class decorator""" def __init__(self, cls): """Parameters ---------- cls : class Decorator class type """ self.__cls = cls self.__instance = None self.__mutex = RLock()
[docs] def initialize(self, *args, **kwargs): """Initialize singleton object if it has not been initialized Parameters ---------- *args, **kwargs Passed to the singleton object's ``__init__()`` """ with self.__mutex: if not self.is_initialized: self.__instance = self.__cls(*args, **kwargs)
@property def is_initialized(self): """True if :py:attr:`instance` is initialized""" with self.__mutex: return self.__instance is not None @property def instance(self): """Singleton instance""" with self.__mutex: if not self.is_initialized: self.initialize() return self.__instance def __call__(self, *args, **kwargs): """Disable new instance of original class Raises ====== TypeError There can only be one instance. """ raise TypeError("Singletons must be accessed by instance") def __instancecheck__(self, inst): return isinstance(inst, self.__cls)