Chris McDonough
2009-11-02 a53cbfbb503010d34c9c02fdaf6eccc56361c7a2
- "What's New in ``repoze.bfg`` 1.1" document added to narrative
documentation.

- Minor typo fixes.

1 files added
4 files modified
863 ■■■■■ changed files
CHANGES.txt 39 ●●●● patch | view | raw | blame | history
docs/index.rst 12 ●●●● patch | view | raw | blame | history
docs/narr/urldispatch.rst 2 ●●● patch | view | raw | blame | history
docs/narr/views.rst 68 ●●●● patch | view | raw | blame | history
docs/whatsnew-1.1.rst 742 ●●●●● patch | view | raw | blame | history
CHANGES.txt
@@ -9,6 +9,9 @@
  order) the ``<route>`` statement which creates the route.  This
  hasn't been true since 1.1a1.
- "What's New in ``repoze.bfg`` 1.1" document added to narrative
  documentation.
1.1b1 (2009-11-01)
==================
@@ -861,6 +864,16 @@
- The ``static`` ZCML directive now uses a custom root factory when
  constructing a route.
- The interface ``IRequestFactories`` was removed from the
  repoze.bfg.interfaces module.  This interface was never an API.
- The function named ``named_request_factories`` and the data
  structure named ``DEFAULT_REQUEST_FACTORIES`` have been removed from
  the ``repoze.bfg.request`` module.  These were never APIs.
- The ``IViewPermissionFactory`` interface has been removed.  This was
  never an API.
Documentation
-------------
@@ -873,8 +886,14 @@
- Fixed documentation for ``repoze.bfg.view.static`` (in narrative
  ``Views`` chapter).
- The interface ``IRequestFactories`` was removed from the
  repoze.bfg.interfaces module.  This interface was never an API.
Deprecations
------------
- The API ``repoze.bfg.testing.registerViewPermission`` has been
  deprecated.
Backwards Incompatibilities
---------------------------
- The interfaces ``IPOSTRequest``, ``IGETRequest``, ``IPUTRequest``,
  ``IDELETERequest``, and ``IHEADRequest`` have been removed from the
@@ -888,22 +907,6 @@
  argument will work too.  Rationale: instead of relying on interfaces
  attached to the request object, BFG now uses a "view predicate" to
  determine the request type.
- The function named ``named_request_factories`` and the data
  structure named ``DEFAULT_REQUEST_FACTORIES`` have been removed from
  the ``repoze.bfg.request`` module.  These were never APIs.
- The ``IViewPermissionFactory`` interface has been removed.  This was
  never an API.
Deprecations
------------
- The API ``repoze.bfg.testing.registerViewPermission`` has been
  deprecated.
Backwards Incompatibilities
---------------------------
- Views registered without the help of the ZCML ``view`` directive are
  now responsible for performing their own authorization checking.
docs/index.rst
@@ -15,6 +15,14 @@
<http://agendaless.com>`_ and other contributors.  It is licensed
under a `BSD-like license <http://repoze.org/license.html>`_.
"What's New" Documents
======================
.. toctree::
   :maxdepth: 2
   whatsnew-1.1
Narrative documentation
=======================
@@ -129,8 +137,8 @@
   tutorials/zodbsessions/index.rst
Change History
==============
Detailed Change History
=======================
.. toctree::
   :maxdepth: 1
docs/narr/urldispatch.rst
@@ -87,7 +87,7 @@
xhr
  Thie value should be either ``True`` or ``False``.  If this value is
  This value should be either ``True`` or ``False``.  If this value is
  specified and is ``True``, the :term:`request` must possess an
  ``HTTP_X_REQUESTED_WITH`` (aka ``X-Requested-With``) header for this
  route to match.  This is useful for detecting AJAX requests issued
docs/narr/views.rst
@@ -210,7 +210,7 @@
the ``renderer`` attribute.  For example, this ZCML associates the
``json`` renderer with a view:
.. code-block:: python
.. code-block:: xml
   :linenos:
   <view
