Browse Source

Merge branch 'master' into fix/uploadfile-downcast

pull/13605/head
Motov Yurii 5 months ago
committed by GitHub
parent
commit
27846b1b51
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 9
      docs/en/docs/release-notes.md
  2. 15
      fastapi/dependencies/utils.py
  3. 4
      fastapi/exceptions.py
  4. 4
      fastapi/routing.py
  5. 12
      tests/test_router_circular_import.py

9
docs/en/docs/release-notes.md

@ -7,6 +7,15 @@ hide:
## Latest Changes ## Latest Changes
### Features
* ✨ Show a clear error on attempt to include router into itself. PR [#14258](https://github.com/fastapi/fastapi/pull/14258) by [@JavierSanchezCastro](https://github.com/JavierSanchezCastro).
* ✨ Replace `dict` by `Mapping` on `HTTPException.headers`. PR [#12997](https://github.com/fastapi/fastapi/pull/12997) by [@rijenkii](https://github.com/rijenkii).
### Refactors
* ♻️ Simplify reading files in memory, do it sequentially instead of (fake) parallel. PR [#14884](https://github.com/fastapi/fastapi/pull/14884) by [@tiangolo](https://github.com/tiangolo).
### Internal ### Internal
* 🔧 Configure `test` workflow to run tests with `inline-snapshot=review`. PR [#14876](https://github.com/fastapi/fastapi/pull/14876) by [@YuriiMotov](https://github.com/YuriiMotov). * 🔧 Configure `test` workflow to run tests with `inline-snapshot=review`. PR [#14876](https://github.com/fastapi/fastapi/pull/14876) by [@YuriiMotov](https://github.com/YuriiMotov).

15
fastapi/dependencies/utils.py

@ -1,7 +1,7 @@
import dataclasses import dataclasses
import inspect import inspect
import sys import sys
from collections.abc import Coroutine, Mapping, Sequence from collections.abc import Mapping, Sequence
from contextlib import AsyncExitStack, contextmanager from contextlib import AsyncExitStack, contextmanager
from copy import copy, deepcopy from copy import copy, deepcopy
from dataclasses import dataclass from dataclasses import dataclass
@ -15,7 +15,6 @@ from typing import (
cast, cast,
) )
import anyio
from fastapi import params from fastapi import params
from fastapi._compat import ( from fastapi._compat import (
ModelField, ModelField,
@ -900,16 +899,8 @@ async def _extract_form_body(
# For types # For types
assert isinstance(value, sequence_types) assert isinstance(value, sequence_types)
results: list[Union[bytes, str]] = [] results: list[Union[bytes, str]] = []
for sub_value in value:
async def process_fn( results.append(await sub_value.read())
fn: Callable[[], Coroutine[Any, Any, Any]],
) -> None:
result = await fn()
results.append(result) # noqa: B023
async with anyio.create_task_group() as tg:
for sub_value in value:
tg.start_soon(process_fn, sub_value.read)
value = serialize_sequence_value(field=field, value=results) value = serialize_sequence_value(field=field, value=results)
else: else:
value = [ value = [

4
fastapi/exceptions.py

@ -1,4 +1,4 @@
from collections.abc import Sequence from collections.abc import Mapping, Sequence
from typing import Annotated, Any, Optional, TypedDict, Union from typing import Annotated, Any, Optional, TypedDict, Union
from annotated_doc import Doc from annotated_doc import Doc
@ -68,7 +68,7 @@ class HTTPException(StarletteHTTPException):
), ),
] = None, ] = None,
headers: Annotated[ headers: Annotated[
Optional[dict[str, str]], Optional[Mapping[str, str]],
Doc( Doc(
""" """
Any headers to send to the client in the response. Any headers to send to the client in the response.

4
fastapi/routing.py

@ -1393,6 +1393,10 @@ class APIRouter(routing.Router):
app.include_router(internal_router) app.include_router(internal_router)
``` ```
""" """
assert self is not router, (
"Cannot include the same APIRouter instance into itself. "
"Did you mean to include a different router?"
)
if prefix: if prefix:
assert prefix.startswith("/"), "A path prefix must start with '/'" assert prefix.startswith("/"), "A path prefix must start with '/'"
assert not prefix.endswith("/"), ( assert not prefix.endswith("/"), (

12
tests/test_router_circular_import.py

@ -0,0 +1,12 @@
import pytest
from fastapi import APIRouter
def test_router_circular_import():
router = APIRouter()
with pytest.raises(
AssertionError,
match="Cannot include the same APIRouter instance into itself. Did you mean to include a different router?",
):
router.include_router(router)
Loading…
Cancel
Save