Source code for orion.core.utils.singleton

# -*- coding: utf-8 -*-
Singleton helpers and boilerplate

from abc import ABCMeta

from orion.core.utils import Factory

[docs]class SingletonAlreadyInstantiatedError(ValueError): """Exception to be raised when someone provides arguments to build an object from a already-instantiated `SingletonType` class. """ def __init__(self, name): """Pass the same constant message to ValueError underneath.""" super().__init__( "A singleton instance of (type: {}) has already been instantiated.".format( name ) )
[docs]class SingletonNotInstantiatedError(TypeError): """Exception to be raised when someone try to access an instance of a singleton that has not been instantiated yet """ def __init__(self, name): """Pass the same constant message to TypeError underneath.""" super().__init__("No singleton instance of (type: {}) was created".format(name))
[docs]class SingletonType(type): """Metaclass that implements the singleton pattern for a Python class.""" def __init__(cls, name, bases, dictionary): """Create a class instance variable and initiate it to None object.""" super(SingletonType, cls).__init__(name, bases, dictionary) cls.instance = None def __call__(cls, *args, **kwargs): """Create an object if does not already exist, otherwise return what there is.""" if cls.instance is None: try: cls.instance = super(SingletonType, cls).__call__(*args, **kwargs) except TypeError as exception: raise SingletonNotInstantiatedError(cls.__name__) from exception elif args or kwargs: raise SingletonAlreadyInstantiatedError(cls.__name__) return cls.instance
[docs]class AbstractSingletonType(SingletonType, ABCMeta): """This will create singleton base classes, that need to be subclassed and implemented.""" pass
[docs]class SingletonFactory(AbstractSingletonType, Factory): """Wrapping `orion.core.utils.Factory` with `SingletonType`. Keep compatibility with `AbstractSingletonType`.""" pass
[docs]def update_singletons(values=None): """Replace singletons by given values and return previous singleton objects""" if values is None: values = {} # Avoiding circular import problems when importing this module. from import Database from import EphemeralDB from import MongoDB from import PickledDB from import Storage from import Legacy from import Track singletons = (Storage, Legacy, Database, MongoDB, PickledDB, EphemeralDB, Track) updated_singletons = {} for singleton in singletons: updated_singletons[singleton] = singleton.instance singleton.instance = values.get(singleton, None) return updated_singletons