@@ -364,11 +364,11 @@
  The view machinery defaults to using the ``__call__`` method of the
  view callable (or the function itself, if the view callable is a
  funcion) to obtain a response dictionary.  The ``attr`` value allows
  you to vary the method attribute used to obtain the response.  For
  example, if your view was a class, and the class has a method named
  ``index`` and you wanted to use this method instead of the class'
  ``__call__`` method to return the response, you'd say
  function) to obtain a response dictionary.  The ``attr`` value
  allows you to vary the method attribute used to obtain the response.
  For example, if your view was a class, and the class has a method
  named ``index`` and you wanted to use this method instead of the
  class' ``__call__`` method to return the response, you'd say
  ``attr="index"`` in the view configuration for the view.  This is
  most useful when the view definition is a class.
@@ -441,6 +441,34 @@
  is an instance of the represented class or if the :term:`context`
  provides the represented interface; it is otherwise false.
route_name
  *This attribute services an advanced feature that isn't often used
  unless you want to perform traversal *after* a route has matched.*
  This value must match the ``name`` of a ``<route>`` declaration (see
  :ref:`urldispatch_chapter`) that must match before this view will be
  called.  The ``<route>`` declaration specified by ``route_name`` must
  exist in ZCML before the view that names the route
  (XML-ordering-wise) .  Note that the ``<route>`` declaration
  referred to by ``route_name`` usually has a ``*traverse`` token in
  the value of its ``path`` attribute, representing a part of the path
  that will be used by traversal against the result of the route's
  :term:`root factory`.  See :ref:`hybrid_chapter` for more
  information on using this advanced feature.
request_type
  This value should be a Python dotted-path string representing the
  :term:`interface` that the :term:`request` must have in order for
  this view to be found and called.  See
  :ref:`view_request_types_section` for more information about request
  types.  For backwards compatibility with :mod:`repoze.bfg` version
  1.0, this value may also be an HTTP ``REQUEST_METHOD`` string, e.g.
  ('GET', 'HEAD', 'PUT', 'POST', or 'DELETE').  Passing request method
  strings as a ``request_type`` is deprecated.  Use the
  ``request_method`` attribute instead for maximum forward
  compatibility.
request_method
  This value can either be one of the strings 'GET', 'POST', 'PUT',
@@ -475,34 +503,6 @@
  :ref:`location_aware` for more information about location-awareness.
  .. note:: This feature is new as of :mod:`repoze.bfg` 1.1.
route_name
  *This attribute services an advanced feature that isn't often used
  unless you want to perform traversal *after* a route has matched.*
  This value must match the ``name`` of a ``<route>`` declaration (see
  :ref:`urldispatch_chapter`) that must match before this view will be
  called.  The ``<route>`` declaration specified by ``route_name`` must
  exist in ZCML before the view that names the route
  (XML-ordering-wise) .  Note that the ``<route>`` declaration
  referred to by ``route_name`` usually has a ``*traverse`` token in
  the value of its ``path`` attribute, representing a part of the path
  that will be used by traversal against the result of the route's
  :term:`root factory`.  See :ref:`hybrid_chapter` for more
  information on using this advanced feature.
request_type
  This value should be a Python dotted-path string representing the
  :term:`interface` that the :term:`request` must have in order for
  this view to be found and called.  See
  :ref:`view_request_types_section` for more information about request
  types.  For backwards compatibility with :mod:`repoze.bfg` version
  1.0, this value may also be an HTTP ``REQUEST_METHOD`` string, e.g.
  ('GET', 'HEAD', 'PUT', 'POST', or 'DELETE').  Passing request method
  strings as a ``request_type`` is deprecated.  Use the
  ``request_method`` attribute instead for maximum forward
  compatibility.
xhr
docs/whatsnew-1.1.rst
New file
@@ -0,0 +1,742 @@
What's New In :mod:`repoze.bfg` 1.1
===================================
This article explains the new features in :mod:`repoze.bfg` version
1.1 as compared to the previous 1.0 release.  It also documents
backwards incompatibilities between the two versions and deprecations
added to 1.1, as well as sotware dependency changes and notable
documentation additions.
Features
--------
The major feature additions of 1.1 are:
- Allow the use of additional :term:`view predicate` parameters to
  more finely control view matching.
- Allow the use of :term:`route predicate` parameters to more finely
  control route matching.
- Make it possible to write views that use a :term:`renderer`.
- Make it possible to write views that use a "wrapper view".
- Added ``<static>`` ZCML directive which registers a view which
  serves up files in a package directory.
