From b2f25e5bc3fef072c289f015484bf028a0c2fc08 Mon Sep 17 00:00:00 2001 From: Amin Alaee Date: Sun, 5 Mar 2023 16:04:51 +0100 Subject: [PATCH] Change `url_for` signature to return a `URL` instance (#1385) Co-authored-by: Marcelo Trylesinski --- docs/routing.md | 2 ++ starlette/datastructures.py | 4 ++-- starlette/requests.py | 2 +- starlette/templating.py | 3 ++- tests/test_routing.py | 4 ++-- 5 files changed, 9 insertions(+), 6 deletions(-) diff --git a/docs/routing.md b/docs/routing.md index 5a76d7bc4..fd1558793 100644 --- a/docs/routing.md +++ b/docs/routing.md @@ -151,6 +151,8 @@ app = Starlette(routes=routes) You'll often want to be able to generate the URL for a particular route, such as in cases where you need to return a redirect response. +* Signature: `url_for(name, **path_params) -> URL` + ```python routes = [ Route("/", homepage, name="homepage") diff --git a/starlette/datastructures.py b/starlette/datastructures.py index 48bd33fec..236f9fa43 100644 --- a/starlette/datastructures.py +++ b/starlette/datastructures.py @@ -187,7 +187,7 @@ def __init__(self, path: str, protocol: str = "", host: str = "") -> None: self.protocol = protocol self.host = host - def make_absolute_url(self, base_url: typing.Union[str, URL]) -> str: + def make_absolute_url(self, base_url: typing.Union[str, URL]) -> URL: if isinstance(base_url, str): base_url = URL(base_url) if self.protocol: @@ -200,7 +200,7 @@ def make_absolute_url(self, base_url: typing.Union[str, URL]) -> str: netloc = self.host or base_url.netloc path = base_url.path.rstrip("/") + str(self) - return str(URL(scheme=scheme, netloc=netloc, path=path)) + return URL(scheme=scheme, netloc=netloc, path=path) class Secret: diff --git a/starlette/requests.py b/starlette/requests.py index 0c7264a56..3f5a8fd6f 100644 --- a/starlette/requests.py +++ b/starlette/requests.py @@ -173,7 +173,7 @@ def state(self) -> State: self._state = State(self.scope["state"]) return self._state - def url_for(self, name: str, **path_params: typing.Any) -> str: + def url_for(self, name: str, **path_params: typing.Any) -> URL: router: Router = self.scope["router"] url_path = router.url_path_for(name, **path_params) return url_path.make_absolute_url(base_url=self.base_url) diff --git a/starlette/templating.py b/starlette/templating.py index bccda36e4..ecea4f3a3 100644 --- a/starlette/templating.py +++ b/starlette/templating.py @@ -2,6 +2,7 @@ from os import PathLike from starlette.background import BackgroundTask +from starlette.datastructures import URL from starlette.requests import Request from starlette.responses import Response from starlette.types import Receive, Scope, Send @@ -77,7 +78,7 @@ def _create_env( self, directory: typing.Union[str, PathLike], **env_options: typing.Any ) -> "jinja2.Environment": @pass_context - def url_for(context: dict, name: str, **path_params: typing.Any) -> str: + def url_for(context: dict, name: str, **path_params: typing.Any) -> URL: request = context["request"] return request.url_for(name, **path_params) diff --git a/tests/test_routing.py b/tests/test_routing.py index 636679757..b70641680 100644 --- a/tests/test_routing.py +++ b/tests/test_routing.py @@ -522,8 +522,8 @@ def test_subdomain_reverse_urls(): async def echo_urls(request): return JSONResponse( { - "index": request.url_for("index"), - "submount": request.url_for("mount:submount"), + "index": str(request.url_for("index")), + "submount": str(request.url_for("mount:submount")), } )