summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris McDonough <chrism@agendaless.com>2009-11-02 02:31:31 +0000
committerChris McDonough <chrism@agendaless.com>2009-11-02 02:31:31 +0000
commita53cbfbb503010d34c9c02fdaf6eccc56361c7a2 (patch)
tree357e420ac0d4ad95183547eca228070a149eef99
parentc32dd3a6664d4112d6e706809cbbbc0b8128a152 (diff)
downloadpyramid-a53cbfbb503010d34c9c02fdaf6eccc56361c7a2.tar.gz
pyramid-a53cbfbb503010d34c9c02fdaf6eccc56361c7a2.tar.bz2
pyramid-a53cbfbb503010d34c9c02fdaf6eccc56361c7a2.zip
- "What's New in ``repoze.bfg`` 1.1" document added to narrative
documentation. - Minor typo fixes.
-rw-r--r--CHANGES.txt39
-rw-r--r--docs/index.rst12
-rw-r--r--docs/narr/urldispatch.rst2
-rw-r--r--docs/narr/views.rst68
-rw-r--r--docs/whatsnew-1.1.rst742
5 files changed, 808 insertions, 55 deletions
diff --git a/CHANGES.txt b/CHANGES.txt
index 281b3e4cb..f0c4879cb 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -9,6 +9,9 @@ Documentation
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 @@ Internal
- 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 @@ Documentation
- 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
@@ -889,22 +908,6 @@ Documentation
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.
diff --git a/docs/index.rst b/docs/index.rst
index 5fcdfb225..efed839c9 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -15,6 +15,14 @@ responses.
<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 @@ Using ZODB Sessions in :mod:`repoze.bfg`
tutorials/zodbsessions/index.rst
-Change History
-==============
+Detailed Change History
+=======================
.. toctree::
:maxdepth: 1
diff --git a/docs/narr/urldispatch.rst b/docs/narr/urldispatch.rst
index e2031ec4e..dd20ae7f4 100644
--- a/docs/narr/urldispatch.rst
+++ b/docs/narr/urldispatch.rst
@@ -87,7 +87,7 @@ view
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
diff --git a/docs/narr/views.rst b/docs/narr/views.rst
index e17f3d201..88ae12764 100644
--- a/docs/narr/views.rst
+++ b/docs/narr/views.rst
@@ -210,7 +210,7 @@ View configuration can vary the renderer associated with a view via
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 @@ attr
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 @@ for
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',
@@ -476,34 +504,6 @@ containment
.. 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
Thie value should be either ``True`` or ``False``. If this value is
diff --git a/docs/whatsnew-1.1.rst b/docs/whatsnew-1.1.rst
new file mode 100644
index 000000000..33d811727
--- /dev/null
+++ b/docs/whatsnew-1.1.rst
@@ -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.
+