Next Release ============ Backwards Incompatibilities --------------------------- - The ``repoze.bfg.templating`` module has been removed; it had been deprecated in 1.1 and never actually had any APIs in it. 1.2a2 (2009-11-29) ================== Bug Fixes --------- - The the long description of this package (as shown on PyPI) was not valid reStructuredText, and so was not renderable. - Trying to use an HTTP method name string such as ``GET`` as a ``request_type`` predicate argument caused a startup time failure when it was encountered in imperative configuration or in a decorator (symptom: ``Type Error: Required specification must be a specification``). This now works again, although ``request_method`` is now the preferred predicate argument for associating a view configuration with an HTTP request method. Documentation ------------- - Fixed "Startup" narrative documentation chapter; it was explaining "the old way" an application constructor worked. 1.2a1 (2009-11-28) ================== Features -------- - An imperative configuration mode. A ``repoze.bfg`` application can now begin its life as a single Python file. Later, the application might evolve into a set of Python files in a package. Even later, it might start making use of other configuration features, such as ``ZCML``. But neither the use of a package nor the use of non-imperative configuration is required to create a simple ``repoze.bfg`` application any longer. Imperative configuration makes ``repoze.bfg`` competetive with "microframeworks" such as `Bottle `_ and `Tornado `_. ``repoze.bfg`` has a good deal of functionality that most microframeworks lack, so this is hopefully a "best of both worlds" feature. The simplest possible ``repoze.bfg`` application is now:: from webob import Response from wsgiref import simple_server from repoze.bfg.configuration import Configurator def hello_world(request): return Response('Hello world!') if __name__ == '__main__': config = Configurator() config.add_view(hello_world) app = config.make_wsgi_app() simple_server.make_server('', 8080, app).serve_forever() - A new class now exists: ``repoze.bfg.configuration.Configurator``. This class forms the basis for sharing machinery between "imperatively" configured applications and traditional declaratively-configured applications. - The ``repoze.bfg.testing.setUp`` function now accepts three extra optional keyword arguments: ``registry``, ``request`` and ``hook_zca``. If the ``registry`` argument is not ``None``, the argument will be treated as the registry that is set as the "current registry" (it will be returned by ``repoze.bfg.threadlocal.get_current_registry``) for the duration of the test. If the ``registry`` argument is ``None`` (the default), a new registry is created and used for the duration of the test. The value of the ``request`` argument is used as the "current request" (it will be returned by ``repoze.bfg.threadlocal.get_current_request``) for the duration of the test; it defaults to ``None``. If ``hook_zca`` is ``True`` (the default), the ``zope.component.getSiteManager`` function will be hooked with a function that returns the value of ``registry`` (or the default-created registry if ``registry`` is ``None``) instead of the registry returned by ``zope.component.getGlobalSiteManager``, causing the Zope Component Architecture API (``getSiteManager``, ``getAdapter``, ``getUtility``, and so on) to use the testing registry instead of the global ZCA registry. - The ``repoze.bfg.testing.tearDown`` function now accepts an ``unhook_zca`` argument. If this argument is ``True`` (the default), ``zope.component.getSiteManager.reset()`` will be called. This will cause the result of the ``zope.component.getSiteManager`` function to be the global ZCA registry (the result of ``zope.component.getGlobalSiteManager``) once again. - The ``run.py`` module in various ``repoze.bfg`` ``paster`` templates now use a ``repoze.bfg.configuration.Configurator`` class instead of the (now-legacy) ``repoze.bfg.router.make_app`` function to produce a WSGI application. Documentation ------------- - The documentation now uses the "request-only" view calling convention in most examples (as opposed to the ``context, request`` convention). This is a documentation-only change; the ``context, request`` convention is also supported and documented, and will be "forever". - ``repoze.bfg.configuration`` API documentation has been added. - A narrative documentation chapter entitled "Creating Your First ``repoze.bfg`` Application" has been added. This chapter details usage of the new ``repoze.bfg.configuration.Configurator`` class, and demonstrates a simplified "imperative-mode" configuration; doing ``repoze.bfg`` application configuration imperatively was previously much more difficult. - A narrative documentation chapter entitled "Configuration, Decorations and Code Scanning" explaining ZCML- vs. imperative- vs. decorator-based configuration equivalence. - The "ZCML Hooks" chapter has been renamed to "Hooks"; it documents how to override hooks now via imperative configuration and ZCML. - The explanation about how to supply an alternate "response factory" has been removed from the "Hooks" chapter. This feature may be removed in a later release (it still works now, it's just not documented). - Add a section entitled "Test Set Up and Tear Down" to the unittesting chapter. Bug Fixes ---------- - The ACL authorization policy debugging output when ``debug_authorization`` console debugging output was turned on wasn't as clear as it could have been when a view execution was denied due to an authorization failure resulting from the set of principals passed never having matched any ACE in any ACL in the lineage. Now in this case, we report ```` as the ACE value and either the root ACL or ```` if no ACL was found. - When two views were registered with the same ``accept`` argument, but were otherwise registered with the same arguments, if a request entered the application which had an ``Accept`` header that accepted *either* of the media types defined by the set of views registered with predicates that otherwise matched, a more or less "random" one view would "win". Now, we try harder to use the view callable associated with the view configuration that has the most specific ``accept`` argument. Thanks to Alberto Valverde for an initial patch. Internals --------- - The routes mapper is no longer a root factory wrapper. It is now consulted directly by the router. - The ``repoze.bfg.registry.make_registry`` callable has been removed. - The ``repoze.bfg.view.map_view`` callable has been removed. - The ``repoze.bfg.view.owrap_view`` callable has been removed. - The ``repoze.bfg.view.predicate_wrap`` callable has been removed. - The ``repoze.bfg.view.secure_view`` callable has been removed. - The ``repoze.bfg.view.authdebug_view`` callable has been removed. - The ``repoze.bfg.view.renderer_from_name`` callable has been removed. Use ``repoze.bfg.configuration.Configurator.renderer_from_name`` instead (still not an API, however). - The ``repoze.bfg.view.derive_view`` callable has been removed. Use ``repoze.bfg.configuration.Configurator.derive_view`` instead (still not an API, however). - The ``repoze.bfg.settings.get_options`` callable has been removed. Its job has been subsumed by the ``repoze.bfg.settings.Settings`` class constructor. - The ``repoze.bfg.view.requestonly`` function has been moved to ``repoze.bfg.configuration.requestonly``. - The ``repoze.bfg.view.rendered_response`` function has been moved to ``repoze.bfg.configuration.rendered_response``. - The ``repoze.bfg.view.decorate_view`` function has been moved to ``repoze.bfg.configuration.decorate_view``. - The ``repoze.bfg.view.MultiView`` class has been moved to ``repoze.bfg.configuration.MultiView``. - The ``repoze.bfg.zcml.Uncacheable`` class has been removed. - The ``repoze.bfg.resource.resource_spec`` function has been removed. - All ZCML directives which deal with attributes which are paths now use the ``path`` method of the ZCML context to resolve a relative name to an absolute one (imperative configuration requirement). - The ``repoze.bfg.scripting.get_root`` API now uses a 'real' WebOb request rather than a FakeRequest when it sets up the request as a threadlocal. - The ``repoze.bfg.traversal.traverse`` API now uses a 'real' WebOb request rather than a FakeRequest when it calls the traverser. - The ``repoze.bfg.request.FakeRequest`` class has been removed. - Most uses of the ZCA threadlocal API (the ``getSiteManager``, ``getUtility``, ``getAdapter``, ``getMultiAdapter`` threadlocal API) have been removed from the core. Instead, when a threadlocal is necessary, the core uses the ``repoze.bfg.threadlocal.get_current_registry`` API to obtain the registry. - The internal ILogger utility named ``repoze.bfg.debug`` is now just an IDebugLogger unnamed utility. A named utility with the old name is registered for b/w compat. - The ``repoze.bfg.interfaces.ITemplateRendererFactory`` interface was removed; it has become unused. - Instead of depending on the ``martian`` package to do code scanning, we now just use our own scanning routines. - We now no longer have a dependency on ``repoze.zcml`` package; instead, the ``repoze.bfg`` package includes implementations of the ``adapter``, ``subscriber`` and ``utility`` directives. - Relating to the following functions: ``repoze.bfg.view.render_view`` ``repoze.bfg.view.render_view_to_iterable`` ``repoze.bfg.view.render_view_to_response`` ``repoze.bfg.view.append_slash_notfound_view`` ``repoze.bfg.view.default_notfound_view`` ``repoze.bfg.view.default_forbidden_view`` ``repoze.bfg.configuration.rendered_response`` ``repoze.bfg.security.has_permission`` ``repoze.bfg.security.authenticated_userid`` ``repoze.bfg.security.effective_principals`` ``repoze.bfg.security.view_execution_permitted`` ``repoze.bfg.security.remember`` ``repoze.bfg.security.forget`` ``repoze.bfg.url.route_url`` ``repoze.bfg.url.model_url`` ``repoze.bfg.url.static_url`` ``repoze.bfg.traversal.virtual_root`` Each of these functions now expects to be called with a request object that has a ``registry`` attribute which represents the current ``repoze.bfg`` registry. They fall back to obtaining the registry from the threadlocal API. Backwards Incompatibilites -------------------------- - Unit tests which use ``zope.testing.cleanup.cleanUp`` for the purpose of isolating tests from one another may now begin to fail due to lack of isolation between tests. Here's why: In repoze.bfg 1.1 and prior, the registry returned by ``repoze.bfg.threadlocal.get_current_registry`` when no other registry had been pushed on to the threadlocal stack was the ``zope.component.globalregistry.base`` global registry (aka the result of ``zope.component.getGlobalSiteManager()``). In repoze.bfg 1.2+, however, the registry returned in this situation is the new module-scope ``repoze.bfg.registry.global_registry`` object. The ``zope.testing.cleanup.cleanUp`` function clears the ``zope.component.globalregistry.base`` global registry unconditionally. However, it does not know about the ``repoze.bfg.registry.global_registry`` object, so it does not clear it. If you use the ``zope.testing.cleanup.cleanUp`` function in the ``setUp`` of test cases in your unit test suite instead of using the (more correct as of 1.1) ``repoze.bfg.testing.setUp``, you will need to replace all calls to ``zope.testing.cleanup.cleanUp`` with a call to ``repoze.bfg.testing.setUp``. If replacing all calls to ``zope.testing.cleanup.cleanUp`` with a call to ``repoze.bfg.testing.setUp`` is infeasible, you can put this bit of code somewhere that is executed exactly **once** (*not* for each test in a test suite; in the `` __init__.py`` of your package or your package's ``tests`` subpackage would be a reasonable place):: import zope.testing.cleanup from repoze.bfg.testing import setUp zope.testing.cleanup.addCleanUp(setUp) - When there is no "current registry" in the ``repoze.bfg.threadlocal.manager`` threadlocal data structure (this is the case when there is no "current request" or we're not in the midst of a ``r.b.testing.setUp``-bounded unit test), the ``.get`` method of the manager returns a data structure containing a *global* registry. In previous releases, this function returned the global Zope "base" registry: the result of ``zope.component.getGlobalSiteManager``, which is an instance of the ``zope.component.registry.Component`` class. In this release, however, the global registry returns a globally importable instance of the ``repoze.bfg.registry.Registry`` class. This registry instance can always be imported as ``repoze.bfg.registry.global_registry``. Effectively, this means that when you call ``repoze.bfg.threadlocal.get_current_registry`` when no request or ``setUp`` bounded unit test is in effect, you will always get back the global registry that lives in ``repoze.bfg.registry.global_registry``. It also means that ``repoze.bfg`` APIs that *call* ``get_current_registry`` will use this registry. This change was made because ``repoze.bfg`` now expects the registry it uses to have a slightly different API than a bare instance of ``zope.component.registry.Components``. - View registration no longer registers a ``repoze.bfg.interfaces.IViewPermission`` adapter (it is no longer checked by the framework; since 1.1, views have been responsible for providing their own security). - The ``repoze.bfg.router.make_app`` callable no longer accepts the ``authentication_policy`` nor the ``authorization_policy`` arguments. This feature was deprecated in version 1.0 and has been removed. - Obscure: the machinery which configured views with a ``request_type`` *and* a ``route_name`` would ignore the request interface implied by ``route_name`` registering a view only for the interface implied by ``request_type``. In the unlikely event that you were trying to use these two features together, the symptom would have been that views that named a ``request_type`` but which were also associated with routes were not found when the route matched. Now if a view is configured with both a ``request_type`` and a ``route_name``, an error is raised. - The ``route`` ZCML directive now no longer accepts the ``request_type`` or ``view_request_type`` attributes. These attributes didn't actually work in any useful way (see entry above this one). - Because the ``repoze.bfg`` package now includes implementations of the ``adapter``, ``subscriber`` and ``utility`` ZCML directives, it is now an error to have ```` in the ZCML of a ``repoze.bfg`` application. A ZCML conflict error will be raised if your ZCML does so. This shouldn't be an issue for "normal" installations; it has always been the responsibility of the ``repoze.bfg.includes`` ZCML to include this file in the past; it now just doesn't. - The ``repoze.bfg.testing.zcml_configure`` API was removed. Use the ``Configurator.load_zcml`` API instead. Deprecations ------------ - The ``repoze.bfg.router.make_app`` function is now nominally deprecated. Its import and usage does not throw a warning, nor will it probably ever disappear. However, using a ``repoze.bfg.configuration.Configurator`` class is now the preferred way to generate a WSGI application. Note that ``make_app`` calls ``zope.component.getSiteManager.sethook( repoze.bfg.threadlocal.get_current_registry)`` on the caller's behalf, hooking ZCA global API lookups, for backwards compatibility purposes. If you disuse ``make_app``, your calling code will need to perform this call itself, at least if your application uses the ZCA global API (``getSiteManager``, ``getAdapter``, etc). Dependencies ------------ - A dependency on the ``martian`` package has been removed (its functionality is replaced internally). - A dependency on the ``repoze.zcml`` package has been removed (its functionality is replaced internally).