diff options
Diffstat (limited to 'docs')
| -rw-r--r-- | docs/index.rst | 12 | ||||
| -rw-r--r-- | docs/narr/urldispatch.rst | 2 | ||||
| -rw-r--r-- | docs/narr/views.rst | 68 | ||||
| -rw-r--r-- | docs/whatsnew-1.1.rst | 742 |
4 files changed, 787 insertions, 37 deletions
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. + |
