Source code for pynion.metaclass.tones

from ..errors.mtce import BadMultitonIdentifier as BMI


[docs]class Singleton(type): """The **singleton pattern** is a design pattern that restricts the instantiation of a class to one object. This is useful when exactly one object is needed to coordinate actions across the system. As a metaclass, the pattern is applied to derived classes such as :: from pynion import Singleton class Foo(object): __metaclass__ = Singleton def __init__(self, bar): self.bar = bar Derived classes can become parents of other classes. Classes inherited from a ``__metaclass__ = Singleton`` are also Singleton. """ instance = {} def __call__(cls, *args, **kw): if cls not in cls.instance: cls.instance[cls] = super(Singleton, cls).__call__(*args, **kw) return cls.instance[cls]
[docs]class Multiton(type): """The **multiton pattern** is a design pattern similar to the singleton. The multiton pattern expands on the singleton concept to manage a map of named instances as key-value pairs. This means that rather than having a single instance per application the multiton pattern instead ensures a single instance per key. As a metaclass, the pattern is applied to derived classes through the :py:attr:`__metaclass__`. By default, the key attribute of the multiton is either: * the :py:meth:`__init__` named argument **name** or * the first argument of :py:meth:`__init__` if not named. The default named argument can be changed by adding the class attribute :py:const:`_IDENTIFIER` :: from pynion import Multiton class Foo(object): __metaclass__ = Multiton _IDENTIFIER = 'newID' # by default this will be 'name' def __init__(self, newID): self.id = newID Derived classes can become parents of other classes. Classes inherited from a ``__metaclass__ = Multiton`` are also Multiton, although their :py:const:`_IDENTIFIER` can be changed. """ instance = {} def __call__(cls, *args, **kw): try: idkey = cls._IDENTIFIER except AttributeError: idkey = 'name' if kw and idkey in kw: ident = kw[idkey] elif len(args) > 0: ident = args[0] else: raise BMI([idkey, cls.__name__]) if cls not in cls.instance: cls.instance.setdefault(cls, {}) if ident not in cls.instance[cls]: cls.instance[cls][ident] = super(Multiton, cls).__call__(*args, **kw) return cls.instance[cls][ident]