Added support for signals

This commit is contained in:
Armin Ronacher 2010-07-17 14:39:28 +02:00
parent a59dfe4a77
commit e0712b47c6
10 changed files with 212 additions and 4 deletions

View file

@ -24,6 +24,10 @@ from .globals import current_app, g, request, session, _request_ctx_stack
from .module import Module
from .templating import render_template, render_template_string
# the signals
from .signals import signals_available, template_rendered, request_started, \
request_finished, got_request_exception
# only import json if it's available
if json_available:
from .helpers import json

View file

@ -32,6 +32,7 @@ from .session import Session, _NullSession
from .module import _ModuleSetupState
from .templating import _DispatchingJinjaLoader, \
_default_template_ctx_processor
from .signals import request_started, request_finished, got_request_exception
# a lock used for logger initialization
_logger_lock = Lock()
@ -657,6 +658,7 @@ class Flask(_PackageBoundObject):
.. versionadded: 0.3
"""
got_request_exception.send(self, exception=e)
handler = self.error_handlers.get(500)
if self.debug:
raise
@ -791,6 +793,7 @@ class Flask(_PackageBoundObject):
"""
with self.request_context(environ):
try:
request_started.send(self)
rv = self.preprocess_request()
if rv is None:
rv = self.dispatch_request()
@ -801,6 +804,7 @@ class Flask(_PackageBoundObject):
response = self.process_response(response)
except Exception, e:
response = self.make_response(self.handle_exception(e))
request_finished.send(self, response=response)
return response(environ, start_response)
def request_context(self, environ):

50
flask/signals.py Normal file
View file

@ -0,0 +1,50 @@
# -*- coding: utf-8 -*-
"""
flask.signals
~~~~~~~~~~~~~
Implements signals based on blinker if available, otherwise
falls silently back to a noop
:copyright: (c) 2010 by Armin Ronacher.
:license: BSD, see LICENSE for more details.
"""
signals_available = False
try:
from blinker import Namespace
signals_available = True
_signals = Namespace()
except ImportError:
class Namespace(object):
def signal(self, name, doc=None):
return _FakeSignal(name, doc)
class _FakeSignal(object):
"""If blinker is unavailable, create a fake class with the same
interface that allows sending of signals but will fail with an
error on anything else. Instead of doing anything on send, it
will just ignore the arguments and do nothing instead.
"""
def __init__(self, name, doc=None):
self.name = name
self.__doc__ = doc
def _fail(self, *args, **kwargs):
raise RuntimeError('signalling support is unavailable '
'because the blinker library is '
'not installed.')
send = lambda *a, **kw: None
connect = disconnect = has_receivers_for = receivers_for = \
temporarily_connected_to = _fail
del _fail
# the namespace for code signals. If you are not flask code, do
# not put signals in here. Create your own namespace instead.
_signals = Namespace()
# core signals. For usage examples grep the sourcecode or consult
# the API documentation in docs/api.rst as well as docs/signals.rst
template_rendered = _signals.signal('template-rendered')
request_started = _signals.signal('request-started')
request_finished = _signals.signal('request-finished')
got_request_exception = _signals.signal('got-request-exception')

View file

@ -11,6 +11,7 @@
from jinja2 import BaseLoader, FileSystemLoader, TemplateNotFound
from .globals import _request_ctx_stack
from .signals import template_rendered
def _default_template_ctx_processor():
@ -59,6 +60,13 @@ class _DispatchingJinjaLoader(BaseLoader):
return result
def _render(template, context, app):
"""Renders the template and fires the signal"""
rv = template.render(context)
template_rendered.send(app, template=template, context=context)
return rv
def render_template(template_name, **context):
"""Renders a template from the template folder with the given
context.
@ -69,7 +77,8 @@ def render_template(template_name, **context):
"""
ctx = _request_ctx_stack.top
ctx.app.update_template_context(context)
return ctx.app.jinja_env.get_template(template_name).render(context)
return _render(ctx.app.jinja_env.get_template(template_name),
context, ctx.app)
def render_template_string(source, **context):
@ -83,4 +92,5 @@ def render_template_string(source, **context):
"""
ctx = _request_ctx_stack.top
ctx.app.update_template_context(context)
return ctx.app.jinja_env.from_string(source).render(context)
return _render(ctx.app.jinja_env.from_string(source),
context, ctx.app)