ZCML really doesn't bother me much. However, I've heard from a good number of people that it drives them absolutely nuts. I can understand the allergy in the context of Zope, because it has about a zillion obscure directives. That said, I'm not sure that putting configuration for bfg in Python is any better than using ZCML, because there just isn't very much ZCML configuration in bfg.
However, in the interest in being nice to the ZCML-allergic (although it does feel a little like pandering), it was extremely simple to create a package named repoze.bfg.convention which makes most ZCML usage optional in repoze.bfg . repoze.bfg.convention uses the very nice martian package to do all of the dirty work. From the package's docs:
repoze.bfg.convention
=============
``repoze.bfg.convention`` allows developers to make application
registry registrations within their application's Python instead of
using ZCML for the same purpose.
To make use of any convention declarations, you must insert the
following boilerplate into your application's ``configure.zcml``::
<bfg:convention package="."/>
After you do so, you will not need to use any other ZCML to configure
most ``repoze.bfg`` application registry directives in your
application. Instead, you will use decorators to do this work.
Note that this package tends to slows down application startup, as the
application registry is not capable of being cached within a
``.cache`` file when this package is in use, and more work is
performed at startup to scan for registrations.
``bfg_view`` Declaration Decorator
----------------------------------
``repoze.bfg.convention.bfg_view`` is a decorator which allows Python
code to make view registrations instead of using ZCML for the same
purpose.
E.g. in a bfg application module ``views.py``::
from models import IMyModel
from repoze.bfg.interfaces import IRequest
from repoze.bfg.convention import bfg_view
@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')
Using this decorator as above replaces the need to add this ZCML to
your application registry::
<bfg:view
for='.models.IMyModel'
view='.views.my_view'
name='my_view'
permission='read'
/>
Note that using this single decorator directive essentially allows you to avoid writing more than four or five lines of ZCML in any repoze.bfg application, because, well... that's all there is to configure in bfg. You basically just configure views. There is one other bfg-specific directive which is not covered here: a security policy directive. I have not provided a way to configure a BFG security policy via Python, because configuring a security policy for your application via ZCML (once, for the entire lifetime of the app, cut and pasted from the docs, using two lines of XML) is hopefully something any reasonable person would agree is tolerable.
So there ya go.