Skip to content

Commit faa1c71

Browse files
committed
Request local objects now fail properly with a RuntimeError. This fixes pallets#105
1 parent d17b6d7 commit faa1c71

File tree

4 files changed

+26
-5
lines changed

4 files changed

+26
-5
lines changed

CHANGES

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ Release date to be announced, codename to be selected
1111
- Added :meth:`~flask.Flask.make_default_options_response`
1212
which can be used by subclasses to alter the default
1313
behaviour for `OPTIONS` responses.
14+
- Unbound locals now raise a proper :exc:`RuntimeError` instead
15+
of an :exc:`AttributeError`.
1416

1517
Version 0.6.1
1618
-------------

docs/upgrading.rst

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,14 @@ installation, make sure to pass it the ``-U`` parameter::
1919

2020
$ easy_install -U Flask
2121

22+
Version 0.7
23+
-----------
24+
25+
Due to a bug in earlier implementations the request local proxies now
26+
raise a :exc:`RuntimeError` instead of an :exc:`AttributeError` when they
27+
are unbound. If you cought these exceptions with :exc:`AttributeError`
28+
before, you should catch them with :exc:`RuntimeError` now.
29+
2230
Version 0.6
2331
-----------
2432

flask/globals.py

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,18 @@
1010
:license: BSD, see LICENSE for more details.
1111
"""
1212

13+
from functools import partial
1314
from werkzeug import LocalStack, LocalProxy
1415

16+
def _lookup_object(name):
17+
top = _request_ctx_stack.top
18+
if top is None:
19+
raise RuntimeError('working outside of request context')
20+
return getattr(top, name)
21+
1522
# context locals
1623
_request_ctx_stack = LocalStack()
17-
current_app = LocalProxy(lambda: _request_ctx_stack.top.app)
18-
request = LocalProxy(lambda: _request_ctx_stack.top.request)
19-
session = LocalProxy(lambda: _request_ctx_stack.top.session)
20-
g = LocalProxy(lambda: _request_ctx_stack.top.g)
24+
current_app = LocalProxy(partial(_lookup_object, 'app'))
25+
request = LocalProxy(partial(_lookup_object, 'request'))
26+
session = LocalProxy(partial(_lookup_object, 'session'))
27+
g = LocalProxy(partial(_lookup_object, 'g'))

tests/flask_tests.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ def index():
7272
ctx.pop()
7373
try:
7474
index()
75-
except AttributeError:
75+
except RuntimeError:
7676
pass
7777
else:
7878
assert 0, 'expected runtime error'
@@ -469,6 +469,10 @@ def test():
469469
else:
470470
assert "Expected ValueError"
471471

472+
def test_request_locals(self):
473+
self.assertEqual(repr(flask.g), '<LocalProxy unbound>')
474+
self.assertFalse(flask.g)
475+
472476

473477
class JSONTestCase(unittest.TestCase):
474478

0 commit comments

Comments
 (0)