Fix registering a blueprint twice with differing names

Previously the blueprint recorded aspects (before request, after
request etc) would only be added to the app if it was the first
registration of the blueprint instance. However only the record-once
aspects (app-before requests, app-after request) should be added once
on registration of the instance, whereas everything else should be
added on every unique name registration. This ensures that these
trigger under the new name as well as the old.
This commit is contained in:
pgjones 2021-06-05 16:08:51 +01:00 committed by Phil Jones
parent 399b851ed7
commit a44c722860
3 changed files with 16 additions and 3 deletions

View file

@ -12,6 +12,7 @@ Unreleased
decorators to accept functions with no arguments. :issue:`4098`
- Support View and MethodView instances with async handlers. :issue:`4112`
- Enhance typing of ``app.errorhandler`` decorator. :issue:`4095`
- Fix registering a blueprint twice with differing names. :issue:`4124`
Version 2.0.1

View file

@ -293,7 +293,6 @@ class Blueprint(Scaffold):
Registering the same blueprint with the same name multiple
times is deprecated and will become an error in Flask 2.1.
"""
first_registration = not any(bp is self for bp in app.blueprints.values())
name_prefix = options.get("name_prefix", "")
self_name = options.get("name", self.name)
name = f"{name_prefix}.{self_name}".lstrip(".")
@ -318,9 +317,12 @@ class Blueprint(Scaffold):
stacklevel=4,
)
first_bp_registration = not any(bp is self for bp in app.blueprints.values())
first_name_registration = name not in app.blueprints
app.blueprints[name] = self
self._got_registered_once = True
state = self.make_setup_state(app, options, first_registration)
state = self.make_setup_state(app, options, first_bp_registration)
if self.has_static_folder:
state.add_url_rule(
@ -330,7 +332,7 @@ class Blueprint(Scaffold):
)
# Merge blueprint data into parent.
if first_registration:
if first_bp_registration or first_name_registration:
def extend(bp_dict, parent_dict):
for key, values in bp_dict.items():

View file

@ -899,6 +899,14 @@ def test_blueprint_renaming(app, client) -> None:
def index():
return flask.request.endpoint
@bp.get("/error")
def error():
flask.abort(403)
@bp.errorhandler(403)
def forbidden(_: Exception):
return "Error", 403
@bp2.get("/")
def index2():
return flask.request.endpoint
@ -911,3 +919,5 @@ def test_blueprint_renaming(app, client) -> None:
assert client.get("/b/").data == b"alt.index"
assert client.get("/a/a/").data == b"bp.sub.index2"
assert client.get("/b/a/").data == b"alt.sub.index2"
assert client.get("/a/error").data == b"Error"
assert client.get("/b/error").data == b"Error"