repoze.bfg Introduction

repoze.bfg is a Python web framework. It is inspired by Zope, Pylons, and Django. repoze.bfg uses the WSGI protocol to handle requests and responses.

Similarities to Other Frameworks

repoze.bfg was inspired by Zope, Pylons and Django.

The repoze.bfg concept of traversal is inspired by Zope. Additionally, repoze.bfg uses the Zope Component Architecture internally, as do Zope 2, Zope 3, and Grok. repoze.bfg application developers may use either ZCML (an XML dialect, used in Zope) or decorators to perform various application configuration tasks. The decorator support is provided by the Grok project. Like Zope, repoze.bfg allows you to create applications which do not need to be forked or otherwise modified to be extended by a third party developer.

The repoze.bfg concept of URL dispatch is inspired by Pylons. Like Pylons, repoze.bfg is mostly policy-free. It makes no assertions about which database you should use, and its built-in templating facilities are only for convenience. In essence, it only supplies a mechanism to map URLs to view code, along with a convention for calling those views. You are free to use third-party components in your application that fit your needs. Also like Pylons, repoze.bfg is dependent upon WSGI.

The Django docs state that Django is not an “MVC” (model/view/controller) framework in their FAQ. repoze.bfg isn’t either. Django’s documentation does a good job of why explaining why they don’t use “MVC” acronym:

Django appears to be a MVC framework, but you call the Controller the “view”, and the View the “template”. How come you don’t use the standard names?

Well, the standard names are debatable.

In our interpretation of MVC, the “view” describes the data that gets presented to the user. It’s not necessarily how the data looks, but which data is presented. The view describes which data you see, not how you see it. It’s a subtle distinction.

So, in our case, a “view” is the Python callback function for a particular URL, because that callback function describes which data is presented.

Furthermore, it’s sensible to separate content from presentation - which is where templates come in. In Django, a “view” describes which data is presented, but a view normally delegates to a template, which describes how the data is presented.

Where does the “controller” fit in, then? In Django’s case, it’s probably the framework itself: the machinery that sends a request to the appropriate view, according to the Django URL configuration.

repoze.bfg uses terminology similar to Django. The skeleton code generator of repoze.bfg generates a directory layout very similar to the directory layout suggested by the Django Book . Additionally, as suggested above, the concepts of view, model and template are used by repoze.bfg as they would be by Django.

Differences from Other Frameworks

Like Zope, the repoze.bfg framework imposes more control inversion upon application developers than other Python frameworks such as Pylons. For example repoze.bfg allows you to explicitly resolve a URL to a context object before invoking a view. Pylons and other Python “MVC” frameworks have no such intermediate step; they resolve a URL directly to a controller. Another example: using the repoze.bfg security subsystem assumes that you’re willing to attach an ACL to a context object; the ACL is checked by the framework itself instead of by user code, and access is permitted or denied by the framework itself rather than by user code. Such a task would typically be performed by user-space decorators in other Python web frameworks.

Like Zope, but unlike Pylons applications or most Django applications, when you build a repoze.bfg application, if you obey certain constraints, the application you produce can be reused, modified, re-integrated, or extended by third-party developers without modification to the original application itself. See Extending An Existing repoze.bfg Application for more information about extending or modifying an existing repoze.bfg application.

repoze.bfg uses the Zope Component Architecture under the hood. However, while a Zope application developer tends to need to understand the component architecture (and concepts such as adapters, utilities, and interfaces) to create a non-trivial application, a repoze.bfg application developer isn’t required to interact with or understand the component architecture at all. repoze.bfg tends to “hide” most interaction with the component architecture behind special-purpose API functions and ZCML directives.

Also unlike Zope and unlike other “full-featured” frameworks such as Django, repoze.bfg makes no assumptions about which persistence mechanisms you should use to build an application. Zope applications are typically reliant on ZODB; repoze.bfg allows you to build ZODB applications, but it has no reliance on the ZODB package. Likewise, Django tends to assume that you want to store your application’s data in a relational database. repoze.bfg makes no such assumption; it allows you to use a relational database but doesn’t encourage or discourage an application developer about such a decision.

Why?

Familiarity: As web developers, we’ve become accustomed to working in very particular ways over the years. This framework is a canonization of practices that “fit our brains”.

Simplicity: repoze.bfg attempts to be a “pay only for what you eat” framework in which you can be productive quickly with partial knowledge. We contrast this with “pay up front for what anyone might eventually want to eat” frameworks, which tend to expect you to understand a great many concepts and technologies fully before you can be truly productive. repoze.bfg doesn’t force you to use any particular technology to produce an application, and we try to keep the core set of concepts you need to understand to a minimum.

Minimalism: repoze.bfg provides only the very basics: URL to code mapping, templating, security, and resources. There is not much more to the framework than these pieces: you are expected to provide the rest.

Documentation: Because repoze.bfg is minimal, it’s relatively easy to keep its documentation up-to-date, which is helpful to bring new developers up to speed. It’s our goal that nothing remain undocumented about repoze.bfg.

