mirror of https://github.com/tiangolo/fastapi.git
Merge branch 'master' into fix/uploadfile-downcast
This commit is contained in:
commit
27846b1b51
|
|
@ -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)
|
||||
Loading…
Reference in New Issue