From 19f9bdc731c7bb5f2811d14b142e1140caaa956e Mon Sep 17 00:00:00 2001 From: "alex.oleshkevich" Date: Tue, 14 Dec 2021 20:55:14 +0300 Subject: [PATCH 1/4] Display missing route details. --- starlette/routing.py | 12 +++++++----- tests/test_routing.py | 2 +- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/starlette/routing.py b/starlette/routing.py index 982980c3c..38af5b091 100644 --- a/starlette/routing.py +++ b/starlette/routing.py @@ -30,6 +30,8 @@ class NoMatchFound(Exception): Raised by `.url_for(name, **path_params)` and `.url_path_for(name, **path_params)` if no matching route exists. """ + def __init__(self, name:str, path_params:typing.Dict[str, typing.Any]) -> None: + super().__init__(f'No route exists for name "{name}" and params "{path_params}".') class Match(Enum): @@ -240,7 +242,7 @@ def url_path_for(self, name: str, **path_params: typing.Any) -> URLPath: expected_params = set(self.param_convertors.keys()) if name != self.name or seen_params != expected_params: - raise NoMatchFound() + raise NoMatchFound(name, path_params) path, remaining_params = replace_params( self.path_format, self.param_convertors, path_params @@ -306,7 +308,7 @@ def url_path_for(self, name: str, **path_params: typing.Any) -> URLPath: expected_params = set(self.param_convertors.keys()) if name != self.name or seen_params != expected_params: - raise NoMatchFound() + raise NoMatchFound(name, path_params) path, remaining_params = replace_params( self.path_format, self.param_convertors, path_params @@ -405,7 +407,7 @@ def url_path_for(self, name: str, **path_params: typing.Any) -> URLPath: ) except NoMatchFound: pass - raise NoMatchFound() + raise NoMatchFound(name, path_params) async def handle(self, scope: Scope, receive: Receive, send: Send) -> None: await self.app(scope, receive, send) @@ -469,7 +471,7 @@ def url_path_for(self, name: str, **path_params: typing.Any) -> URLPath: return URLPath(path=str(url), protocol=url.protocol, host=host) except NoMatchFound: pass - raise NoMatchFound() + raise NoMatchFound(name, path_params) async def handle(self, scope: Scope, receive: Receive, send: Send) -> None: await self.app(scope, receive, send) @@ -590,7 +592,7 @@ def url_path_for(self, name: str, **path_params: typing.Any) -> URLPath: return route.url_path_for(name, **path_params) except NoMatchFound: pass - raise NoMatchFound() + raise NoMatchFound(name, path_params) async def startup(self) -> None: """ diff --git a/tests/test_routing.py b/tests/test_routing.py index dcb996531..13a0cebcb 100644 --- a/tests/test_routing.py +++ b/tests/test_routing.py @@ -238,7 +238,7 @@ def test_url_path_for(): assert app.url_path_for("homepage") == "/" assert app.url_path_for("user", username="tomchristie") == "/users/tomchristie" assert app.url_path_for("websocket_endpoint") == "/ws" - with pytest.raises(NoMatchFound): + with pytest.raises(NoMatchFound, match='No route exists for name "broken" and params "{}".'): assert app.url_path_for("broken") with pytest.raises(AssertionError): app.url_path_for("user", username="tom/christie") From f961e96f266cac360206f377450dcf59e2615ac8 Mon Sep 17 00:00:00 2001 From: "alex.oleshkevich" Date: Tue, 14 Dec 2021 21:05:37 +0300 Subject: [PATCH 2/4] Fix formatting. --- starlette/routing.py | 7 +++++-- tests/test_routing.py | 4 +++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/starlette/routing.py b/starlette/routing.py index 38af5b091..6f050c302 100644 --- a/starlette/routing.py +++ b/starlette/routing.py @@ -30,8 +30,11 @@ class NoMatchFound(Exception): Raised by `.url_for(name, **path_params)` and `.url_path_for(name, **path_params)` if no matching route exists. """ - def __init__(self, name:str, path_params:typing.Dict[str, typing.Any]) -> None: - super().__init__(f'No route exists for name "{name}" and params "{path_params}".') + + def __init__(self, name: str, path_params: typing.Dict[str, typing.Any]) -> None: + super().__init__( + f'No route exists for name "{name}" and params "{path_params}".' + ) class Match(Enum): diff --git a/tests/test_routing.py b/tests/test_routing.py index 13a0cebcb..ed0fc8508 100644 --- a/tests/test_routing.py +++ b/tests/test_routing.py @@ -238,7 +238,9 @@ def test_url_path_for(): assert app.url_path_for("homepage") == "/" assert app.url_path_for("user", username="tomchristie") == "/users/tomchristie" assert app.url_path_for("websocket_endpoint") == "/ws" - with pytest.raises(NoMatchFound, match='No route exists for name "broken" and params "{}".'): + with pytest.raises( + NoMatchFound, match='No route exists for name "broken" and params "{}".' + ): assert app.url_path_for("broken") with pytest.raises(AssertionError): app.url_path_for("user", username="tom/christie") From edda0496bf343b3d84ea9e592a56647a0dc62fe1 Mon Sep 17 00:00:00 2001 From: "alex.oleshkevich" Date: Sun, 26 Dec 2021 01:30:56 +0300 Subject: [PATCH 3/4] Display only path params keys in NoMatchFound error. --- starlette/routing.py | 3 ++- tests/test_routing.py | 6 +++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/starlette/routing.py b/starlette/routing.py index 6f050c302..856c7a8dd 100644 --- a/starlette/routing.py +++ b/starlette/routing.py @@ -32,8 +32,9 @@ class NoMatchFound(Exception): """ def __init__(self, name: str, path_params: typing.Dict[str, typing.Any]) -> None: + params = ', '.join(list(path_params.keys())) super().__init__( - f'No route exists for name "{name}" and params "{path_params}".' + f'No route exists for name "{name}" and params "{params}".' ) diff --git a/tests/test_routing.py b/tests/test_routing.py index ed0fc8508..7db7261dd 100644 --- a/tests/test_routing.py +++ b/tests/test_routing.py @@ -239,9 +239,13 @@ def test_url_path_for(): assert app.url_path_for("user", username="tomchristie") == "/users/tomchristie" assert app.url_path_for("websocket_endpoint") == "/ws" with pytest.raises( - NoMatchFound, match='No route exists for name "broken" and params "{}".' + NoMatchFound, match='No route exists for name "broken" and params "".' ): assert app.url_path_for("broken") + with pytest.raises( + NoMatchFound, match='No route exists for name "broken" and params "key, key2".' + ): + assert app.url_path_for("broken", key="value", key2="value2") with pytest.raises(AssertionError): app.url_path_for("user", username="tom/christie") with pytest.raises(AssertionError): From 5d5c5a0e34b87e3047c0f170a0e47b67cb1a804a Mon Sep 17 00:00:00 2001 From: "alex.oleshkevich" Date: Sun, 26 Dec 2021 01:33:03 +0300 Subject: [PATCH 4/4] Fix linting issues. --- starlette/routing.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/starlette/routing.py b/starlette/routing.py index 856c7a8dd..33d7fe08a 100644 --- a/starlette/routing.py +++ b/starlette/routing.py @@ -32,10 +32,8 @@ class NoMatchFound(Exception): """ def __init__(self, name: str, path_params: typing.Dict[str, typing.Any]) -> None: - params = ', '.join(list(path_params.keys())) - super().__init__( - f'No route exists for name "{name}" and params "{params}".' - ) + params = ", ".join(list(path_params.keys())) + super().__init__(f'No route exists for name "{name}" and params "{params}".') class Match(Enum):