==================
Features
--------
- A new ZCML directive was added named ``notfound``. This ZCML
directive can be used to name a view that should be invoked when the
request can't otherwise be resolved to a view callable. For example::
<notfound
view="helloworld.views.notfound_view"/>
- A new ZCML directive was added named ``forbidden``. This ZCML
directive can be used to name a view that should be invoked when a
view callable for a request is found, but cannot be invoked due to
an authorization failure. For example::
<forbidden
view="helloworld.views.forbidden_view"/>
- Allow views to be *optionally* defined as callables that accept only
a request object, instead of both a context and a request (which
still works, and always will). The following types work as views in
this style:
- functions that accept a single argument ``request``, e.g.::
def aview(request):
pass
- new and old-style classes that have an ``__init__`` method that
accepts ``self, request``, e.g.::
def View(object):
__init__(self, request):
pass
- Arbitrary callables that have a ``__call__`` method that accepts
``self, request``, e.g.::
def AView(object):
def __call__(self, request):
pass
view = AView()
This likely should have been the calling convention all along, as
the request has ``context`` as an attribute already, and with views
called as a result of URL dispatch, having the context in the
arguments is not very useful. C'est la vie.
- Cache the absolute path in the caller's package globals within
``repoze.bfg.path`` to get rid of repeated (expensive) calls to
os.path.abspath.
- Add ``reissue_time`` and ``timeout`` parameters to
``repoze.bfg.authentication.AuthTktAuthenticationPolicy``
constructor. If these are passed, cookies will be reset every so
often (cadged from the same change to repoze.who lately).
- The matchdict related to the matching of a Routes route is available
on the request as the ``matchdict`` attribute:
``request.matchdict``. If no route matched, this attribute will be
None.
- Make 404 responses slightly cheaper by showing
``environ["PATH_INFO"]`` on the notfound result page rather than the
fullly computed URL.
- Move LRU cache implementation into a separate package
(``repoze.lru``).
- The concepts of traversal and URL dispatch have been unified. It is
now possible to use the same sort of factory as both a traversal
"root factory" and what used to be referred to as a urldispatch
"context factory".
- When the root factory argument (as a first argument) passed to
``repoze.bfg.router.make_app`` is ``None``, a *default* root factory
is used. This is in support of using routes as "root finders"; it
supplants the idea that there is a default
``IRoutesContextFactory``.
- The `view`` ZCML statement and the ``repoze.bfg.view.bfg_view``
decorator now accept an extra argument: ``route_name``. If a
``route_name`` is specified, it must match the name of a previously
defined ``route`` statement. When it is specified, the view will
only be called when that route matches during a request.
- It is now possible to perform traversal *after* a route has matched.
Use the pattern ``*traverse`` in a ``<route>`` ``path`` attribute
within ZCML, and the path remainder which it matches will be used as
a traversal path.
- When any route defined matches, the WSGI environment will now
contain a key ``bfg.routes.route`` (the Route object which matched),
and a key ``bfg.routes.matchdict`` (the result of calling route.match).
Deprecations
------------
- Utility registrations against
``repoze.bfg.interfaces.INotFoundView`` and
``repoze.bfg.interfaces.IForbiddenView`` are now deprecated. Use
the ``notfound`` and ``forbidden`` ZCML directives instead (see the
"Hooks" chapter for more information). Such registrations will
continue to work, but the notfound and forbidden directives do
"extra work" to ensure that the callable named by the directive can
be called by the router even if it's a class or
request-argument-only view.
Removals
--------
- The ``IRoutesContext``, ``IRoutesContextFactory``, and
``IContextNotFound`` interfaces were removed from
``repoze.bfg.interfaces``. These were never APIs.
- The ``repoze.bfg.urldispatch.RoutesContextNotFound``,
``repoze.bfg.urldispatch.RoutesModelTraverser`` and
``repoze.bfg.urldispatch.RoutesContextURL`` classes were removed.
These were also never APIs.
Backwards Incompatibilities
---------------------------
- Moved the ``repoze.bfg.push`` module, which implemented the ``pushpage``
decorator, into a separate distribution, ``repoze.bfg.pushpage``.
Applications which used this decorator should continue to work after
adding that distribution to their installation requirements.
- Changing the default request factory via an IRequestFactory utility
registration (as used to be documented in the "Hooks" chapter's
"Changing the request factory" section) is no longer supported. The
dance to manufacture a request is complicated as a result of
unifying traversal and url dispatch, making it highly unlikely for
anyone to be able to override it properly. For those who just want
to decorate or modify a request, use a NewRequestEvent subscriber
(see the Events chapter in the documentation).
- The ``repoze.bfg.IRequestFactory`` interface was removed. See the
bullet above for why.
- Routes "context factories" (spelled as the factory argument to a
route statement in ZCML) must now expect the WSGI environ as a
single argument rather than a set of keyword arguments. They can
obtain the match dictionary by asking for
environ['bfg.routes.matchdict']. This is the same set of keywords
that used to be passed to urldispatch "context factories" in BFG 0.9
and below.
- Using the ``zope.component.adapter`` decorator on a bfg view
function no longer works. Use the ``repoze.bfg.view.bfg_view``
decorator instead to mark a function (or a class) as a view.
- The name under which the matching route object is found in the
environ was changed from ``bfg.route`` to ``bfg.routes.route``.
- Finding the root is now done *before* manufacturing a request object
(and sending a new request event) within the router (it used to be
performed afterwards).
- Adding ``*path_info`` to a route no longer changes the PATH_INFO for
a request that matches using URL dispatch. This feature was only
there to service the ``repoze.bfg.wsgi.wsgiapp2`` decorator and it
did it wrong; use ``*subpath`` instead now.
- The values of ``subpath``, ``traversed``, and ``virtual_root_path``
attached to the request object are always now tuples instead of
lists (performance).
Bug Fixes
---------
- The ``bfg_alchemy`` Paster template named "repoze.tm" in its
pipeline rather than "repoze.tm2", causing the startup to fail.
- Move BBB logic for registering an
IAuthenticationPolicy/IForbiddenView/INotFoundView based on older
concepts from the router module's ``make_app`` function into the
``repoze.bfg.zcml.zcml_configure`` callable, to service
compatibility with scripts that use "zope.configuration.xmlconfig"
(replace with ``repoze.bfg.zml.zcml_configure`` as necessary to get
BBB logic)
Documentation
-------------
- Add interface docs related to how to create authentication policies
and authorization policies to the "Security" narrative chapter.
- Added a (fairly sad) "Combining Traversal and URL Dispatch" chapter
to the narrative documentation. This explains the usage of
``*traverse`` and ``*subpath`` in routes URL patters.
- A "router" chapter explaining the request/response lifecycle at a
high level was added.
- Replaced all mentions and explanations of a routes "context factory"
with equivalent explanations of a "root factory" (context factories
have been disused).
- Updated Routes bfgwiki2 tutorial to reflect the fact that context
factories are now no longer used.