From 7aa7fd566d3e138e3a644bd51ccdc3aa445869d5 Mon Sep 17 00:00:00 2001 From: Chris Withers Date: Mon, 7 Jun 2010 15:56:35 +0000 Subject: A documented example of using Venusian to add your own decorator. --- docs/narr/hooks.rst | 83 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) (limited to 'docs') diff --git a/docs/narr/hooks.rst b/docs/narr/hooks.rst index 678b9dbc3..97f68ab25 100644 --- a/docs/narr/hooks.rst +++ b/docs/narr/hooks.rst @@ -336,3 +336,86 @@ class :class:`repoze.bfg.traversal.TraversalContextURL` in the `traversal module `_ of the :term:`Repoze` Subversion repository. + +Registering your own decorators +------------------------------- + +The decorators provided by :mod:`repoze.bfg`, such as +:class:`~repoze.bfg.view.bfg_view`, neither molest the +functions or classes they're decorating nor cause any side effects +to happen until a :term:`scan` is performed. + +You may wish to have your own decorators that exhibit such +behaviour. This is possible by using the :term:`Venusian` package in +the same way that is used by :mod:`repoze.bfg`. + +For example, suppose you wanted to write a decorator that registered a +particular function with a :term:`Zope Component Architecture` +utility. Such a utility is likely only to be available once your +application's configuration is at least partially completed. A normal +decorator would fail as it would be executed before the +configuration had even begun. + +However, using :term:`Venusian`, the decorator could be written as +follows: + +.. code-block:: python + :linenos: + + import venusian + from zope.component import getSiteManager + + class registerFunction(object): + + def __init__(self,path): + self.path = path + + def register(self,scanner,name,wrapped): + getSiteManager().getUtility(ISomething).register( + self.path,wrapped + ) + + def __call__(self,wrapped): + venusian.attach(wrapped,self.register) + return wrapped + +This decorator could then be used to register functions throughout +your code: + +.. code-block:: python + :linenos: + + @registerFunction('/some/path') + def my_function(): + do_stuff() + +However, the utility would only be used when a :term:`scan` was +performed, enabling you to set up the utility in advance: + +.. code-block:: python + :linenos: + + from paste.httpserver import serve + from repoze.bfg.configuration import Configurator + + class UtilityImplementation: + + implements(ISomething) + + def __init__(self): + self.registrations = {} + + def register(self,path,callable_): + self.registrations[path]=callable_ + + if __name__ == '__main__': + config = Configurator() + config.begin() + config.registry.registerUtility(UtilityImplementation()) + config.scan() + config.end() + app = config.make_wsgi_app() + serve(app, host='0.0.0.0') + +For full details, please read the `Venusian documentations +`__. -- cgit v1.2.3