Browse Source

🎨 [pre-commit.ci] Auto format from pre-commit.com hooks

pull/12529/head
pre-commit-ci[bot] 8 months ago
parent
commit
b189030589
  1. 4
      docs_src/dependencies/tutorial013c_an_py39.py
  2. 3
      fastapi/applications.py
  3. 3
      fastapi/dependencies/models.py
  4. 68
      fastapi/dependencies/utils.py
  5. 8
      fastapi/exceptions.py
  6. 4
      fastapi/params.py
  7. 20
      fastapi/utils.py
  8. 8
      tests/test_lifespan_scoped_dependencies/test_dependency_overrides.py
  9. 12
      tests/test_lifespan_scoped_dependencies/test_endpoint_usage.py
  10. 1
      tests/test_params_repr.py

4
docs_src/dependencies/tutorial013c_an_py39.py

@ -32,9 +32,7 @@ async def get_configuration() -> dict:
}
GlobalConfiguration = Annotated[
dict, Depends(get_configuration, scope="lifespan")
]
GlobalConfiguration = Annotated[dict, Depends(get_configuration, scope="lifespan")]
async def get_database_connection(configuration: GlobalConfiguration):

3
fastapi/applications.py

@ -36,9 +36,8 @@ from fastapi.openapi.utils import get_openapi
from fastapi.params import Depends
from fastapi.routing import merge_lifespan_context
from fastapi.types import DecoratedCallable, IncEx
from fastapi.utils import generate_unique_id, call_asynchronously
from fastapi.utils import call_asynchronously, generate_unique_id
from starlette.applications import Starlette
from starlette.concurrency import run_in_threadpool
from starlette.datastructures import State
from starlette.exceptions import HTTPException
from starlette.middleware import Middleware

3
fastapi/dependencies/models.py

@ -2,7 +2,7 @@ import inspect
import sys
from dataclasses import dataclass, field
from functools import cached_property
from typing import Any, Callable, List, Optional, Sequence, Union, Tuple, cast
from typing import Any, Callable, List, Optional, Sequence, Tuple, Union, cast
from fastapi._compat import ModelField
from fastapi.security.base import SecurityBase
@ -65,6 +65,7 @@ class LifespanDependant:
)
return self.caller, self.index
@dataclass
class EndpointDependant:
path_params: List[ModelField] = field(default_factory=list)

68
fastapi/dependencies/utils.py

