diff --git a/CHANGES b/CHANGES index 03611cc8..6d0a0172 100644 --- a/CHANGES +++ b/CHANGES @@ -11,6 +11,8 @@ Release date to be announced, codename to be selected - Added :meth:`~flask.Flask.make_default_options_response` which can be used by subclasses to alter the default behaviour for `OPTIONS` responses. +- Unbound locals now raise a proper :exc:`RuntimeError` instead + of an :exc:`AttributeError`. Version 0.6.1 ------------- diff --git a/docs/upgrading.rst b/docs/upgrading.rst index 24966e7e..ba8e9947 100644 --- a/docs/upgrading.rst +++ b/docs/upgrading.rst @@ -19,6 +19,14 @@ installation, make sure to pass it the ``-U`` parameter:: $ easy_install -U Flask +Version 0.7 +----------- + +Due to a bug in earlier implementations the request local proxies now +raise a :exc:`RuntimeError` instead of an :exc:`AttributeError` when they +are unbound. If you cought these exceptions with :exc:`AttributeError` +before, you should catch them with :exc:`RuntimeError` now. + Version 0.6 ----------- diff --git a/flask/globals.py b/flask/globals.py index aac46555..84714105 100644 --- a/flask/globals.py +++ b/flask/globals.py @@ -10,11 +10,18 @@ :license: BSD, see LICENSE for more details. """ +from functools import partial from werkzeug import LocalStack, LocalProxy +def _lookup_object(name): + top = _request_ctx_stack.top + if top is None: + raise RuntimeError('working outside of request context') + return getattr(top, name) + # context locals _request_ctx_stack = LocalStack() -current_app = LocalProxy(lambda: _request_ctx_stack.top.app) -request = LocalProxy(lambda: _request_ctx_stack.top.request) -session = LocalProxy(lambda: _request_ctx_stack.top.session) -g = LocalProxy(lambda: _request_ctx_stack.top.g) +current_app = LocalProxy(partial(_lookup_object, 'app')) +request = LocalProxy(partial(_lookup_object, 'request')) +session = LocalProxy(partial(_lookup_object, 'session')) +g = LocalProxy(partial(_lookup_object, 'g')) diff --git a/tests/flask_tests.py b/tests/flask_tests.py index 2944f0ea..2f90a2f3 100644 --- a/tests/flask_tests.py +++ b/tests/flask_tests.py @@ -72,7 +72,7 @@ class ContextTestCase(unittest.TestCase): ctx.pop() try: index() - except AttributeError: + except RuntimeError: pass else: assert 0, 'expected runtime error' @@ -469,6 +469,10 @@ class BasicFunctionalityTestCase(unittest.TestCase): else: assert "Expected ValueError" + def test_request_locals(self): + self.assertEqual(repr(flask.g), '') + self.assertFalse(flask.g) + class JSONTestCase(unittest.TestCase):