From 99afbb277d25d3b052e00b9a8da216054d51d62a Mon Sep 17 00:00:00 2001 From: pgjones Date: Tue, 18 May 2021 13:06:21 +0100 Subject: [PATCH] Fix blueprint nested url_prefix This ensures that the url_prefix is correctly applied, no matter if set during the registration override or when constructing the blueprint. --- src/flask/blueprints.py | 4 ++- tests/test_blueprints.py | 66 +++++++++++++++------------------------- 2 files changed, 28 insertions(+), 42 deletions(-) diff --git a/src/flask/blueprints.py b/src/flask/blueprints.py index 88883ba7..85870a90 100644 --- a/src/flask/blueprints.py +++ b/src/flask/blueprints.py @@ -354,7 +354,9 @@ class Blueprint(Scaffold): bp_options["url_prefix"] = ( state.url_prefix.rstrip("/") + "/" + bp_url_prefix.lstrip("/") ) - else: + elif bp_url_prefix is not None: + bp_options["url_prefix"] = bp_url_prefix + elif state.url_prefix is not None: bp_options["url_prefix"] = state.url_prefix bp_options["name_prefix"] = options.get("name_prefix", "") + self.name + "." diff --git a/tests/test_blueprints.py b/tests/test_blueprints.py index 0bae5333..0f9e9db9 100644 --- a/tests/test_blueprints.py +++ b/tests/test_blueprints.py @@ -837,48 +837,32 @@ def test_nested_blueprint(app, client): assert client.get("/parent/child/grandchild/no").data == b"Grandchild no" -def test_nested_blueprint_url_prefix(app, client): - parent = flask.Blueprint("parent", __name__, url_prefix="/parent") - child = flask.Blueprint("child", __name__, url_prefix="/child") - grandchild = flask.Blueprint("grandchild", __name__, url_prefix="/grandchild") - apple = flask.Blueprint("apple", __name__, url_prefix="/apple") - - @parent.route("/") - def parent_index(): - return "Parent" +@pytest.mark.parametrize( + "parent_init, child_init, parent_registration, child_registration", + [ + ("/parent", "/child", None, None), + ("/parent", None, None, "/child"), + (None, None, "/parent", "/child"), + ("/other", "/something", "/parent", "/child"), + ], +) +def test_nesting_url_prefixes( + parent_init, + child_init, + parent_registration, + child_registration, + app, + client, +) -> None: + parent = flask.Blueprint("parent", __name__, url_prefix=parent_init) + child = flask.Blueprint("child", __name__, url_prefix=child_init) @child.route("/") - def child_index(): - return "Child" + def index(): + return "index" - @grandchild.route("/") - def grandchild_index(): - return "Grandchild" + parent.register_blueprint(child, url_prefix=child_registration) + app.register_blueprint(parent, url_prefix=parent_registration) - @apple.route("/") - def apple_index(): - return "Apple" - - child.register_blueprint(grandchild) - child.register_blueprint(apple, url_prefix="/orange") # test overwrite - parent.register_blueprint(child) - app.register_blueprint(parent) - - assert client.get("/parent/").data == b"Parent" - assert client.get("/parent/child/").data == b"Child" - assert client.get("/parent/child/grandchild/").data == b"Grandchild" - assert client.get("/parent/child/orange/").data == b"Apple" - - -def test_nested_blueprint_url_prefix_only_parent_prefix(app, client): - parent = flask.Blueprint("parent", __name__) - child = flask.Blueprint("child", __name__) - - @child.route("/child-endpoint") - def child_index(): - return "Child" - - parent.register_blueprint(child) - app.register_blueprint(parent, url_prefix="/parent") - - assert client.get("/parent/child-endpoint").data == b"Child" + response = client.get("/parent/child/") + assert response.status_code == 200