From fbd488678f93c13527a9fba252bd89b53abec5e9 Mon Sep 17 00:00:00 2001 From: Armin Ronacher Date: Mon, 14 Mar 2011 16:13:58 -0400 Subject: [PATCH] Implemented flask.has_request_context() --- CHANGES | 1 + docs/api.rst | 2 ++ flask/__init__.py | 1 + flask/ctx.py | 32 ++++++++++++++++++++++++++++++++ tests/flask_tests.py | 12 ++++++++++++ 5 files changed, 48 insertions(+) diff --git a/CHANGES b/CHANGES index 32329ef8..9420dac6 100644 --- a/CHANGES +++ b/CHANGES @@ -39,6 +39,7 @@ Release date to be announced, codename to be selected - Implemented a silent flag for `config.from_pyfile`. - Added `teardown_request` decorator, for functions that should run at the end of a request regardless of whether an exception occurred. +- Implemented :func:`flask.has_request_context` Version 0.6.1 ------------- diff --git a/docs/api.rst b/docs/api.rst index fb604abf..c2d90ce6 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -224,6 +224,8 @@ Useful Functions and Classes This is a proxy. See :ref:`notes-on-proxies` for more information. +.. autofunction:: has_request_context + .. autofunction:: url_for .. function:: abort(code) diff --git a/flask/__init__.py b/flask/__init__.py index ee8508bc..3a232e5e 100644 --- a/flask/__init__.py +++ b/flask/__init__.py @@ -21,6 +21,7 @@ from .helpers import url_for, jsonify, json_available, flash, \ send_file, send_from_directory, get_flashed_messages, \ get_template_attribute, make_response from .globals import current_app, g, request, session, _request_ctx_stack +from .ctx import has_request_context from .module import Module from .templating import render_template, render_template_string from .session import Session diff --git a/flask/ctx.py b/flask/ctx.py index d3ac231d..b63f09f1 100644 --- a/flask/ctx.py +++ b/flask/ctx.py @@ -19,6 +19,38 @@ class _RequestGlobals(object): pass +def has_request_context(): + """If you have code that wants to test if a request context is there or + not this function can be used. For instance if you want to take advantage + of request information is it's available but fail silently if the request + object is unavailable. + + :: + + class User(db.Model): + + def __init__(self, username, remote_addr=None): + self.username = username + if remote_addr is None and has_request_context(): + remote_addr = request.remote_addr + self.remote_addr = remote_addr + + Alternatively you can also just test any of the context bound objects + (such as :class:`request` or :class:`g` for truthness):: + + class User(db.Model): + + def __init__(self, username, remote_addr=None): + self.username = username + if remote_addr is None and request: + remote_addr = request.remote_addr + self.remote_addr = remote_addr + + .. versionadded:: 0.7 + """ + return _request_ctx_stack.top is not None + + class _RequestContext(object): """The request context contains all request relevant information. It is created at the beginning of the request and pushed to the diff --git a/tests/flask_tests.py b/tests/flask_tests.py index e3631202..2283b0c2 100644 --- a/tests/flask_tests.py +++ b/tests/flask_tests.py @@ -89,6 +89,18 @@ class ContextTestCase(unittest.TestCase): assert meh() == 'http://localhost/meh' assert flask._request_ctx_stack.top is None + def test_context_test(self): + app = flask.Flask(__name__) + assert not flask.request + assert not flask.has_request_context() + ctx = app.test_request_context() + ctx.push() + try: + assert flask.request + assert flask.has_request_context() + finally: + ctx.pop() + def test_manual_context_binding(self): app = flask.Flask(__name__) @app.route('/')