#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from .manager import Manager
__all__ = [
"Singleton", "SingletonManager", "ManagerMeta"
]
[docs]class Singleton(type):
"""
A metaclass to create singletons, i.e classes that can have at most only
one instance created at a given time.
"""
def __call__(cls, *args, **kwargs):
"""
Check that an instance is already stored before creating a new one.
"""
if hasattr(cls, "instance"):
return cls.instance
cls.instance = super(Singleton, cls).__call__(*args, **kwargs)
return cls.instance
[docs]class ManagerMeta(type):
"""
A metaclass to allow simple managing of instances.
"""
def __new__(cls, name, bases, attr, **kwargs):
"""
Overridden to remove the keyword arguments coming from the class
definition, after the metaclass keyword. They can be retrieved as
keyword arguments in the metaclass provided for the class construction,
but the default metaclass (type) doesn't handle keyword arguments, so
we need to remove them before sending it to type.
"""
return super(ManagerMeta, cls).__new__(cls, name, bases, attr)
def __init__(
cls,
name,
bases,
attr,
manager=Manager,
after_creation=lambda x, y: None,
):
"""
To initiate the manager of connectors.
"""
# init the class as usual
super(ManagerMeta, cls).__init__(name, bases, attr)
# add a manager of the connectors
if not hasattr(cls, "manager"):
# check if a manager is given at the construction of the class
cls.manager = manager()
return
# do something after the class creation
after_creation(cls, name)
# also add the class to the manager
cls.manager.add(name, cls)
def __call__(cls, *args, **kwargs):
"""
Register the database when the instance of the database is created.
"""
# create the instance
instance = super(ManagerMeta, cls).__call__(*args, **kwargs)
# register the database
cls.manager.create(instance)
return instance
[docs]class SingletonManager(ManagerMeta):
"""
Metaclass to manage instances created with a given name as singletons.
"""
def __call__(cls, name, *args, **kwargs):
"""
Check instance already created, else create one and register.
"""
# check if the instance already exists
if name in cls.manager:
return cls.manager[name]
# create the instance as usual and register it
return super(SingletonManager, cls).__call__(
name,
*args,
**kwargs
)
def __iter__(cls):
return iter(cls.manager)