:mod:`repoze.bfg` TODOs
|
=======================
|
|
- Supply ``X-Vhm-Host`` support.
|
|
- Basic WSGI documentation (pipeline / app / server).
|
|
- Provide a webob.Response class facade for forward compat.
|
|
- Fix message catalog extraction / compilation documentation.
|
|
- Change docs about creating a venusian decorator to not use ZCA.
|
|
- Add a ``susbcriber`` decorator and docs.
|
|
- ``decorator=`` parameter to bfg_view.
|
|
Renderer overhaul
|
------------------
|
|
Currently the division of responsibility between the BFG configurator
|
and a BFG renderer implementation is awkward and wrong.
|
|
- Renderer factories have no ability to convert a raw ``renderer=``
|
path (e.g. ``templates/foo.pt```) into something internally
|
meaningful. Instead, BFG mangles the string into a package-relative
|
spec before it is passed to the renderer factory. This is wrong, as
|
some renderers may not be interested in package-relative specs at
|
all (for instance, loader-style renderers which have a hardcoded set
|
of template locations). The reason, however, that BFG currently
|
does it this way is that the raw renderer path alone does not
|
contain enough information itself to be useful; knowledge of the
|
*package* is also required for package-based renderers to make sense
|
of relative renderer strings (e.g. ``templates/foo.pt`` could mean
|
the ``templates/foo.pt`` file within the ``mypackage`` package).
|
|
To fix this, we need to provide some way to pass the package name to
|
the renderer factory as well as the renderer path. But the package
|
name isn't the only thing an *arbitrary* renderer might need.
|
Another renderer might need, for example, a deployment setting. So
|
we'll need to identify all the crap that *might* be useful to a
|
renderer factory and we'll need to pass all of it into the renderer
|
factory as a garbage barge dictionary; individual renderers will
|
make use of whatever they can from that garbage barge dictionary.
|
Garbage barge dict item candidates: ``package`` (the "current"
|
package), ``config`` (the configurator), ``package_name`` (the
|
current package's ``__name__``), ``settings`` (the deployment
|
settings), ``registry`` (the component registry).
|
|
- A BFG renderer currently returns a *string*. It would be more
|
symmetric if a renderer always returned a Response object. Then the
|
calling machinery inside BFG could treat a view which happened to
|
use a renderer exactly the same as a view which returns a response
|
directly. Maybe. Problem: varying response attributes such as
|
``content-type``, etc only makes sense when the view callable uses a
|
renderer; not when it doesn't, so there's some asymmetry there.
|
Maybe we make renderers return Responses, but still keep the
|
attribute-inspection stuff inside BFG, only used when we call a view
|
which we know uses a renderer. We *could* always call the attribute
|
inspection stuff, but it would be a slowdown in cases where views
|
really do always return a Response directly.
|
|
- The ``system`` value passed to a renderer is not extensible. It
|
should be extensible on a per-application basis. For example, you
|
might want to add a top-level variable ``c`` to the values passed to
|
all renderers representing a template context to emulate Pylons.
|
|
- ``repoze.bfg.chameleon_zpt.render_template_to_response``, et. al. do
|
not use the same machinery as view renderers. It would be useful if
|
templates rendered with ``render_template_to_response`` had the same
|
``system`` values available to it as templates renderered via a view
|
renderer.
|
|
To at least partially ameliorate the above, renderer factories should
|
be changed to things that have a set of interfaces something like
|
this::
|
|
class IRendererFactory(Interface):
|
def __call__(path, info):
|
"" Return an IRenderer."""
|
|
class IRenderer(Interface):
|
def __call__(value, system):
|
""" Return a Response """
|
|
A semi-pseudocode example:
|
|
from webob import Response
|
|
class SampleRendererFactory(object):
|
def __init__(self, **config):
|
self.config = config
|
|
def __call__(self, path, info):
|
path = do_something_to_evaluate_path_using_info(path, info)
|
search_path = self.config['search_path']
|
debug = self.config['debug']
|
def renderer(value, system):
|
string = do_rendering(search_path, debug, path, value, system)
|
return Response(string)
|
return renderer
|
|
if __name__ == '__main__':
|
|
def view1(request):
|
return {'a':1}
|
|
def view2(request):
|
return {'a':2}
|
|
renderer_factory = SampleRendererFactory(search_path=['/a', '/b'])
|
|
package_name = 'some.package'
|
|
for view, path in [
|
(view1, 'templates/foo.pt'),
|
(view2, 'templates/bar.pt'),
|
]:
|
renderer = renderer_factory(path, dict(package_name=package_name))
|
register_renderer_for_view(renderer, view)
|
|
This is mostly an amelioration for the first and second bullet points
|
above. The second two bullet points are not addressed by it.
|
|
Also: think about generalizing this a bit into something which wraps a
|
view callable like a decorator, which can influence input and output.
|