- A new API function: ``repoze.bfg.url.static_url`` is available to
  compute the path of static resources.
- View configurations can now name an ``attr`` representing the method
  that should be called to return a response.
- ``@bfg_view`` decorators may now be stacked, allowing for the same
  view callable to be associated with multiple different view
  configurations without resorting to ZCML for view configuration.
- ``@bfg_view`` decorators may now be placed on a class method.
- ``paster bfgshell`` now supports IPython if it is found in the
  Python environment invoking Paster.
- Commonly executed codepaths have been accelerated.
View Predicates
~~~~~~~~~~~~~~~
:mod:`repoze.bfg` 1.0, :term:`view configuration` allowed relatively
coarse matching of a :term:`request` to a :term:`view callable`.
Individual view configurations could match the same URL depending on
the :term:`context` and the URL path, as well as a limited number of
other request values.
For example, two view configurations mentioning the same :term:`view
name` could be spelled via a ``@bfg_view`` decorator with a different
``for_`` parameter.  The view ultimately chosen would be based on the
:term:`context` type based on the ``for_`` attribute like so:
.. code-block:: python
   from webob import Response
   from repoze.bfg.view import bfg_view
   from myapp.models import Document
   from myapp.models import Folder
   @bfg_view(name='index.html', for_=Document)
   def document_view(context, request):
       return Response('document view')
   @bfg_view(name='index.html', for_=Folder)
   def folder_view(context, request):
       return Response('folder view')
In the above configuration, the ``document_view`` :term:`view
callable` will be chosen when the :term:`context` is of the class
``myapp.models.Document``, while the ``folder_view`` view callbale
will be chosen when the context is of class ``myapp.models.Folder``.
There were a number of other attributes that could influence the
choosing of view callables, such as ``request_type``, and others.
However, the matching algorithm was rather limited.
In :mod:`repoze.bfg` 1.1, this facility has been enhanced via the
availability of additional :term:`view predicate` attributes.  For
example, one view predicate new to 1.1 is ``containment``, which
implies that the view will be called when the class or interface
mentioned as ``containment`` is present with respect to any instance
in the :term:`lineage` of the context:
.. code-block:: python
   from webob import Response
   from repoze.bfg.view import bfg_view
   from myapp.models import Document
   from myapp.models import Folder
   from myapp.models import Blog
   from myapp.models import Calendar
   @bfg_view(name='index.html', for_=Document, containment=Blog)
   def blog_document_view(context, request):
       return Response('blog document view')
   @bfg_view(name='index.html', for_=Folder, containment=Blog)
   def blog_folder_view(context, request):
       return Response('blog folder view')
   @bfg_view(name='index.html', for_=Document, containment=Calendar)
   def calendar_document_view(context, request):
       return Response('calendar document view')
   @bfg_view(name='index.html', for_=Folder, containment=Calendar)
   def calendar_folder_view(context, request):
       return Response('calendar folder view')
As might be evident in the above example, you can use the
``containment`` predicate to arrange for different view callables to
be called based on the lineage of the context.  In the above example,
the ``blog_document_view`` will be called when the context is of the
class ``myapp.models.Document`` and the containment has an instance of
the class ``myapp.models.Blog`` in it.  But when all else is equal,
except the containment has an instance of the class
``myapp.models.Calendar`` in it instead of ``myapp.models.Blog``, the
``calendar_document_view`` will be called instead.
All view predicates configurable via the ``@bfg_view`` decorator are
available via :term:`ZCML` :term:`view configuration` as wel..
Additional new 1.1 view predicates besides ``containment`` are:
``request_method``
  True if the specified value (e.g. GET/POST/HEAD/PUT/DELETE) is the
  request.method value.
``request_param``
  True if the specified value is present in the request.GET or
  request.POST multidicts.
``xhr``
  True if the request.is_xhr attribute is ``True``, meaning that the
  request has an ``X-Requested-With`` header with the value
  ``XMLHttpRequest``
``accept``
  True if the value of this attribute represents matches one or more
  mimetypes in the ``Accept`` HTTP request header.
``header``
  True if the value of this attribute represents an HTTP header name
  or a header name/value pair present in the request.
