From 92acd05d9bd33419ab885e4472b28a1d5cc15d2e Mon Sep 17 00:00:00 2001 From: Ivan Sushkov Date: Mon, 2 May 2022 12:29:55 -0600 Subject: [PATCH] add url_for method to app --- src/flask/app.py | 45 ++++++++++++++++++++++++++++++++++++++++++++ src/flask/helpers.py | 38 +------------------------------------ 2 files changed, 46 insertions(+), 37 deletions(-) diff --git a/src/flask/app.py b/src/flask/app.py index ad859b27..de883a92 100644 --- a/src/flask/app.py +++ b/src/flask/app.py @@ -23,6 +23,7 @@ from werkzeug.routing import MapAdapter from werkzeug.routing import RequestRedirect from werkzeug.routing import RoutingException from werkzeug.routing import Rule +from werkzeug.urls import url_quote from werkzeug.utils import redirect as _wz_redirect from werkzeug.wrappers import Response as BaseResponse @@ -1661,6 +1662,50 @@ class Flask(Scaffold): return asgiref_async_to_sync(func) + def url_for( + self, + endpoint: str, + external: bool, + url_adapter, + **values: t.Any, + ) -> str: + + anchor = values.pop("_anchor", None) + method = values.pop("_method", None) + scheme = values.pop("_scheme", None) + self.inject_url_defaults(endpoint, values) + + # This is not the best way to deal with this but currently the + # underlying Werkzeug router does not support overriding the scheme on + # a per build call basis. + old_scheme = None + if scheme is not None: + if not external: + raise ValueError("When specifying _scheme, _external must be True") + old_scheme = url_adapter.url_scheme + url_adapter.url_scheme = scheme + + try: + try: + rv = url_adapter.build( + endpoint, values, method=method, force_external=external + ) + finally: + if old_scheme is not None: + url_adapter.url_scheme = old_scheme + except BuildError as error: + # We need to inject the values again so that the app callback can + # deal with that sort of stuff. + values["_external"] = external + values["_anchor"] = anchor + values["_method"] = method + values["_scheme"] = scheme + return self.handle_url_build_error(error, endpoint, values) + + if anchor is not None: + rv += f"#{url_quote(anchor)}" + return rv + def redirect(self, location: str, code: int = 302) -> BaseResponse: """Create a redirect response object. diff --git a/src/flask/helpers.py b/src/flask/helpers.py index dec9b771..167fa132 100644 --- a/src/flask/helpers.py +++ b/src/flask/helpers.py @@ -11,8 +11,6 @@ from threading import RLock import werkzeug.utils from werkzeug.exceptions import abort as _wz_abort -from werkzeug.routing import BuildError -from werkzeug.urls import url_quote from werkzeug.utils import redirect as _wz_redirect from .globals import _app_ctx_stack @@ -307,41 +305,7 @@ def url_for(endpoint: str, **values: t.Any) -> str: external = values.pop("_external", True) - anchor = values.pop("_anchor", None) - method = values.pop("_method", None) - scheme = values.pop("_scheme", None) - appctx.app.inject_url_defaults(endpoint, values) - - # This is not the best way to deal with this but currently the - # underlying Werkzeug router does not support overriding the scheme on - # a per build call basis. - old_scheme = None - if scheme is not None: - if not external: - raise ValueError("When specifying _scheme, _external must be True") - old_scheme = url_adapter.url_scheme - url_adapter.url_scheme = scheme - - try: - try: - rv = url_adapter.build( - endpoint, values, method=method, force_external=external - ) - finally: - if old_scheme is not None: - url_adapter.url_scheme = old_scheme - except BuildError as error: - # We need to inject the values again so that the app callback can - # deal with that sort of stuff. - values["_external"] = external - values["_anchor"] = anchor - values["_method"] = method - values["_scheme"] = scheme - return appctx.app.handle_url_build_error(error, endpoint, values) - - if anchor is not None: - rv += f"#{url_quote(anchor)}" - return rv + return current_app.url_for(endpoint, external, url_adapter, **values) def redirect(