Source code for poppy.core.generic.metaclasses

#!/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)