``path_info``
  True if the value of this attribute (a regular expression pattern)
  matches the ``PATH_INFO`` WSGI environment variable.
All other existing view configuration parameters from 1.0 still exist.
Any number of view predicates can be specified in a view
configuration.  All view predicates in a view configuration must be
True for a view callable to be invoked.  If one does not evaluate to
True, the view will not be invoked, and view matching will continue,
until all potential matches are exhausted (and the Not Found view is
invoked).
Route Predicates
~~~~~~~~~~~~~~~~
In :mod:`repoze.bfg` 1.0, a :term:`route` would match or not match
based on only one value: the ``PATH_INFO`` value of the WSGI
environment, as specified by the ``path`` parameter of the ``<route>``
ZCML directive.
In 1.1, matching can be more finely controlled via the use of one or
more :term:`route predicate` attributes.
The additional route predicates in 1.1 are:
``xhr``
  True if the request.is_xhr attribute is ``True``, meaning that the
  request has an ``X-Requested-With`` header with the value
  ``XMLHttpRequest``.
``request_method``
  True if the specified value (e.g. GET/POST/HEAD/PUT/DELETE) is the
  request.method value.
``path_info``
  True if the value of this attribute (a regular expression pattern)
  matches the ``PATH_INFO`` WSGI environment variable.
``request_param``
  True if the specified value is present in either of the
  ``request.GET`` or ``request.POST`` multidicts.
``header``
  True if the value of this attribute represents an HTTP header name
  or a header name/value pair present in the request.
``accept``
  True if the value of this attribute represents matches one or more
  mimetypes in the ``Accept`` HTTP request header.
All other existing route configuration parameters from 1.0 still exist.
Any number of route predicates can be specified in a route
configuration.  All route predicates in a route configuration must be
True for a route to match a request.  If one does not evaluate to
True, the route will not be invoked, and route matching will continue,
until all potential routes are exhausted (at which point, traversal is
attempted).
View Renderers
~~~~~~~~~~~~~~
In :mod:`repoze.bfg` 1.0 and prior, views were required to return a
:term:`response` object unconditionally.
In :mod:`repoze.bfg` 1.1, a :term:`view configuration` can name a
:term:`renderer`.  A renderer can either be a template or a token that
is associated with a serialization technique (e.g. ``json``).  When a
view configuration names a renderer, the view can return a data
structure understood by the renderer (such as a dictionary), and the
renderer will convert the data structure to a response on the behalf
of the developer.
View configuration can vary the renderer associated with a view via
the ``renderer`` attribute to the configuration.  For example, this
ZCML associates the ``json`` renderer with a view:
.. code-block:: xml
   :linenos:
   <view
     view=".views.my_view"
     renderer="json"
     />
The ``@bfg_view`` decorator can also associate a view callable with a
renderer:
.. code-block:: python
   :linenos:
   from repoze.bfg.view import bfg_view
   @bfg_view(renderer='json')
   def my_view(context, request):
       return {'abc':123}
The ``json`` renderer renders view return values to a :term:`JSON`
serialization.
Another built-in renderer uses the :term:`Chameleon` templating
language to render a dictionary to a response.  For example:
.. code-block:: python
   :linenos:
   from repoze.bfg.view import bfg_view
   @bfg_view(renderer='templates/my_template.pt')
   def my_view(context, request):
       return {'abc':123}
See :ref:`built_in_renders` for the available built-in renderers.
If the ``view`` callable associated with a ``view`` directive returns
a Response object (an object with the attributes ``status``,
``headerlist`` and ``app_iter``), any renderer associated with the
``view`` declaration is ignored, and the response is passed back to
BFG unmolested.  For example, if your view callable returns an
``HTTPFound`` response, no renderer will be employed.
.. code-block:: python
   :linenos:
   from webob.exc import HTTPFound
   from repoze.bfg.view import bfg_view
   @bfg_view(renderer='templates/my_template.pt')
   def my_view(context, request):
       return HTTPFound(location='http://example.com') # renderer avoided
