summaryrefslogtreecommitdiff
path: root/docs/whatsnew-1.2.rst
blob: 862bef375078b063ba6d26a22d8338bb1e22cdbf (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
What's New In :mod:`repoze.bfg` 1.2
===================================

This article explains the new features in :mod:`repoze.bfg` version
1.2 as compared to the previous 1.1 release.  It also documents
backwards incompatibilities between the two versions and deprecations
added to 1.2, as well as software dependency changes and notable
documentation additions.

Major Feature Additions
-----------------------

The major feature addition in 1.2 is an :term:`imperative
configuration` mode.

A :mod:`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 :term:`ZCML` and perhaps a
:term:`scan`.  But neither the use of a package nor the use of
non-imperative configuration is required to create a simple
:mod:`repoze.bfg` application any longer.

:term:`Imperative configuration` makes :mod:`repoze.bfg` competitive
with "microframeworks" such as `Bottle <http://bottle.paws.de/>`_ and
`Tornado <http://www.tornadoweb.org/>`_.  :mod:`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 :mod:`repoze.bfg` application is now:

  .. code-block:: python
     :linenos:

     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()

For an introduction to imperative-mode configuration, see
:ref:`configuration_narr`.

Minor Miscellaneous Feature Additions
-------------------------------------

- 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.

- ``repoze.bfg.testing.DummyModel`` now accepts a new constructor
  keyword argument: ``__provides__``.  If this constructor argument is
  provided, it should be an interface or a tuple of interfaces.  The
  resulting model will then provide these interfaces (they will be
  attached to the constructed model via
  ``zope.interface.alsoProvides``).

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 the
  below-mentioned bit of code somewhere that is executed exactly
  **once** (*not* for each test in a test suite).  Placing this in the
  ``__init__.py`` of your package or the ``__init__.py`` of a
  ``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
  :mod:`repoze.bfg` APIs that *call* ``get_current_registry`` will use
  this registry.

  This change was made because :mod:`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 ``<include package="repoze.zcml"
  file="meta.zcml"/>`` 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.

- The ``repoze.bfg.templating`` module has been removed; it had been
  deprecated in 1.1 and hasn't possessed any APIs since before 1.0.

Deprecations and Behavior Differences
-------------------------------------

- 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).

Dependency Changes
------------------

- 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).

Documentation Enhancements
--------------------------

- 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.