diff --git a/CHANGES b/CHANGES index e02a393b..b414f5ad 100644 --- a/CHANGES +++ b/CHANGES @@ -3,6 +3,22 @@ Flask Changelog Here you can see the full list of changes between each Flask release. +Version 0.7.2 +------------- + +Bugfix release, released on July 6th 2011 + +- Fixed an issue with URL processors not properly working on + blueprints. + +Version 0.7.1 +------------- + +Bugfix release, released on June 29th 2011 + +- Added missing future import that broke 2.5 compatibility. +- Fixed an infinite redirect issue with blueprints. + Version 0.7 ----------- diff --git a/flask/__init__.py b/flask/__init__.py index 1c5e3ba2..0f1b97e3 100644 --- a/flask/__init__.py +++ b/flask/__init__.py @@ -10,7 +10,7 @@ :license: BSD, see LICENSE for more details. """ -__version__ = '0.8-dev' +__version__ = '0.7.2' # utilities we import from Werkzeug and Jinja2 that are unused # in the module but are exported as public interface. diff --git a/flask/app.py b/flask/app.py index eb7ba023..dff4272b 100644 --- a/flask/app.py +++ b/flask/app.py @@ -706,6 +706,12 @@ class Flask(_PackageBoundObject): if 'OPTIONS' not in methods: methods = tuple(methods) + ('OPTIONS',) provide_automatic_options = True + + # due to a werkzeug bug we need to make sure that the defaults are + # None if they are an empty dictionary. This should not be necessary + # with Werkzeug 0.7 + options['defaults'] = options.get('defaults') or None + rule = self.url_rule_class(rule, methods=methods, **options) rule.provide_automatic_options = provide_automatic_options self.url_map.add(rule) diff --git a/flask/blueprints.py b/flask/blueprints.py index a0dfd521..0c3a7d0f 100644 --- a/flask/blueprints.py +++ b/flask/blueprints.py @@ -56,7 +56,7 @@ class BlueprintSetupState(object): #: A dictionary with URL defaults that is added to each and every #: URL that was defined with the blueprint. - self.url_defaults = dict(self.blueprint.url_defaults) + self.url_defaults = dict(self.blueprint.url_values_defaults) self.url_defaults.update(self.options.get('url_defaults', ())) def add_url_rule(self, rule, endpoint=None, view_func=None, **options): @@ -102,7 +102,7 @@ class Blueprint(_PackageBoundObject): self.view_functions = {} if url_defaults is None: url_defaults = {} - self.url_defaults = url_defaults + self.url_values_defaults = url_defaults def record(self, func): """Registers a function that is called when the blueprint is diff --git a/flask/templating.py b/flask/templating.py index d50691b3..147f49d0 100644 --- a/flask/templating.py +++ b/flask/templating.py @@ -117,8 +117,6 @@ def render_template(template_name, **context): """ ctx = _request_ctx_stack.top ctx.app.update_template_context(context) - if template_name[:1] == ':': - template_name = ctx.request.blueprint + template_name return _render(ctx.app.jinja_env.get_template(template_name), context, ctx.app) diff --git a/scripts/make-release.py b/scripts/make-release.py index 9955b13e..574cb75d 100644 --- a/scripts/make-release.py +++ b/scripts/make-release.py @@ -33,8 +33,8 @@ def parse_changelog(): if change_info: break - match = re.match(r'^released on (\w+\s+\d+\w+\s+\d+)' - r'(?:, codename (.*))?(?i)', change_info) + match = re.search(r'released on (\w+\s+\d+\w+\s+\d+)' + r'(?:, codename (.*))?(?i)', change_info) if match is None: continue diff --git a/setup.py b/setup.py index 1809e05e..92a0b5d9 100644 --- a/setup.py +++ b/setup.py @@ -86,7 +86,7 @@ def run_tests(): setup( name='Flask', - version='0.8-dev', + version='0.7.2', url='http://github.com/mitsuhiko/flask/', license='BSD', author='Armin Ronacher', diff --git a/tests/flask_tests.py b/tests/flask_tests.py index e04c2458..e13dfd36 100644 --- a/tests/flask_tests.py +++ b/tests/flask_tests.py @@ -830,6 +830,37 @@ class BasicFunctionalityTestCase(unittest.TestCase): rv = c.post('/accept', data={'myfile': 'foo' * 100}) assert rv.data == '42' + def test_url_processors(self): + app = flask.Flask(__name__) + + @app.url_defaults + def add_language_code(endpoint, values): + if flask.g.lang_code is not None and \ + app.url_map.is_endpoint_expecting(endpoint, 'lang_code'): + values.setdefault('lang_code', flask.g.lang_code) + + @app.url_value_preprocessor + def pull_lang_code(endpoint, values): + flask.g.lang_code = values.pop('lang_code', None) + + @app.route('//') + def index(): + return flask.url_for('about') + + @app.route('//about') + def about(): + return flask.url_for('something_else') + + @app.route('/foo') + def something_else(): + return flask.url_for('about', lang_code='en') + + c = app.test_client() + + self.assertEqual(c.get('/de/').data, '/de/about') + self.assertEqual(c.get('/de/about').data, '/foo') + self.assertEqual(c.get('/foo').data, '/en/about') + class JSONTestCase(unittest.TestCase): @@ -1309,6 +1340,33 @@ class BlueprintTestCase(unittest.TestCase): self.assertEqual(c.get('/1/bar').data, u'23') self.assertEqual(c.get('/2/bar').data, u'19') + def test_blueprint_url_processors(self): + bp = flask.Blueprint('frontend', __name__, url_prefix='/') + + @bp.url_defaults + def add_language_code(endpoint, values): + values.setdefault('lang_code', flask.g.lang_code) + + @bp.url_value_preprocessor + def pull_lang_code(endpoint, values): + flask.g.lang_code = values.pop('lang_code') + + @bp.route('/') + def index(): + return flask.url_for('.about') + + @bp.route('/about') + def about(): + return flask.url_for('.index') + + app = flask.Flask(__name__) + app.register_blueprint(bp) + + c = app.test_client() + + self.assertEqual(c.get('/de/').data, '/de/about') + self.assertEqual(c.get('/de/about').data, '/de/') + def test_templates_and_static(self): from blueprintapp import app c = app.test_client() @@ -1364,6 +1422,21 @@ class BlueprintTestCase(unittest.TestCase): self.assertEqual(c.get('/fe2').data.strip(), '/fe') self.assertEqual(c.get('/be').data.strip(), '/fe') + def test_empty_url_defaults(self): + bp = flask.Blueprint('bp', __name__) + + @bp.route('/', defaults={'page': 1}) + @bp.route('/page/') + def something(page): + return str(page) + + app = flask.Flask(__name__) + app.register_blueprint(bp) + + c = app.test_client() + self.assertEqual(c.get('/').data, '1') + self.assertEqual(c.get('/page/2').data, '2') + class SendfileTestCase(unittest.TestCase):