From f34c0281252bf1838e2ec24fe8b064b232a098ef Mon Sep 17 00:00:00 2001 From: Armin Ronacher Date: Mon, 8 Oct 2012 07:01:49 +0200 Subject: [PATCH] Added template tests and made config a true global --- CHANGES | 7 +++++++ docs/templating.rst | 15 ++++++++++++--- flask/app.py | 11 +++++++---- flask/templating.py | 9 +++++---- flask/testsuite/templating.py | 12 ++++++++++++ 5 files changed, 43 insertions(+), 11 deletions(-) diff --git a/CHANGES b/CHANGES index 00978cdd..fd9d110c 100644 --- a/CHANGES +++ b/CHANGES @@ -23,6 +23,13 @@ Release date to be decided. - Removed deprecated internal ``flask.session`` module alias. Use ``flask.sessions`` instead to get the session module. This is not to be confused with ``flask.session`` the session proxy. +- Templates can now be rendered without request context. The behavior is + slightly different as the ``request``, ``session`` and ``g`` objects + will not be available and blueprint's context processors are not + called. +- The config object is now available to the template as a real global and + not through a context processor which makes it available even in imported + templates by default. Version 0.9 ----------- diff --git a/docs/templating.rst b/docs/templating.rst index 8ecf5332..166f26aa 100644 --- a/docs/templating.rst +++ b/docs/templating.rst @@ -38,20 +38,29 @@ by default: .. versionadded:: 0.6 + .. versionchanged:: 0.10 + This is now always available, even in imported templates. + .. data:: request :noindex: - The current request object (:class:`flask.request`) + The current request object (:class:`flask.request`). This variable is + unavailable if the template was rendered without an active request + context. .. data:: session :noindex: - The current session object (:class:`flask.session`) + The current session object (:class:`flask.session`). This variable + is unavailable if the template was rendered without an active request + context. .. data:: g :noindex: - The request-bound object for global variables (:data:`flask.g`) + The request-bound object for global variables (:data:`flask.g`). This + variable is unavailable if the template was rendered without an active + request context. .. function:: url_for :noindex: diff --git a/flask/app.py b/flask/app.py index 1763aa74..87ba933e 100644 --- a/flask/app.py +++ b/flask/app.py @@ -645,7 +645,8 @@ class Flask(_PackageBoundObject): rv = Environment(self, **options) rv.globals.update( url_for=url_for, - get_flashed_messages=get_flashed_messages + get_flashed_messages=get_flashed_messages, + config=self.config ) rv.filters['tojson'] = json.htmlsafe_dumps return rv @@ -694,9 +695,11 @@ class Flask(_PackageBoundObject): to add extra variables. """ funcs = self.template_context_processors[None] - bp = _request_ctx_stack.top.request.blueprint - if bp is not None and bp in self.template_context_processors: - funcs = chain(funcs, self.template_context_processors[bp]) + reqctx = _request_ctx_stack.top + if reqctx is not None: + bp = reqctx.request.blueprint + if bp is not None and bp in self.template_context_processors: + funcs = chain(funcs, self.template_context_processors[bp]) orig_ctx = context.copy() for func in funcs: context.update(func()) diff --git a/flask/templating.py b/flask/templating.py index e5d896cb..2bac22e9 100644 --- a/flask/templating.py +++ b/flask/templating.py @@ -12,7 +12,7 @@ import posixpath from jinja2 import BaseLoader, Environment as BaseEnvironment, \ TemplateNotFound -from .globals import _request_ctx_stack +from .globals import _request_ctx_stack, _app_ctx_stack from .signals import template_rendered from .module import blueprint_is_module @@ -22,8 +22,9 @@ def _default_template_ctx_processor(): `session` and `g`. """ reqctx = _request_ctx_stack.top + if reqctx is None: + return {} return dict( - config=reqctx.app.config, request=reqctx.request, session=reqctx.session, g=reqctx.g @@ -119,7 +120,7 @@ def render_template(template_name_or_list, **context): :param context: the variables that should be available in the context of the template. """ - ctx = _request_ctx_stack.top + ctx = _app_ctx_stack.top ctx.app.update_template_context(context) return _render(ctx.app.jinja_env.get_or_select_template(template_name_or_list), context, ctx.app) @@ -134,7 +135,7 @@ def render_template_string(source, **context): :param context: the variables that should be available in the context of the template. """ - ctx = _request_ctx_stack.top + ctx = _app_ctx_stack.top ctx.app.update_template_context(context) return _render(ctx.app.jinja_env.from_string(source), context, ctx.app) diff --git a/flask/testsuite/templating.py b/flask/testsuite/templating.py index 1df4292d..6345b710 100644 --- a/flask/testsuite/templating.py +++ b/flask/testsuite/templating.py @@ -37,6 +37,18 @@ class TemplatingTestCase(FlaskTestCase): rv = app.test_client().get('/') self.assert_equal(rv.data, '42') + def test_request_less_rendering(self): + app = flask.Flask(__name__) + app.config['WORLD_NAME'] = 'Special World' + @app.context_processor + def context_processor(): + return dict(foo=42) + + with app.app_context(): + rv = flask.render_template_string('Hello {{ config.WORLD_NAME }} ' + '{{ foo }}') + self.assert_equal(rv, 'Hello Special World 42') + def test_standard_context(self): app = flask.Flask(__name__) app.secret_key = 'development key'