Skip to content
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion sanic/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -417,8 +417,11 @@ def _apply_exception_handler(
def _apply_listener(self, listener: FutureListener):
return self.register_listener(listener.listener, listener.event)

def _apply_route(self, route: FutureRoute) -> List[Route]:
def _apply_route(
self, route: FutureRoute, overwrite: bool = False
) -> List[Route]:
params = route._asdict()
params["overwrite"] = overwrite
websocket = params.pop("websocket", False)
subprotocols = params.pop("subprotocols", None)

Expand Down
11 changes: 10 additions & 1 deletion sanic/blueprints.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ class Blueprint(BaseSanic):
"_future_listeners",
"_future_exceptions",
"_future_signals",
"allow_route_overwrite",
"copied_from",
"ctx",
"exceptions",
Expand All @@ -116,9 +117,11 @@ def __init__(
version: Optional[Union[int, str, float]] = None,
strict_slashes: Optional[bool] = None,
version_prefix: str = "/v",
allow_route_overwrite: bool = False,
):
super().__init__(name=name)
self.reset()
self.allow_route_overwrite = allow_route_overwrite
self.copied_from = ""
self.ctx = SimpleNamespace()
self.host = host
Expand Down Expand Up @@ -169,6 +172,7 @@ def registered(self) -> bool:

def reset(self):
self._apps: Set[Sanic] = set()
self.allow_route_overwrite = False
self.exceptions: List[RouteHandler] = []
self.listeners: Dict[str, List[ListenerType[Any]]] = {}
self.middlewares: List[MiddlewareType] = []
Expand All @@ -182,6 +186,7 @@ def copy(
url_prefix: Optional[Union[str, Default]] = _default,
version: Optional[Union[int, str, float, Default]] = _default,
version_prefix: Union[str, Default] = _default,
allow_route_overwrite: Union[bool, Default] = _default,
strict_slashes: Optional[Union[bool, Default]] = _default,
with_registration: bool = True,
with_ctx: bool = False,
Expand Down Expand Up @@ -225,6 +230,8 @@ def copy(
new_bp.strict_slashes = strict_slashes
if not isinstance(version_prefix, Default):
new_bp.version_prefix = version_prefix
if not isinstance(allow_route_overwrite, Default):
new_bp.allow_route_overwrite = allow_route_overwrite

for key, value in attrs_backup.items():
setattr(self, key, value)
Expand Down Expand Up @@ -354,7 +361,9 @@ def register(self, app, options):
continue

registered.add(apply_route)
route = app._apply_route(apply_route)
route = app._apply_route(
apply_route, overwrite=self.allow_route_overwrite
)

# If it is a copied BP, then make sure all of the names of routes
# matchup with the new BP name
Expand Down
8 changes: 6 additions & 2 deletions sanic/mixins/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,11 @@ def decorator(handler):
error_format,
route_context,
)

overwrite = getattr(self, "allow_route_overwrite", False)
if overwrite:
self._future_routes = set(
filter(lambda x: x.uri != uri, self._future_routes)
)
self._future_routes.add(route)

args = list(signature(handler).parameters.keys())
Expand All @@ -182,7 +186,7 @@ def decorator(handler):
handler.is_stream = stream

if apply:
self._apply_route(route)
self._apply_route(route, overwrite=overwrite)

if static:
return route, handler
Expand Down
2 changes: 2 additions & 0 deletions sanic/router.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ def add( # type: ignore
unquote: bool = False,
static: bool = False,
version_prefix: str = "/v",
overwrite: bool = False,
error_format: Optional[str] = None,
) -> Union[Route, List[Route]]:
"""
Expand Down Expand Up @@ -122,6 +123,7 @@ def add( # type: ignore
name=name,
strict=strict_slashes,
unquote=unquote,
overwrite=overwrite,
)

if isinstance(host, str):
Expand Down
41 changes: 40 additions & 1 deletion tests/test_blueprint_copy.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from sanic import Blueprint, Sanic
from sanic import Blueprint, Request, Sanic
from sanic.response import text


Expand Down Expand Up @@ -74,3 +74,42 @@ def handle_request(request):
assert "test_bp_copy.test_bp4.handle_request" in route_names
assert "test_bp_copy.test_bp5.handle_request" in route_names
assert "test_bp_copy.test_bp6.handle_request" in route_names


def test_bp_copy_with_route_overwriting(app: Sanic):
Comment thread
ChihweiLHBird marked this conversation as resolved.
bpv1 = Blueprint("bp_v1", version=1, url_prefix="my_api")

@bpv1.route("/")
async def handler(request: Request):
return text("v1")

app.blueprint(bpv1)

bpv2 = bpv1.copy("bp_v2", version=2, allow_route_overwrite=True)
bpv3 = bpv1.copy(
"bp_v3", version=3, allow_route_overwrite=True, with_registration=False
)

@bpv2.route("/")
async def handler(request: Request):
return text("v2")

app.blueprint(bpv2)

@bpv3.route("/")
async def handler(request: Request):
return text("v3")

app.blueprint(bpv3)

_, response = app.test_client.get("/v1/my_api")
assert response.status == 200
assert response.text == "v1"

_, response = app.test_client.get("/v2/my_api")
assert response.status == 200
assert response.text == "v2"

_, response = app.test_client.get("/v3/my_api")
assert response.status == 200
assert response.text == "v3"
18 changes: 18 additions & 0 deletions tests/test_blueprints.py
Original file line number Diff line number Diff line change
Expand Up @@ -1112,3 +1112,21 @@ async def index(_):
app.router.finalize()

assert app.router.routes[0].path == "foo/"


def test_bp_allow_override(app: Sanic):
bp = Blueprint("test_text", allow_route_overwrite=True)

@bp.route("/")
def handler1(request):
return text("Hello")

@bp.route("/")
def handler2(request):
return text("Overwritten Hello")

app.blueprint(bp)
_, response = app.test_client.get("/")

Comment thread
ahopkins marked this conversation as resolved.
Outdated
assert response.status == 200
assert response.text == "Overwritten Hello"