@ -53,8 +53,16 @@ from fastapi.concurrency import (
asynccontextmanager,
contextmanager_in_threadpool,
)
from fastapi.dependencies.models import EndpointDependant, LifespanDependant, SecurityRequirement
from fastapi.exceptions import DependencyScopeError, InvalidDependencyScope, UninitializedLifespanDependency
from fastapi.dependencies.models import (
EndpointDependant,
LifespanDependant,
SecurityRequirement,
)
from fastapi.exceptions import (
DependencyScopeError,
InvalidDependencyScope,
UninitializedLifespanDependency,
)
from fastapi.logger import logger
from fastapi.security.base import SecurityBase
from fastapi.security.oauth2 import OAuth2, SecurityScopes
@ -122,7 +130,7 @@ def ensure_multipart_is_installed() -> None:
def get_parameterless_sub_dependant(
*, depends: params.Depends, path: str, caller: Callable[..., Any], index: int
*, depends: params.Depends, path: str, caller: Callable[..., Any], index: int
) -> Union[EndpointDependant, LifespanDependant]:
assert callable(depends.dependency), (
"A parameter-less dependency must have a callable dependency"
@ -135,7 +143,7 @@ def get_parameterless_sub_dependant(
path=path,
call=depends.dependency,
security_scopes=use_security_scopes,
index=index
index=index,
)
elif depends.scope == "lifespan":
return get_lifespan_dependant(
@ -146,8 +154,7 @@ def get_parameterless_sub_dependant(
)
else:
raise InvalidDependencyScope(
f'Dependency "{index}" of {caller} has an invalid '
f'scope: "{depends.scope}"'
f'Dependency "{index}" of {caller} has an invalid scope: "{depends.scope}"'
)
@ -267,7 +274,7 @@ def get_lifespan_dependant(
raise DependencyScopeError(
f'Dependency "{dependant.name}" has "lifespan" scope, but was defined'
f'with an invalid argument: "{param_name}" which is '
f'not a valid sub-dependency. Lifespan scoped dependencies may only '
f"not a valid sub-dependency. Lifespan scoped dependencies may only "
f"use lifespan scoped sub-dependencies."
)
@ -275,7 +282,7 @@ def get_lifespan_dependant(
raise DependencyScopeError(
f'Dependency "{dependant.name}" has "lifespan" scope, but was defined with the '
f'sub-dependency "{param_name}" which has "{param_details.depends.scope}" scope. Lifespan scoped '
f'dependencies may only use lifespan scoped sub-dependencies.'
f"dependencies may only use lifespan scoped sub-dependencies."
)
assert param_details.depends.dependency is not None
@ -346,23 +353,27 @@ def get_endpoint_dependant(
if param_details.depends.scopes:
use_security_scopes.extend(param_details.depends.scopes)
if param_details.depends.scope == "lifespan":
dependant.lifespan_dependencies.append(get_lifespan_dependant(
caller=call,
call=param_details.depends.dependency,
name=param_name,
use_cache=param_details.depends.use_cache,
index=index
))
dependant.lifespan_dependencies.append(
get_lifespan_dependant(
caller=call,
call=param_details.depends.dependency,
name=param_name,
use_cache=param_details.depends.use_cache,
index=index,
)
)
elif param_details.depends.scope in ("request", "function", None):
dependant.endpoint_dependencies.append(get_endpoint_dependant(
path=path,
call=param_details.depends.dependency,
name=param_name,
security_scopes=use_security_scopes,
use_cache=param_details.depends.use_cache,
index=index,
scope=param_details.depends.scope
))
dependant.endpoint_dependencies.append(
get_endpoint_dependant(
path=path,
call=param_details.depends.dependency,
name=param_name,
security_scopes=use_security_scopes,
use_cache=param_details.depends.use_cache,
index=index,
scope=param_details.depends.scope,
)
)
else:
raise InvalidDependencyScope(
f'Dependency "{name}" of {call} has an invalid '
@ -628,7 +639,10 @@ def add_param_to_fields(*, field: ModelField, dependant: EndpointDependant) -> N
async def _solve_generator(
*, dependant: Union[EndpointDependant, LifespanDependant], stack: AsyncExitStack, sub_values: Dict[str, Any]
*,
dependant: Union[EndpointDependant, LifespanDependant],
stack: AsyncExitStack,
sub_values: Dict[str, Any],
) -> Any:
assert dependant.call
if dependant.is_gen_callable:
@ -690,7 +704,9 @@ async def solve_lifespan_dependant(
if dependant_to_solve.is_gen_callable or dependant_to_solve.is_async_gen_callable:
value = await _solve_generator(
dependant=dependant_to_solve, stack=async_exit_stack, sub_values=dependency_arguments
dependant=dependant_to_solve,
stack=async_exit_stack,
sub_values=dependency_arguments,
)
elif dependant_to_solve.is_coroutine_callable:
value = await call(**dependency_arguments)

8
fastapi/exceptions.py

@ -146,31 +146,39 @@ class FastAPIError(RuntimeError):
A generic, FastAPI-specific error.
"""
class DependencyError(FastAPIError):
"""
A generic error regarding to dependencies.
"""
pass
class InvalidDependencyScope(DependencyError):
"""
A dependency was declared with an unsupported scope value.
"""
pass
class DependencyScopeError(DependencyError):
"""
A dependency declared that it depends on another dependency with an invalid
(narrower) scope.
"""
class UninitializedLifespanDependency(DependencyError):
"""
A bug in FastAPI caused a lifespan-scoped dependency to not initialize properly
at the point where we handled a request that depended on it.
"""
pass
class ValidationException(Exception):
def __init__(self, errors: Sequence[Any]) -> None:
self._errors = errors

4
fastapi/params.py

@ -773,7 +773,9 @@ class Depends:
def __post_init__(self):
if self.scope not in ("lifespan", "request", "function", None):
raise InvalidDependencyScope(f"Dependency received an invalid scope: \"{self.scope}\"")
raise InvalidDependencyScope(
f'Dependency received an invalid scope: "{self.scope}"'
)
@dataclass

20
fastapi/utils.py

@ -7,18 +7,18 @@ from dataclasses import is_dataclass
from typing import (
TYPE_CHECKING,
Any,
Awaitable,
Dict,
MutableMapping,
Optional,
Set,
Type,
TypeVar,
Union,
cast, Awaitable, TypeVar,
cast,
)
from weakref import WeakKeyDictionary
from starlette.concurrency import run_in_threadpool
import fastapi
from fastapi._compat import (
PYDANTIC_V2,
@ -35,7 +35,8 @@ from fastapi._compat import (
from fastapi.datastructures import DefaultPlaceholder, DefaultType
from pydantic import BaseModel
from pydantic.fields import FieldInfo
from typing_extensions import Literal, TypeIs, ParamSpec
from starlette.concurrency import run_in_threadpool
from typing_extensions import Literal, ParamSpec, TypeIs
if TYPE_CHECKING: # pragma: nocover
from .routing import APIRoute
@ -269,7 +270,7 @@ def get_value_or_default(
def _is_coroutine_callable(
callable_: Callable[..., Any]
callable_: Callable[..., Any],
) -> TypeIs[Callable[..., Awaitable[Any]]]:
if inspect.isroutine(callable_):
return iscoroutinefunction(callable_)
@ -278,12 +279,13 @@ def _is_coroutine_callable(
dunder_call = getattr(callable_, "__call__", None) # noqa: B004
return iscoroutinefunction(dunder_call)
async def call_asynchronously(
callable_: Union[Callable[_P, _T], Callable[_P, Awaitable[_T]]],
*args: _P.args,
**kwargs: _P.kwargs
callable_: Union[Callable[_P, _T], Callable[_P, Awaitable[_T]]],
*args: _P.args,
**kwargs: _P.kwargs,
) -> _T:
if _is_coroutine_callable(callable_):
return await callable_(*args, **kwargs)
else:
return await run_in_threadpool(callable_, *args, **kwargs)
return await run_in_threadpool(callable_, *args, **kwargs)

8
tests/test_lifespan_scoped_dependencies/test_dependency_overrides.py

@ -494,9 +494,7 @@ def test_override_lifespan_scoped_dependency_cannot_use_endpoint_scoped_paramete
router=app,
path="/test",
is_websocket=is_websocket,
annotation=Annotated[
None, Depends(dependency_func, scope="lifespan")
],
annotation=Annotated[None, Depends(dependency_func, scope="lifespan")],
)
with pytest.raises(DependencyScopeError):
@ -567,9 +565,7 @@ def test_override_lifespan_scoped_dependency_cannot_use_endpoint_scoped_dependen
router=app,
path="/test",
is_websocket=is_websocket,
annotation=Annotated[
None, Depends(dependency_func, scope="lifespan")
],
annotation=Annotated[None, Depends(dependency_func, scope="lifespan")],
)
app.dependency_overrides[dependency_func] = override_dependency_func

12
tests/test_lifespan_scoped_dependencies/test_endpoint_usage.py

@ -453,9 +453,7 @@ def test_lifespan_scoped_dependency_cannot_use_endpoint_scoped_parameters(
router=app,
path="/test",
is_websocket=is_websocket,
annotation=Annotated[
None, Depends(dependency_func, scope="lifespan")
],
annotation=Annotated[None, Depends(dependency_func, scope="lifespan")],
)
@ -519,7 +517,9 @@ def test_the_same_dependency_can_work_in_different_scopes(
is_websocket=is_websocket,
annotation1=Annotated[
int,
Depends(dependency_factory.get_dependency(), scope=endpoint_dependency_scope),
Depends(
dependency_factory.get_dependency(), scope=endpoint_dependency_scope
),
],
annotation2=Annotated[
int,
@ -659,9 +659,7 @@ def test_lifespan_scoped_dependency_cannot_use_endpoint_scoped_dependencies(
router=app,
path="/test",
is_websocket=is_websocket,
annotation=Annotated[
None, Depends(dependency_func, scope="lifespan")
],
annotation=Annotated[None, Depends(dependency_func, scope="lifespan")],
)

1
tests/test_params_repr.py

@ -1,6 +1,5 @@
from typing import Any, List
import pytest
from dirty_equals import IsOneOf
from fastapi.params import Body, Cookie, Header, Param, Path, Query

Loading…
Cancel
Save