diff --git a/flask/__init__.py b/flask/__init__.py index 54bfedda..f35ef328 100644 --- a/flask/__init__.py +++ b/flask/__init__.py @@ -23,7 +23,8 @@ from .config import Config from .helpers import url_for, jsonify, json_available, flash, \ send_file, send_from_directory, get_flashed_messages, \ get_template_attribute, make_response, safe_join -from .globals import current_app, g, request, session, _request_ctx_stack +from .globals import current_app, g, request, session, _request_ctx_stack, \ + _app_ctx_stack from .ctx import has_request_context from .module import Module from .blueprints import Blueprint diff --git a/flask/helpers.py b/flask/helpers.py index 26be5e30..b86ce158 100644 --- a/flask/helpers.py +++ b/flask/helpers.py @@ -200,6 +200,9 @@ def url_for(endpoint, **values): """ appctx = _app_ctx_stack.top reqctx = _request_ctx_stack.top + if appctx is None: + raise RuntimeError('Attempted to generate a URL with the application ' + 'context being pushed. This has to be executed ') # If request specific information is available we have some extra # features that support "relative" urls. @@ -225,6 +228,11 @@ def url_for(endpoint, **values): # the urls external by default. else: url_adapter = appctx.url_adapter + if url_adapter is None: + raise RuntimeError('Application was not able to create a URL ' + 'adapter for request independent URL generation. ' + 'You might be able to fix this by setting ' + 'the SERVER_NAME config variable.') external = values.pop('_external', True) anchor = values.pop('_anchor', None) diff --git a/flask/testsuite/appctx.py b/flask/testsuite/appctx.py index 2c198047..c60dbc67 100644 --- a/flask/testsuite/appctx.py +++ b/flask/testsuite/appctx.py @@ -18,7 +18,7 @@ from flask.testsuite import FlaskTestCase class AppContextTestCase(FlaskTestCase): - def test_basic_support(self): + def test_basic_url_generation(self): app = flask.Flask(__name__) app.config['SERVER_NAME'] = 'localhost' app.config['PREFERRED_URL_SCHEME'] = 'https' @@ -31,6 +31,28 @@ class AppContextTestCase(FlaskTestCase): rv = flask.url_for('index') self.assert_equal(rv, 'https://localhost/') + def test_url_generation_requires_server_name(self): + app = flask.Flask(__name__) + with app.app_context(): + with self.assert_raises(RuntimeError): + flask.url_for('index') + + def test_url_generation_without_context_fails(self): + with self.assert_raises(RuntimeError): + flask.url_for('index') + + def test_request_context_means_app_context(self): + app = flask.Flask(__name__) + with app.test_request_context(): + self.assert_equal(flask.current_app._get_current_object(), app) + self.assert_equal(flask._app_ctx_stack.top, None) + + def test_app_context_provides_current_app(self): + app = flask.Flask(__name__) + with app.app_context(): + self.assert_equal(flask.current_app._get_current_object(), app) + self.assert_equal(flask._app_ctx_stack.top, None) + def suite(): suite = unittest.TestSuite()