Additional renderers can be added to the system as necessary via a
ZCML directive (see :ref:`adding_and_overriding_renderers`).
If you do not define a ``renderer`` attribute in view configuration
for a view, no renderer is associated with the view.  In such a
configuration, an error is raised when a view does not return an
object which implements :term:`Response` interface, as was the case
under BFG 1.0.
Views Which Use Wrappers
~~~~~~~~~~~~~~~~~~~~~~~~
In :mod:`repoze.bfg` 1.1, view configuration may specify a ``wrapper``
attribute.  For example:
.. code-block:: xml
   :linenos:
   <view
     name="one"
     view=".views.wrapper_view"
     />
   <view
     name="two"
     view=".views.my_view"
     wrapper="one"
     />
The ``wrapper`` attribute of a view configuration is a :term:`view
name` (*not* an object dotted name).  It specifies *another* view
callable declared elsewhere in :term:`view configuration`.  In the
above example, the wrapper of the ``two`` view is the ``one`` view.
The wrapper view will be called when after the wrapped view is
invoked; it will receive the response body of the wrapped view as the
``wrapped_body`` attribute of its own request, and the response
returned by this view as the ``wrapped_response`` attribute of its own
request.
Using a wrapper makes it possible to "chain" views together to form a
composite response.  The response of the outermost wrapper view will
be returned to the user.
The wrapper view will be found as any view is found: see
:ref:`view_lookup_ordering`.  The "best" wrapper view will be found
based on the lookup ordering: "under the hood" this wrapper view is
looked up via ``repoze.bfg.view.render_view_to_response(context,
request, 'wrapper_viewname')``. The context and request of a wrapper
view is the same context and request of the inner view.
If the ``wrapper`` attribute is unspecified in a view configuration,
no view wrapping is done.
The ``@bfg_view`` decorator accepts a ``wrapper`` parameter, mirroring
its ZCML view configuration counterpart.
``<static>`` ZCML Directive
~~~~~~~~~~~~~~~~~~~~~~~~~~~
A new ZCML directive named ``static`` has been added.  Inserting a
``static`` declaration in a ZCML file will cause static resources to
be served at a configurable URL.
Here's an example of a ``static`` directive that will serve files up
from the ``templates/static`` directory of the :mod:`repoze.bfg`
application containing the following configuration at the URL
``/static``.
.. code-block:: xml
   :linenos:
   <static
      name="static"
      path="templates/static"
      />
Using the ``static`` ZCML directive is now the preferred way to serve
static resources (such as JavaScript and CSS files) within a
:mod:`repoze.bfg` application.  Previous strategies for serving static
resources will still work, however.
New ``static_url`` API
~~~~~~~~~~~~~~~~~~~~~~
The new ``repoze.bfg.url.static_url`` API generates a fully qualified
URL to a static resource available via a path exposed via the
``<static>`` ZCML directive (see :ref:`static_resources_section`).
For example, if a ``<static>`` directive is in ZCML configuration like
so:
.. code-block:: xml
   :linenos:
   <static
      name="static"
      path="templates/static"
      />
You can generate a URL to a resource which lives within the
``templates/static`` subdirectory using the ``static_url`` API like
so:
.. code-block:: python
   :linenos:
   from repoze.bfg.url import static_url
   url = static_url('templates/static/example.css', request)
Use of the ``static_url`` API prevents the developer from needing to
hardcode path values in template URLs.
``attr`` View Configuration Value
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The view machinery defaults to using the ``__call__`` method of the
view callable (or the function itself, if the view callable is a
function) to obtain a response dictionary.
In :mod:`repoze.bfg` 1.1, the ``attr`` view configuration value allows
you to vary the attribute of a view callable used to obtain the
response.
For example, if your view is a class, and the class has a method named
``index`` and you want to use this method instead of the class'
``__call__`` method to return the response, you'd say ``attr="index"``
in the view configuration for the view.
Specifying ``attr`` is most useful when the view definition is a
class.
``@bfg_view`` Decorators May Now Be Stacked
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
More than one ``@bfg_view`` decorator may now be stacked on top of any
number of others.  Each invocation of the decorator registers a single
view configuration.  For instance, the following combination of
decorators and a function will register two view configurations for
the same view callable:
.. code-block:: python
   :linenos:
    from repoze.bfg.view import bfg_view
    @bfg_view(name='edit')
    @bfg_view(name='change')
    def edit(context, request):
        pass
