From 5a7f9a4d57424f14a1e072cc06b6bf7a191a7d08 Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Fri, 16 Jan 2009 18:58:16 +0000 Subject: Features -------- - The functionality of ``repoze.bfg.convention`` has been merged into the core. Applications which make use of ``repoze.bfg.convention`` will continue to work indefinitely, but it is recommended that apps stop depending upon it. To do so, substitute imports of ``repoze.bfg.convention.bfg_view`` with imports of ``repoze.bfg.view.bfg_view``, and change the stanza in ZCML from ```` to ````. As a result of the merge, bfg has grown a new dependency: ``martian``. - View functions which use the pushpage decorator are now pickleable (meaning their use won't prevent a ``configure.zcml.cache`` file from being written to disk). Implementation Changes ---------------------- - The ``wsgiapp`` decorator now uses ``webob.Request.get_response`` to do its work rather than relying on howgrown WSGI code. --- repoze/bfg/view.py | 89 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) (limited to 'repoze/bfg/view.py') diff --git a/repoze/bfg/view.py b/repoze/bfg/view.py index 3f9216b0d..f580a4fb1 100644 --- a/repoze/bfg/view.py +++ b/repoze/bfg/view.py @@ -12,6 +12,10 @@ from repoze.bfg.interfaces import IView from repoze.bfg.security import Unauthorized from repoze.bfg.security import Allowed +from zope.interface import Interface + +from repoze.bfg.interfaces import IRequest + _marker = () def view_execution_permitted(context, request, name=''): @@ -162,3 +166,88 @@ class static(object): response.headerlist = headers return response +class bfg_view(object): + """ Decorator which allows Python code to make view registrations + instead of using ZCML for the same purpose. + + E.g. in the module ``views.py``:: + + from models import IMyModel + from repoze.bfg.interfaces import IRequest + + @bfg_view(name='my_view', request_type=IRequest, for_=IMyModel, + permission='read')) + def my_view(context, request): + return render_template_to_response('templates/my.pt') + + Equates to the ZCML:: + + + + If ``name`` is not supplied, the empty string is used (implying + the default view). + + If ``request_type`` is not supplied, the interface + ``repoze.bfg.interfaces.IRequest`` is used. + + If ``for_`` is not supplied, the interface + ``zope.interface.Interface`` (implying *all* interfaces) is used. + + If ``permission`` is not supplied, no permission is registered for + this view (it's accessible by any caller). + + Any individual or all parameters can be omitted. The simplest + bfg_view declaration then becomes:: + + @bfg_view() + def my_view(...): + ... + + Such a registration implies that the view name will be + ``my_view``, registered for models with the + ``zope.interface.Interface`` interface, using no permission, + registered against requests which implement the default IRequest + interface. + + To make use of bfg_view declarations, insert the following + boilerplate into your application registry's ZCML:: + + + """ + def __init__(self, name='', request_type=IRequest, for_=Interface, + permission=None): + self.name = name + self.request_type = request_type + self.for_ = for_ + self.permission = permission + + def __call__(self, wrapped): + # We intentionally return a do-little un-functools-wrapped + # decorator here so as to make the decorated function + # unpickleable; applications which use bfg_view decorators + # should never be able to load actions from an actions cache; + # instead they should rerun the file_configure function each + # time the application starts in case any of the decorators + # has been changed. Disallowing these functions from being + # pickled enforces that. + def decorator(context, request): + return wrapped(context, request) + decorator.__is_bfg_view__ = True + decorator.__permission__ = self.permission + decorator.__for__ = self.for_ + decorator.__view_name__ = self.name + decorator.__request_type__ = self.request_type + # we assign to __grok_module__ here rather than __module__ to + # make it unpickleable but allow for the grokker to be able to + # find it + decorator.__grok_module__ = wrapped.__module__ + decorator.__name__ = wrapped.__name__ + decorator.__doc__ = wrapped.__doc__ + decorator.__dict__.update(wrapped.__dict__) + return decorator + -- cgit v1.2.3