Source code for Cauldron.registry

# -*- coding: utf-8 -*-
"""
A registry of setup and teardown functions for dispatchers and clients.
"""

import collections
from .compat import WeakOrderedSet
from .utils.helpers import _inherited_docstring

__all__ = ['client', 'dispatcher', 'keys', 'teardown', 'Registry']

[docs]class Registry(object): """A registry of setup and teardown functions. This module contains two :class:`Registry` instances: ``client`` and ``dispatcher``. They serve as the setup and teardown registries for the KTL client and disptachetr side APIs. Additional setup or teardown functions can be registered using :meth:`setup_for` and :meth:`teardown_for`. The base keyword and service classes for a particular backend can be set using :meth:`keyword_for` and :meth:`service_for`. All of these methods are decorators and can be used as such in the appropriate places:: from Cauldron import registry @regsitry.client.setup_for("mybackend") def mysetup(): # Do some setup work here! pass """ def __init__(self, name, doc=None, modname="Cauldron.DFW"): super(Registry, self).__init__() self.name = name self._setup = collections.defaultdict(WeakOrderedSet) self._teardown = collections.defaultdict(WeakOrderedSet) self._keyword = {} self._service = {} self._backend = None self._modname = modname self._service_cls = None self._keyword_cls = None if doc is not None: self.__doc__ = doc @property def backend(self): """Get the backend name.""" return self._backend
[docs] def keys(self): """Return the active and available registry keys.""" return list(set(self._keyword.keys()).union(self._service.keys()))
[docs] def guard(self, msg, error=RuntimeError): """Guard against backends that aren't set up.""" if self._backend is None: raise error("The backend must be set before {0}. Call Cauldron.api.use('backend') to set the backend.".format(msg))
def _insert_setup(self, func, backend='all'): """Add a setup function for a particual backend.""" self._setup[backend].add(func) def _insert_teardown(self, func, backend='all'): """Insert a teardown.""" self._teardown[backend].add(func)
[docs] def use(self, backend): """Set the backend.""" if self._backend is not None: raise RuntimeError("The backend cannot be set twice. It is already '{0}'.".format(self._backend)) self._backend = backend
@property def Keyword(self): """The Keyword class.""" self.guard("accessing the Keyword class") if self._keyword_cls is None: cls = self._keyword[self._backend] self._keyword_cls = type('Keyword', (cls,), {'__module__':'{0}.Keyword'.format(self._modname)}) return self._keyword[self._backend] @property def Service(self): """The Service class.""" self.guard("accessing the Service class") if self._service_cls is None: cls = self._service[self._backend] self._service_cls = type('Service', (cls,), {'__module__':'{0}.Service'.format(self._modname)}) return self._service_cls
[docs] def keyword_for(self, backend, keyword=None): """Register a keyword class.""" def _decorate(class_): if backend in self._keyword: raise KeyError("Cannot register multiple Keyword classes for backend '{0}'".format(backend)) self._keyword[backend] = class_ return class_ if keyword is None: return _decorate return _decorate(keyword)
[docs] def service_for(self, backend, service=None): """Register a service""" def _decorate(class_): if backend in self._service: raise KeyError("Cannot register multiple Service classes for backend '{0}'".format(backend)) self._service[backend] = class_ return class_ if service is None: return _decorate return _decorate(service)
[docs] def setup_for(self, backend): """Register a setup function.""" def _decorate(func): self._insert_setup(func, backend) return func if callable(backend): self._insert_setup(backend, 'all') return backend return _decorate
[docs] def teardown_for(self, backend): """Register a teardown function.""" def _decorate(func): self._insert_teardown(func, backend) return func if callable(backend): self._insert_teardown(backend, 'all') return backend return _decorate
[docs] def setup(self): """Do the setup process.""" self.guard("calling the setup functions") for func in self._setup['all']: func() for func in self._setup[self._backend]: func()
[docs] def teardown(self): """Do the teardown process.""" for func in self._teardown['all']: func() if self._backend is None: return for func in self._teardown[self._backend]: func() self._backend = None self._service_cls = None self._keyword_cls = None
client = Registry("client", doc="A registry of setup and teardown functions to support the KTL client interface.", modname="Cauldron.ktl") dispatcher = Registry("dispatcher", doc="A registry of setup and teardown functions to support the KTL dispatcher interface.", modname="Cauldron.DFW")
[docs]def keys(): """Keys available in both registries.""" return list(set(client.keys()).union(dispatcher.keys()))
[docs]def teardown(): """Teardown both the client and dispatcher.""" client.teardown() dispatcher.teardown()