This makes it possible to associate more than one view configuration
with a single callable without requiring any ZCML.
Stacking ``@bfg_view`` decorators was not possible in
:mod:`repoze.bfg` 1.0.
``@bfg_view`` Decorators May Now Be Applied to A Class Method
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In :mod:`repoze.bfg` 1.0, the ``@bfg_view`` decorator could not be
used on class methods.  In 1.1, the ``@bfg_view`` decorator can be
used against a class method:
.. code-block:: python
   :linenos:
    from webob import Response
    from repoze.bfg.view import bfg_view
    class MyView(object):
        def __init__(self, context, request):
            self.context = context
            self.request = request
        @bfg_view(name='hello')
        def amethod(self):
            return Response('hello from %s!' % self.context)
When the bfg_view decorator is used against a class method, a view is
registered for the *class* (it's a "class view" where the "attr"
happens to be the name of the method it is attached to), so the class
it's defined within must have a suitable constructor: one that accepts
``context, request`` or just ``request``.
IPython Support
~~~~~~~~~~~~~~~
If it is installed in the environment used to run :mod:`repoze.bfg`,
aqn `IPython <http://ipython.scipy.org/moin/>` shell will be opened
when the ``paster bfgshell`` command is invoked.
Common Codepaths Have Been Accelerated
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
:mod:`repoze.bfg` 1.1 is roughly 10% - 20% faster in commonly executed
codepaths than :mod:`repoze.bfg` 1.0 was on average.  Accelerated APIs
include ``repoze.bfg.location.lineage``, ``repoze.bfg.url.model_url``,
and ``repoze.bfg.url.route_url``.  Other internal (non-API) functions
were similarly accelerated.
Minor Miscellaneous Feature Additions
-------------------------------------
- For behavior like Django's ``APPEND_SLASH=True``, use the
  ``repoze.bfg.view.append_slash_notfound_view`` view as the Not Found
  view in your application.  When this view is the Not Found view
  (indicating that no view was found), and any routes have been
  defined in the configuration of your application, if the value of
  ``PATH_INFO`` does not already end in a slash, and if the value of
  ``PATH_INFO`` *plus* a slash matches any route's path, do an HTTP
  redirect to the slash-appended PATH_INFO.  Note that this will
  *lose* ``POST`` data information (turning it into a GET), so you
  shouldn't rely on this to redirect POST requests.
- Add ``repoze.bfg.testing.registerSettings`` API, which is documented
  in the "repoze.bfg.testing" API chapter.  This allows for
  registration of "settings" values obtained via
  ``repoze.bfg.settings.get_settings()`` for use in unit tests.
- Added ``max_age`` parameter to ``authtktauthenticationpolicy`` ZCML
  directive.  If this value is set, it must be an integer representing
  the number of seconds which the auth tkt cookie will survive.
  Mainly, its existence allows the auth_tkt cookie to survive across
  browser sessions.
- The ``reissue_time`` argument to the ``authtktauthenticationpolicy``
  ZCML directive now actually works.  When it is set to an integer
  value, an authticket set-cookie header is appended to the response
  whenever a request requires authentication and 'now' minus the
  authticket's timestamp is greater than ``reissue_time`` seconds.
- Expose and document ``repoze.bfg.testing.zcml_configure`` API.  This
  function populates a component registry from a ZCML file for testing
  purposes.  It is documented in the "Unit and Integration Testing"
  chapter.
- Virtual hosting narrative docs chapter updated with info about
  ``mod_wsgi``.
- Added "Creating Integration Tests" section to unit testing narrative
  documentation chapter.  As a result, the name of the unittesting
  chapter is now "Unit and Integration Testing".
- Add a new ``repoze.bfg.testing`` API: ``registerRoute``, for
  registering routes to satisfy calls to
  e.g. ``repoze.bfg.url.route_url`` in unit tests.
- Added a tutorial which explains how to use ``repoze.session``
  (ZODB-based sessions) in a ZODB-based repoze.bfg app.
- Added a tutorial which explains how to add ZEO to a ZODB-based
  ``repoze.bfg`` application.
- Added a tutorial which explains how to run a ``repoze.bfg``
  application under `mod_wsgi <http://code.google.com/p/modwsgi/>`_.
  See "Running a repoze.bfg Application under mod_wsgi" in the
  tutorials section of the documentation.
