diff options
| author | Chris McDonough <chrism@agendaless.com> | 2010-09-12 22:33:16 +0000 |
|---|---|---|
| committer | Chris McDonough <chrism@agendaless.com> | 2010-09-12 22:33:16 +0000 |
| commit | ad6a6706391c60dbdb66073caff1306b771da0bd (patch) | |
| tree | 058fa1f42f71069112b0258bb249730231941811 /repoze/bfg/request.py | |
| parent | 79c11cc905bcc5eae4f1b6e63aa187551966be34 (diff) | |
| download | pyramid-ad6a6706391c60dbdb66073caff1306b771da0bd.tar.gz pyramid-ad6a6706391c60dbdb66073caff1306b771da0bd.tar.bz2 pyramid-ad6a6706391c60dbdb66073caff1306b771da0bd.zip | |
- Add a new request API: ``request.add_finished_callback``. Finished
callbacks are called by the router unconditionally near the very end
of request processing.
Diffstat (limited to 'repoze/bfg/request.py')
| -rw-r--r-- | repoze/bfg/request.py | 55 |
1 files changed, 55 insertions, 0 deletions
diff --git a/repoze/bfg/request.py b/repoze/bfg/request.py index 6318faf5a..6e5417d9a 100644 --- a/repoze/bfg/request.py +++ b/repoze/bfg/request.py @@ -39,6 +39,7 @@ class Request(WebobRequest): """ implements(IRequest) response_callbacks = () + finished_callbacks = () default_charset = 'utf-8' def add_response_callback(self, callback): @@ -84,6 +85,60 @@ class Request(WebobRequest): callback(self, response) self.response_callbacks = () + def add_finished_callback(self, callback): + """ + Add a callback to the set of callbacks to be called + unconditionally by the :term:`router` at the very end of + request processing. + + ``callback`` is a callable which accepts a single positional + parameter: ``request``. For example: + + .. code-block:: python + :linenos: + + import transaction + + def commit_callback(request): + '''commit or abort the transaction associated with request''' + if hasattr(request, 'exception'): + transaction.abort() + else: + transaction.commit() + request.add_finished_callback(commit_callback) + + Finished callbacks are called in the order they're added ( + first- to most-recently- added). Finished callbacks (unlike + response callbacks) are *always* called, even if an exception + happens in application code that prevents a response from + being generated. + + The set of finished callbacks associated with a request are + called *very late* in the processing of that request; they are + essentially the last thing called by the :term:`router`. They + are called after response processing has already occurred in a + top-level ``finally:`` block within the router request + processing code. As a result, mutations performed to the + ``request`` provided to a finished callback will have no + meaningful effect, because response processing will have + already occurred, and the request's scope will expire almost + immediately after all finished callbacks have been processed. + + Errors raised by finished callbacks are not handled specially. + They will be propagated to the caller of the :mod:`repoze.bfg` + router application. """ + + callbacks = self.finished_callbacks + if not callbacks: + callbacks = [] + callbacks.append(callback) + self.finished_callbacks = callbacks + + def _process_finished_callbacks(self): + for callback in self.finished_callbacks: + callback(self) + self.finished_callbacks = () + # override default WebOb "environ['adhoc_attr']" mutation behavior __getattr__ = object.__getattribute__ __setattr__ = object.__setattr__ |
