|
from typing import Type, TypeVar |
|
|
|
class SingletonMetaclass(type): |
|
T = TypeVar("T", bound="SingletonMetaclass") |
|
_instances = {} |
|
|
|
def __call__(cls, *args, **kwargs): |
|
if cls not in cls._instances: |
|
cls._instances[cls] = super(SingletonMetaclass, cls).__call__( |
|
*args, **kwargs |
|
) |
|
return cls._instances[cls] |
|
|
|
def inject_instance(cls: Type[T], instance: T) -> None: |
|
assert cls not in SingletonMetaclass._instances, ( |
|
"Cannot inject instance after first instantiation" |
|
) |
|
SingletonMetaclass._instances[cls] = instance |
|
|
|
def get_instance(cls: Type[T], *args, **kwargs) -> T: |
|
""" |
|
Gets the singleton instance of the class, creating it if it doesn't exist. |
|
""" |
|
if cls not in SingletonMetaclass._instances: |
|
SingletonMetaclass._instances[cls] = super( |
|
SingletonMetaclass, cls |
|
).__call__(*args, **kwargs) |
|
return cls._instances[cls] |
|
|
|
|
|
class ProxiedSingleton(object, metaclass=SingletonMetaclass): |
|
def __init__(self): |
|
super().__init__() |
|
|