- Allow ``repoze.bfg.traversal.find_interface`` API to use a class
  object as the argument to compare against the ``model`` passed in.
  This means you can now do ``find_interface(model, SomeClass)`` and
  the first object which is found in the lineage which has
  ``SomeClass`` as its class (or the first object found which has
  ``SomeClass`` as any of its superclasses) will be returned.
- The ordering of route declarations vs. the ordering of view
  declarations that use a "route_name" in ZCML no longer matters.
  Previously it had been impossible to use a route_name from a route
  that had not yet been defined in ZCML (order-wise) within a "view"
  declaration.
- The repoze.bfg router now catches both
  ``repoze.bfg.security.Unauthorized`` and
  ``repoze.bfg.view.NotFound`` exceptions while rendering a view.
  When the router catches an ``Unauthorized``, it returns the
  registered forbidden view.  When the router catches a ``NotFound``,
  it returns the registered notfound view.
Backwards Incompatibilities
---------------------------
- The ``authtkt`` authentication policy ``remember`` method now no
  longer honors ``token`` or ``userdata`` keyword arguments.
- Importing ``getSiteManager`` and ``get_registry`` from
  ``repoze.bfg.registry`` is no longer supported.  These imports were
  deprecated in repoze.bfg 1.0.  Import of ``getSiteManager`` should
  be done as ``from zope.component import getSiteManager``.  Import of
  ``get_registry`` should be done as ``from repoze.bfg.threadlocal
  import get_current_registry``.  This was done to prevent a circular
  import dependency.
- Code bases which alternately invoke both
  ``zope.testing.cleanup.cleanUp`` and ``repoze.bfg.testing.cleanUp``
  (treating them equivalently, using them interchangeably) in the
  setUp/tearDown of unit tests will begin to experience test failures
  due to lack of test isolation.  The "right" mechanism is
  ``repoze.bfg.testing.cleanUp`` (or the combination of
  ``repoze.bfg.testing.setUp`` and
  ``repoze.bfg.testing.tearDown``). but a good number of legacy
  codebases will use ``zope.testing.cleanup.cleanUp`` instead.  We
  support ``zope.testing.cleanup.cleanUp`` but not in combination with
  ``repoze.bfg.testing.cleanUp`` in the same codebase.  You should use
  one or the other test cleanup function in a single codebase, but not
  both.
- In 0.8a7, the return value expected from an object implementing
  ``ITraverserFactory`` was changed from a sequence of values to a
  dictionary containing the keys ``context``, ``view_name``,
  ``subpath``, ``traversed``, ``virtual_root``, ``virtual_root_path``,
  and ``root``.  Until now, old-style traversers which returned a
  sequence have continued to work but have generated a deprecation
  warning.  In this release, traversers which return a sequence
  instead of a dictionary will no longer work.
- The interfaces ``IPOSTRequest``, ``IGETRequest``, ``IPUTRequest``,
  ``IDELETERequest``, and ``IHEADRequest`` have been removed from the
  ``repoze.bfg.interfaces`` module.  These were not documented as APIs
  post-1.0.  Instead of using one of these, use a ``request_method``
  ZCML attribute or ``request_method`` bfg_view decorator parameter
  containing an HTTP method name (one of ``GET``, ``POST``, ``HEAD``,
  ``PUT``, ``DELETE``) instead of one of these interfaces if you were
  using one explicitly.  Passing a string in the set (``GET``,
  ``HEAD``, ``PUT``, ``POST``, ``DELETE``) as a ``request_type``
  argument will work too.  Rationale: instead of relying on interfaces
  attached to the request object, BFG now uses a "view predicate" to
  determine the request type.
- Views registered without the help of the ZCML ``view`` directive are
  now responsible for performing their own authorization checking.
- The ``registry_manager`` backwards compatibility alias importable
  from "repoze.bfg.registry", deprecated since repoze.bfg 0.9 has been
  removed.  If you are tring to use the registry manager within a
  debug script of your own, use a combination of the
  "repoze.bfg.paster.get_app" and "repoze.bfg.scripting.get_root" APIs
  instead.
