From 68ec5a30687a89a56406d8abd603b51a6645856e Mon Sep 17 00:00:00 2001 From: Pedro Algarvio Date: Thu, 25 Aug 2011 11:46:05 +0100 Subject: [PATCH 1/5] Allow passing the endpoint to the route decorators on Flask's `application` and `blueprints`. --- flask/app.py | 3 ++- flask/blueprints.py | 3 ++- tests/flask_tests.py | 60 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 64 insertions(+), 2 deletions(-) diff --git a/flask/app.py b/flask/app.py index 35577984..0597ba5b 100644 --- a/flask/app.py +++ b/flask/app.py @@ -942,7 +942,8 @@ class Flask(_PackageBoundObject): :class:`~werkzeug.routing.Rule` object. """ def decorator(f): - self.add_url_rule(rule, None, f, **options) + endpoint = options.pop("endpoint", None) + self.add_url_rule(rule, endpoint, f, **options) return f return decorator diff --git a/flask/blueprints.py b/flask/blueprints.py index 075961ab..6d693781 100644 --- a/flask/blueprints.py +++ b/flask/blueprints.py @@ -157,7 +157,8 @@ class Blueprint(_PackageBoundObject): :func:`url_for` function is prefixed with the name of the blueprint. """ def decorator(f): - self.add_url_rule(rule, f.__name__, f, **options) + endpoint = options.pop("endpoint", f.__name__) + self.add_url_rule(rule, endpoint, f, **options) return f return decorator diff --git a/tests/flask_tests.py b/tests/flask_tests.py index 220bf4cb..3753218e 100644 --- a/tests/flask_tests.py +++ b/tests/flask_tests.py @@ -1005,6 +1005,32 @@ class BasicFunctionalityTestCase(unittest.TestCase): rv = c.post('/foo', data={}, follow_redirects=True) self.assertEqual(rv.data, 'success') + def test_route_decorator_custom_endpoint(self): + app = flask.Flask(__name__) + app.debug = True + + @app.route('/foo/') + def foo(): + return flask.request.endpoint + + @app.route('/bar/', endpoint='bar') + def for_bar(): + return flask.request.endpoint + + @app.route('/bar/123', endpoint='123') + def for_bar_foo(): + return flask.request.endpoint + + with app.test_request_context(): + assert flask.url_for('foo') == '/foo/' + assert flask.url_for('bar') == '/bar/' + assert flask.url_for('123') == '/bar/123' + + c = app.test_client() + self.assertEqual(c.get('/foo/').data, 'foo') + self.assertEqual(c.get('/bar/').data, 'bar') + self.assertEqual(c.get('/bar/123').data, '123') + class InstanceTestCase(unittest.TestCase): @@ -1687,6 +1713,40 @@ class BlueprintTestCase(unittest.TestCase): self.assertEqual(c.get('/').data, '1') self.assertEqual(c.get('/page/2').data, '2') + def test_route_decorator_custom_endpoint(self): + + bp = flask.Blueprint('bp', __name__) + + @bp.route('/foo') + def foo(): + return flask.request.endpoint + + @bp.route('/bar', endpoint='bar') + def foo_bar(): + return flask.request.endpoint + + @bp.route('/bar/123', endpoint='123') + def foo_bar_foo(): + return flask.request.endpoint + + @bp.route('/bar/foo') + def bar_foo(): + return flask.request.endpoint + + app = flask.Flask(__name__) + app.register_blueprint(bp, url_prefix='/py') + + @app.route('/') + def index(): + return flask.request.endpoint + + c = app.test_client() + self.assertEqual(c.get('/').data, 'index') + self.assertEqual(c.get('/py/foo').data, 'bp.foo') + self.assertEqual(c.get('/py/bar').data, 'bp.bar') + self.assertEqual(c.get('/py/bar/123').data, 'bp.123') + self.assertEqual(c.get('/py/bar/foo').data, 'bp.bar_foo') + class SendfileTestCase(unittest.TestCase): From 04e87a93def1593dd886931e0f9e1d4f37f8d243 Mon Sep 17 00:00:00 2001 From: Pedro Algarvio Date: Thu, 25 Aug 2011 12:01:41 +0100 Subject: [PATCH 2/5] Add endpoint parameter documentation to the route decorator. --- flask/app.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/flask/app.py b/flask/app.py index 0597ba5b..67314fc8 100644 --- a/flask/app.py +++ b/flask/app.py @@ -938,6 +938,9 @@ class Flask(_PackageBoundObject): subdomain matching is in use. :param strict_slashes: can be used to disable the strict slashes setting for this rule. See above. + :param endpoint: Since version 0.8 you can also pass the enpoint, + it will be used instead of generating the endpoint + from the function name. :param options: other options to be forwarded to the underlying :class:`~werkzeug.routing.Rule` object. """ From 03a71e022919a0e1bff6606400e9d5ae234b8244 Mon Sep 17 00:00:00 2001 From: Pedro Algarvio Date: Thu, 25 Aug 2011 17:26:57 +0100 Subject: [PATCH 3/5] Deny dot's in blueprint endpoints. Add tests for that too. --- flask/blueprints.py | 2 ++ tests/flask_tests.py | 51 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+) diff --git a/flask/blueprints.py b/flask/blueprints.py index 6d693781..8bfc610e 100644 --- a/flask/blueprints.py +++ b/flask/blueprints.py @@ -166,6 +166,8 @@ class Blueprint(_PackageBoundObject): """Like :meth:`Flask.add_url_rule` but for a blueprint. The endpoint for the :func:`url_for` function is prefixed with the name of the blueprint. """ + if endpoint: + assert '.' not in endpoint, "Blueprint endpoint's should not contain dot's" self.record(lambda s: s.add_url_rule(rule, endpoint, view_func, **options)) diff --git a/tests/flask_tests.py b/tests/flask_tests.py index 3753218e..d5f7413d 100644 --- a/tests/flask_tests.py +++ b/tests/flask_tests.py @@ -1747,6 +1747,57 @@ class BlueprintTestCase(unittest.TestCase): self.assertEqual(c.get('/py/bar/123').data, 'bp.123') self.assertEqual(c.get('/py/bar/foo').data, 'bp.bar_foo') + def test_route_decorator_custom_endpoint_with_dots(self): + bp = flask.Blueprint('bp', __name__) + + @bp.route('/foo') + def foo(): + return flask.request.endpoint + + try: + @bp.route('/bar', endpoint='bar.bar') + def foo_bar(): + return flask.request.endpoint + except AssertionError: + pass + else: + raise AssertionError('expected AssertionError not raised') + + try: + @bp.route('/bar/123', endpoint='bar.123') + def foo_bar_foo(): + return flask.request.endpoint + except AssertionError: + pass + else: + raise AssertionError('expected AssertionError not raised') + + def foo_foo_foo(): + pass + + self.assertRaises( + AssertionError, + lambda: bp.add_url_rule( + '/bar/123', endpoint='bar.123', view_func=foo_foo_foo + ) + ) + + self.assertRaises( + AssertionError, + bp.route('/bar/123', endpoint='bar.123'), + lambda: None + ) + + app = flask.Flask(__name__) + app.register_blueprint(bp, url_prefix='/py') + + c = app.test_client() + self.assertEqual(c.get('/py/foo').data, 'bp.foo') + # The rule's din't actually made it through + rv = c.get('/py/bar') + assert rv.status_code == 404 + rv = c.get('/py/bar/123') + assert rv.status_code == 404 class SendfileTestCase(unittest.TestCase): From 5f7f3b17dfe2fbeecf82d5745c497b3ea94bf50a Mon Sep 17 00:00:00 2001 From: Christopher Currie Date: Tue, 30 Aug 2011 15:09:56 -0700 Subject: [PATCH 4/5] Fix for d5cd4f8d which broke install on Windows --- setup.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/setup.py b/setup.py index db2eb9c7..5dfe3a87 100644 --- a/setup.py +++ b/setup.py @@ -89,9 +89,7 @@ setup( 'and good intentions', long_description=__doc__, packages=['flask', 'flask.testsuite'], - package_data={ - 'flask.testsuite': ['test_apps/*', 'static/*', 'templates/*'] - }, + include_package_data = True, zip_safe=False, platforms='any', install_requires=[ From 37f9cb9ca69176dec36faff4b2138226b479f65f Mon Sep 17 00:00:00 2001 From: Ron DuPlain Date: Thu, 1 Sep 2011 12:35:04 -0400 Subject: [PATCH 5/5] Import with statement in testsuite, Python 2.5. --- flask/testing.py | 2 ++ flask/testsuite/__init__.py | 3 +++ flask/testsuite/basic.py | 3 +++ flask/testsuite/blueprints.py | 3 +++ flask/testsuite/deprecations.py | 3 +++ flask/testsuite/helpers.py | 3 +++ flask/testsuite/templating.py | 3 +++ flask/testsuite/testing.py | 3 +++ 8 files changed, 23 insertions(+) diff --git a/flask/testing.py b/flask/testing.py index 612b4d4d..67c3b434 100644 --- a/flask/testing.py +++ b/flask/testing.py @@ -10,6 +10,8 @@ :license: BSD, see LICENSE for more details. """ +from __future__ import with_statement + from contextlib import contextmanager from werkzeug.test import Client, EnvironBuilder from flask import _request_ctx_stack diff --git a/flask/testsuite/__init__.py b/flask/testsuite/__init__.py index 3f807251..49b85b23 100644 --- a/flask/testsuite/__init__.py +++ b/flask/testsuite/__init__.py @@ -9,6 +9,9 @@ :copyright: (c) 2011 by Armin Ronacher. :license: BSD, see LICENSE for more details. """ + +from __future__ import with_statement + import os import sys import flask diff --git a/flask/testsuite/basic.py b/flask/testsuite/basic.py index 078027b9..e71ce75c 100644 --- a/flask/testsuite/basic.py +++ b/flask/testsuite/basic.py @@ -8,6 +8,9 @@ :copyright: (c) 2011 by Armin Ronacher. :license: BSD, see LICENSE for more details. """ + +from __future__ import with_statement + import re import flask import unittest diff --git a/flask/testsuite/blueprints.py b/flask/testsuite/blueprints.py index 73577961..3f65dd48 100644 --- a/flask/testsuite/blueprints.py +++ b/flask/testsuite/blueprints.py @@ -8,6 +8,9 @@ :copyright: (c) 2011 by Armin Ronacher. :license: BSD, see LICENSE for more details. """ + +from __future__ import with_statement + import flask import unittest import warnings diff --git a/flask/testsuite/deprecations.py b/flask/testsuite/deprecations.py index 062f40b0..795a5d3d 100644 --- a/flask/testsuite/deprecations.py +++ b/flask/testsuite/deprecations.py @@ -8,6 +8,9 @@ :copyright: (c) 2011 by Armin Ronacher. :license: BSD, see LICENSE for more details. """ + +from __future__ import with_statement + import flask import unittest from flask.testsuite import FlaskTestCase, catch_warnings diff --git a/flask/testsuite/helpers.py b/flask/testsuite/helpers.py index 56264f70..052d36e1 100644 --- a/flask/testsuite/helpers.py +++ b/flask/testsuite/helpers.py @@ -8,6 +8,9 @@ :copyright: (c) 2011 by Armin Ronacher. :license: BSD, see LICENSE for more details. """ + +from __future__ import with_statement + import os import flask import unittest diff --git a/flask/testsuite/templating.py b/flask/testsuite/templating.py index eadbdcf6..453bfb65 100644 --- a/flask/testsuite/templating.py +++ b/flask/testsuite/templating.py @@ -8,6 +8,9 @@ :copyright: (c) 2011 by Armin Ronacher. :license: BSD, see LICENSE for more details. """ + +from __future__ import with_statement + import flask import unittest from flask.testsuite import FlaskTestCase diff --git a/flask/testsuite/testing.py b/flask/testsuite/testing.py index 32867c3f..2b073fd3 100644 --- a/flask/testsuite/testing.py +++ b/flask/testsuite/testing.py @@ -8,6 +8,9 @@ :copyright: (c) 2011 by Armin Ronacher. :license: BSD, see LICENSE for more details. """ + +from __future__ import with_statement + import flask import unittest from flask.testsuite import FlaskTestCase