Speed: repoze.bfg is faster than many other popular Python web frameworks for common tasks such as templating and simple response generation. The “hardware is cheap” mantra has its limits when you’re responsible for managing a great many machines: the fewer you need, the less pain you’ll have.

It’s Tested

If it ain’t tested, it’s broke. We strive to test repoze.bfg completely. Below a run of the nosetests command configured to show code coverage information (run against the repoze.bfg trunk as of the 1.0 release).

[chrism@vitaminf trunk]$ python setup.py nosetests
running nosetests
running egg_info
writing requirements to repoze.bfg.egg-info/requires.txt
writing repoze.bfg.egg-info/PKG-INFO
writing namespace_packages to repoze.bfg.egg-info/namespace_packages.txt
writing top-level names to repoze.bfg.egg-info/top_level.txt
writing dependency_links to repoze.bfg.egg-info/dependency_links.txt
writing entry points to repoze.bfg.egg-info/entry_points.txt
writing manifest file 'repoze.bfg.egg-info/SOURCES.txt'
running build_ext
...........................................................................
...........................................................................
...........................................................................
...........................................................................
...........................................................................
...........................................................................
...........................................................................
...........................................................................
............................................
Name                                     Stmts   Exec  Cover   Missing
----------------------------------------------------------------------
repoze.bfg                                   0      0   100%
repoze.bfg.authentication                  196    196   100%
repoze.bfg.authorization                    50     50   100%
repoze.bfg.chameleon_text                   48     48   100%
repoze.bfg.chameleon_zpt                    41     41   100%
repoze.bfg.events                           18     18   100%
repoze.bfg.functional                       14     14   100%
repoze.bfg.includes                          0      0   100%
repoze.bfg.interfaces                       73     73   100%
repoze.bfg.location                         10     10   100%
repoze.bfg.log                               9      9   100%
repoze.bfg.paster                           48     48   100%
repoze.bfg.path                             28     28   100%
repoze.bfg.registry                         51     51   100%
repoze.bfg.request                          67     67   100%
repoze.bfg.resource                         83     83   100%
repoze.bfg.router                          167    167   100%
repoze.bfg.scripting                        10     10   100%
repoze.bfg.secpols                         166    166   100%
repoze.bfg.security                        114    114   100%
repoze.bfg.settings                         35     35   100%
repoze.bfg.static                           48     48   100%
repoze.bfg.templating                       35     35   100%
repoze.bfg.testing                         218    218   100%
repoze.bfg.tests                             0      0   100%
repoze.bfg.tests.fixtureapp                  0      0   100%
repoze.bfg.tests.fixtureapp.models           4      4   100%
repoze.bfg.tests.fixtureapp.subpackage       0      0   100%
repoze.bfg.tests.fixtureapp.views            4      4   100%
repoze.bfg.tests.grokkedapp                  9      9   100%
repoze.bfg.tests.routesapp                   0      0   100%
repoze.bfg.tests.routesapp.views             4      4   100%
repoze.bfg.tests.test_authentication       433    433   100%
repoze.bfg.tests.test_authorization        124    124   100%
repoze.bfg.tests.test_chameleon_text       172    172   100%
repoze.bfg.tests.test_chameleon_zpt        161    161   100%
repoze.bfg.tests.test_events                59     59   100%
repoze.bfg.tests.test_integration          123    123   100%
repoze.bfg.tests.test_location              34     34   100%
repoze.bfg.tests.test_log                   11     11   100%
repoze.bfg.tests.test_paster                69     69   100%
repoze.bfg.tests.test_path                 104    104   100%
repoze.bfg.tests.test_registry              95     95   100%
repoze.bfg.tests.test_request              230    230   100%
repoze.bfg.tests.test_resource             233    233   100%
repoze.bfg.tests.test_router               830    830   100%
repoze.bfg.tests.test_scripting             44     44   100%
repoze.bfg.tests.test_secpols              598    598   100%
repoze.bfg.tests.test_security             294    294   100%
repoze.bfg.tests.test_settings             137    137   100%
repoze.bfg.tests.test_static               120    120   100%
repoze.bfg.tests.test_templating           126    126   100%
repoze.bfg.tests.test_testing              394    394   100%
repoze.bfg.tests.test_threadlocal           69     69   100%
repoze.bfg.tests.test_traversal            906    906   100%
repoze.bfg.tests.test_url                  173    173   100%
repoze.bfg.tests.test_urldispatch          166    166   100%
repoze.bfg.tests.test_view                 409    409   100%
repoze.bfg.tests.test_wsgi                  99     99   100%
repoze.bfg.tests.test_zcml                1290   1290   100%
repoze.bfg.threadlocal                      29     29   100%
repoze.bfg.traversal                       200    200   100%
repoze.bfg.url                              63     63   100%
repoze.bfg.urldispatch                     101    101   100%
repoze.bfg.view                             72     72   100%
repoze.bfg.wsgi                             27     27   100%
repoze.bfg.zcml                            274    274   100%
----------------------------------------------------------------------
TOTAL                                     9819   9819   100%
----------------------------------------------------------------------
Ran 644 tests in 22.150s

OK