Browse Source
Merge branch 'master' into fix/uploadfile-downcast
pull/13605/head
Motov Yurii
5 months ago
committed by
GitHub
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with
30 additions and
14 deletions
docs/en/docs/release-notes.md
fastapi/dependencies/utils.py
fastapi/exceptions.py
fastapi/routing.py
tests/test_router_circular_import.py
@ -7,6 +7,15 @@ hide:
## 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
* 🔧 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 ).
@ -1,7 +1,7 @@
import dataclasses
import inspect
import sys
from collections . abc import Coroutine , Mapping , Sequence
from collections . abc import Mapping , Sequence
from contextlib import AsyncExitStack , contextmanager
from copy import copy , deepcopy
from dataclasses import dataclass
@ -15,7 +15,6 @@ from typing import (
cast ,
)
import anyio
from fastapi import params
from fastapi . _compat import (
ModelField ,
@ -900,16 +899,8 @@ async def _extract_form_body(
# For types
assert isinstance ( value , sequence_types )
results : list [ Union [ bytes , str ] ] = [ ]
async def process_fn (
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 )
for sub_value in value :
results . append ( await sub_value . read ( ) )
value = serialize_sequence_value ( field = field , value = results )
else :
value = [
@ -1,4 +1,4 @@
from collections . abc import Sequence
from collections . abc import Mapping , Sequence
from typing import Annotated , Any , Optional , TypedDict , Union
from annotated_doc import Doc
@ -68,7 +68,7 @@ class HTTPException(StarletteHTTPException):
) ,
] = None ,
headers : Annotated [
Optional [ dict [ str , str ] ] ,
Optional [ Mapping [ str , str ] ] ,
Doc (
"""
Any headers to send to the client in the response .
@ -1393,6 +1393,10 @@ class APIRouter(routing.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 :
assert prefix . startswith ( " / " ) , " A path prefix must start with ' / ' "
assert not prefix . endswith ( " / " ) , (
@ -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 )