From efd7f01c292b8b99164bc7010c19da38cadb2d08 Mon Sep 17 00:00:00 2001 From: Yurii Karabas <1998uriyyo@gmail.com> Date: Mon, 3 May 2021 23:59:02 +0300 Subject: [PATCH] Add better exception msg for duplicated param names --- starlette/routing.py | 9 +++++++++ tests/test_routing.py | 14 ++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/starlette/routing.py b/starlette/routing.py index 1e6ae0b55..2707bbf4a 100644 --- a/starlette/routing.py +++ b/starlette/routing.py @@ -107,6 +107,7 @@ def compile_path( """ path_regex = "^" path_format = "" + duplicated_params = set() idx = 0 param_convertors = {} @@ -124,10 +125,18 @@ def compile_path( path_format += path[idx : match.start()] path_format += "{%s}" % param_name + if param_name in param_convertors: + duplicated_params.add(param_name) + param_convertors[param_name] = convertor idx = match.end() + if duplicated_params: + names = ", ".join(sorted(duplicated_params)) + ending = "s" if len(duplicated_params) > 1 else "" + raise ValueError(f"Duplicated param name{ending} {names} at path {path}") + path_regex += re.escape(path[idx:]) + "$" path_format += path[idx:] diff --git a/tests/test_routing.py b/tests/test_routing.py index 8927c60cd..fff3332db 100644 --- a/tests/test_routing.py +++ b/tests/test_routing.py @@ -622,3 +622,17 @@ def test_partial_async_endpoint(): cls_method_response = test_client.get("/cls") assert cls_method_response.status_code == 200 assert cls_method_response.json() == {"arg": "foo"} + + +def test_duplicated_param_names(): + with pytest.raises( + ValueError, + match="Duplicated param name id at path /{id}/{id}", + ): + Route("/{id}/{id}", user) + + with pytest.raises( + ValueError, + match="Duplicated param names id, name at path /{id}/{name}/{id}/{name}", + ): + Route("/{id}/{name}/{id}/{name}", user)