From ae64f1187278499663bcb60120dc82b17e8897ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Thu, 30 Oct 2025 00:38:54 +0100 Subject: [PATCH] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Reduce=20internal=20cyclic?= =?UTF-8?q?=20recursion=20in=20dependencies,=20from=202=20functions=20call?= =?UTF-8?q?ing=20each=20other=20to=201=20calling=20itself?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- fastapi/dependencies/utils.py | 59 ++++++++++++++--------------------- 1 file changed, 23 insertions(+), 36 deletions(-) diff --git a/fastapi/dependencies/utils.py b/fastapi/dependencies/utils.py index 18f6a234e..5f6f1a1aa 100644 --- a/fastapi/dependencies/utils.py +++ b/fastapi/dependencies/utils.py @@ -129,39 +129,12 @@ def get_parameterless_sub_dependant(*, depends: params.Depends, path: str) -> De assert callable(depends.dependency), ( "A parameter-less dependency must have a callable dependency" ) - return get_sub_dependant(depends=depends, dependency=depends.dependency, path=path) - - -def get_sub_dependant( - *, - depends: params.Depends, - dependency: Callable[..., Any], - path: str, - name: Optional[str] = None, - security_scopes: Optional[List[str]] = None, -) -> Dependant: - security_requirement = None - security_scopes = security_scopes or [] - if isinstance(depends, params.Security): - if depends.scopes: - security_scopes.extend(depends.scopes) - if isinstance(dependency, SecurityBase): - use_scopes: List[str] = [] - if isinstance(dependency, (OAuth2, OpenIdConnect)): - use_scopes = security_scopes - security_requirement = SecurityRequirement( - security_scheme=dependency, scopes=use_scopes - ) - sub_dependant = get_dependant( - path=path, - call=dependency, - name=name, - security_scopes=security_scopes, - use_cache=depends.use_cache, + use_security_scopes = [] + if isinstance(depends, params.Security) and depends.scopes: + use_security_scopes.extend(depends.scopes) + return get_dependant( + path=path, call=depends.dependency, security_scopes=use_security_scopes ) - if security_requirement: - sub_dependant.security_requirements.append(security_requirement) - return sub_dependant CacheKey = Tuple[Optional[Callable[..., Any]], Tuple[str, ...]] @@ -285,13 +258,27 @@ def get_dependant( ) if param_details.depends is not None: assert param_details.depends.dependency - sub_dependant = get_sub_dependant( - depends=param_details.depends, - dependency=param_details.depends.dependency, + use_security_scopes = security_scopes or [] + if isinstance(param_details.depends, params.Security): + if param_details.depends.scopes: + use_security_scopes.extend(param_details.depends.scopes) + sub_dependant = get_dependant( path=path, + call=param_details.depends.dependency, name=param_name, - security_scopes=security_scopes, + security_scopes=use_security_scopes, + use_cache=param_details.depends.use_cache, ) + if isinstance(param_details.depends.dependency, SecurityBase): + use_scopes: List[str] = [] + if isinstance( + param_details.depends.dependency, (OAuth2, OpenIdConnect) + ): + use_scopes = use_security_scopes + security_requirement = SecurityRequirement( + security_scheme=param_details.depends.dependency, scopes=use_scopes + ) + sub_dependant.security_requirements.append(security_requirement) dependant.dependencies.append(sub_dependant) continue if add_non_field_param_to_dependency(