- The ``INotFoundAppFactory`` interface has been removed; it has
  been deprecated since repoze.bfg 0.9.  If you have something like
  the following in your ``configure.zcml``::
   <utility provides="repoze.bfg.interfaces.INotFoundAppFactory"
            component="helloworld.factories.notfound_app_factory"/>
  Replace it with something like::
   <notfound
       view="helloworld.views.notfound_view"/>
  See "Changing the Not Found View" in the "Hooks" chapter of the
  documentation for more information.
- The ``IUnauthorizedAppFactory`` interface has been removed; it has
  been deprecated since repoze.bfg 0.9.  If you have something like
  the following in your ``configure.zcml``::
   <utility provides="repoze.bfg.interfaces.IUnauthorizedAppFactory"
            component="helloworld.factories.unauthorized_app_factory"/>
  Replace it with something like::
   <forbidden
       view="helloworld.views.forbidden_view"/>
  See "Changing the Forbidden View" in the "Hooks" chapter of the
  documentation for more information.
- ``ISecurityPolicy``-based security policies, deprecated since
  repoze.bfg 0.9, have been removed.  If you have something like this
  in your ``configure.zcml``, it will no longer work::
   <utility
     provides="repoze.bfg.interfaces.ISecurityPolicy"
     factory="repoze.bfg.security.RemoteUserInheritingACLSecurityPolicy"
     />
   If ZCML like the above exists in your application, you will receive
   an error at startup time.  Instead of the above, you'll need
   something like::
     <remoteuserauthenticationpolicy/>
     <aclauthorizationpolicy/>
   This is just an example.  See the "Security" chapter of the
   repoze.bfg documentation for more information about configuring
   security policies.
Deprecations and Behavior Differences
-------------------------------------
- In previous versions of BFG, the "root factory" (the ``get_root``
  callable passed to ``make_app`` or a function pointed to by the
  ``factory`` attribute of a route) was called with a "bare" WSGI
  environment.  In this version, and going forward, it will be called
  with a ``request`` object.  The request object passed to the factory
  implements dictionary-like methods in such a way that existing root
  factory code which expects to be passed an environ will continue to
  work.
- The ``__call__`` of a plugin "traverser" implementation (registered
  as an adapter for ``ITraverser`` or ``ITraverserFactory``) will now
  receive a *request* as the single argument to its ``__call__``
  method.  In previous versions it was passed a WSGI ``environ``
  object.  The request object passed to the factory implements
  dictionary-like methods in such a way that existing traverser code
  which expects to be passed an environ will continue to work.
- The request implements dictionary-like methods that mutate and query
  the WSGI environ.  This is only for the purpose of backwards
  compatibility with root factories which expect an ``environ`` rather
  than a request.
- The order in which the router calls the request factory and the root
  factory has been reversed.  The request factory is now called first;
  the resulting request is passed to the root factory.
- Add ``setUp`` and ``tearDown`` functions to the
  ``repoze.bfg.testing`` module.  Using ``setUp`` in a test setup and
  ``tearDown`` in a test teardown is now the recommended way to do
  component registry setup and teardown.  Previously, it was
  recommended that a single function named
  ``repoze.bfg.testing.cleanUp`` be called in both the test setup and
  tear down.  ``repoze.bfg.testing.cleanUp`` still exists (and will
  exist "forever" due to its widespread use); it is now just an alias
  for ``repoze.bfg.testing.setUp`` and is nominally deprecated.
- The import of ``repoze.bfg.security.Unauthorized`` is deprecated in
  favor of ``repoze.bfg.exceptions.Forbidden``.  The old location
  still functions but emits a deprecation warning.  The rename from
  ``Unauthorized`` to ``Forbidden`` brings parity to the the name of
  the exception and the system view it invokes when raised.
- Custom ZCML directives which register an authentication or
  authorization policy (ala "authtktauthenticationpolicy" or
  "aclauthorizationpolicy") should register the policy "eagerly" in
  the ZCML directive instead of from within a ZCML action.  If an
  authentication or authorization policy is not found in the component
  registry by the view machinery during deferred ZCML processing, view
  security will not work as expected.
Dependency Changes
------------------
- When used under Python < 2.6, BFG now has an installation time
  dependency on the ``simplejson`` package.